Deploy Docker To Digitalocean Droplet

Deploy Docker To Digitalocean Droplet

Reading time1 min
#Cloud#DevOps#Containers#Docker#DigitalOcean#Droplets

Streamlined Docker Deployment: DigitalOcean Droplets for Production-Grade Containers

Modern teams need deployment strategies that don’t introduce unnecessary complexity. DigitalOcean droplets, coupled with Docker, provide a straightforward, cost-conscious backbone for small-scale production workloads or staging environments. This guide emphasizes the real-world practices: less theory, more sustained operation.


When Container Management Should Stay Simple

Orchestration platforms like Kubernetes shine at scale but introduce overhead. For single-service apps or lightweight projects, DigitalOcean droplets with Docker hit a pragmatic balance—root-level access, tight resource control, and rapid recovery via droplet snapshots. The result: lean deployments, minimal latency.


Baselines

Before proceeding, ensure the following:

  • DigitalOcean account with billing set up
  • SSH keypair registered (see “Security Shortcuts” below)
  • CLI access (macOS/Linux: ssh; Windows: WSL or PuTTY; or try DigitalOcean’s web console)
  • Docker CLI installed locally (for building and pushing images; not strictly required on the droplet)

1. Provision the Droplet

ParameterRecommendation
ImageUbuntu 22.04 LTS
Plan1 vCPU, 1GB RAM ($5/mo)
Data CenterChoose per user geo
SSH KeyAlways use; avoid passwords

From the control panel, select Create > Droplet. Assign your SSH key. After provisioning, a public IPv4 will be shown—this is your jump point.


2. SSH Access: First Principles

Default root login is enabled on new droplets.

ssh root@<DROPLET_IP>

If you see Permission denied (publickey), troubleshoot with ssh -vvv root@<DROPLET_IP>. Misconfigured keys or disabled agent forwarding are typical causes.

Gotcha: DigitalOcean assigns regular root shell; harden with a non-root user post-setup if intended for long-living environments.


3. Docker Installation (Ubuntu 22.04)

Install latest Docker packages—avoid snap and OS repos (they lag).

apt-get update && apt-get install -y \
  ca-certificates curl gnupg lsb-release

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Check status:

docker info | grep 'Server Version'

Known issue: If systemctl status docker shows failed, check /var/log/syslog for overlay filesystem errors. Sometimes, resizing the droplet resolves initialization hangs.


4. Sanity Check: Hello World

Confirm a functioning Docker daemon.

docker run --rm hello-world

Expected output (truncated):

Hello from Docker!
This message shows that your installation appears to be working correctly.

If you see:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock

check that the daemon is running (systemctl restart docker).


5. Ship Your Own Containers

Assume an example Node.js application:

Dockerfile:

FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Note: npm ci --omit=dev skips devDependencies—vital for minimizing image size in production.

Build and publish from your workstation (Docker Hub example):

docker build -t yourrepo/myapp:2024.06.12 .
docker push yourrepo/myapp:2024.06.12

Tag with date/version for traceable deployments. Avoid latest except in test loops.


6. Retrieve & Run on Droplet

On the droplet, pull the image:

docker pull yourrepo/myapp:2024.06.12

Deploy:

docker run -d --name myapp -p 80:3000 --restart=unless-stopped yourrepo/myapp:2024.06.12

Access at http://<DROPLET_IP>. If port 80 is in use, substitute above (e.g., -p 8080:3000).

Trade-off: Mapping container’s app port to 80 bypasses the need for nginx/traefik, but limits flexibility for multi-app hosting.


7. Compose: Multiple Containers Without Orchestration Bloat

For stateful/multi-service apps, docker-compose supports consistent, easy setups.

docker-compose.yml:

version: '3.8'
services:
  web:
    image: yourrepo/myapp:2024.06.12
    ports: ["80:3000"]
    restart: unless-stopped
    environment:
      NODE_ENV: production
  db:
    image: postgres:15.4-alpine
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: example_pw
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Start all:

docker compose up -d

Remember: Volumes mounted only exist on this droplet. Data persistence is not “cloud native” here unless bound to external storage or periodically snapshotted.


8. Security & Maintenance

  • Firewall: Harden ingress rules. Shortest path:
ufw allow ssh
ufw allow http
ufw allow https
ufw enable
  • User Management: For long-term hosts, add a sudo user; disable root SSH:
adduser deployer
usermod -aG docker deployer
  • Logs/Monitoring: docker logs myapp for quick check; deploy docker events or integrate promtail to centralize logs for production.
  • Image Refresh: Schedule a service (cron, GitHub Actions CI) to pull fresh images—even on single-server setups, drift leads to issues.

Non-Obvious: Zero Downtime Container Restarts (No Orchestrator)

Performing live deployments:

docker pull yourrepo/myapp:2024.06.13
docker run -d --name myapp-v2 -p 8080:3000 --restart=unless-stopped yourrepo/myapp:2024.06.13
# Wait for healthcheck, then swap iptables/nginx mapping, or adjust DNS if using internal LB.
docker stop myapp && docker rm myapp
docker rename myapp-v2 myapp

This approach minimizes downtime without full orchestration.


Side Notes

  • Snapshots: Use DigitalOcean’s droplet snapshots for rollback; there is a lag of several minutes.
  • Secrets management: Avoid embedding secrets in images; pass as environment variables or mount via secrets volume (manual on single droplets).
  • Persistent data: Leverage DigitalOcean Volumes if database durability is critical.

Conclusion

For projects where Kubernetes is excessive but manual deployment is too brittle, Docker with DigitalOcean droplets strikes a usable middle ground. With these real-world workflows, expect predictable deployments and simpler rollbacks—provided operational hygiene is maintained.

Alternatives: DigitalOcean App Platform abstracts even further but at the cost of less granular control.

On constrained budgets or when hands-on access is essential, this is a sensible, maintainable deployment baseline.


Questions on more advanced multi-node setups, HA proxies, or GitOps flows? Comments open.