News & Updates

Nginx, Docker Compose & DigitalOcean: A Simple Guide to Modern Web Deployment

By Erica Hollis 14 min read 3022 views

Nginx, Docker Compose & DigitalOcean: A Simple Guide to Modern Web Deployment

Deploying a web application today means juggling multiple tools. Nginx is a lightweight reverse proxy and web server, Docker Compose lets you orchestrate containers locally or in the cloud, and DigitalOcean provides an affordable, scalable infrastructure. Together they form a powerful stack that is both simple to set up and robust in production. This guide walks through each component, shows how to stitch them together with Docker Compose, and explains how to push the stack onto a DigitalOcean droplet.

Why Combine Nginx, Docker Compose & DigitalOcean?

Each tool solves a common pain point:

  • Docker Compose abstracts container configuration into a single YAML file.
  • Nginx handles SSL termination, load balancing, and static file serving with minimal overhead.
  • DigitalOcean offers preconfigured droplets, managed databases, and a user‑friendly API that fits well with containerized workloads.

When you stack them, you get a reproducible deployment pipeline: local Compose tests, container images pushed to a registry, and a clean, scalable production environment.

Step‑by‑Step Setup

1. Prepare Your Local Project

Assume you have a Node.js app named app. Create a Dockerfile in the root:

FROM node:18-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node","index.js"]

In the same directory, add a minimal docker-compose.yml that also defines an Nginx service:

version: "3.8"
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
nginx:
image: nginx:alpine
depends_on:
- web
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "80:80"
- "443:443"

2. Create the Nginx Configuration

In nginx.conf, point requests to the Node container:

server {
listen 80;
server_name example.com;
location / {
proxy_pass http://web:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Optional: Serve static assets from /public
location /public {
root /usr/src/app;
try_files $uri $uri/ =404;
}
}

For SSL, you can generate certificates with certbot or use DigitalOcean’s managed certificates. Place them in a certs folder and mount the volumes in Compose.

3. Test Locally

Run:

docker compose up --build

Visit http://localhost. You should see your Node app served through Nginx. Stop the stack with Ctrl+C and docker compose down.

4. Build Container Images

For production, tag the images and push them to a registry:

docker build -t registry.digitalocean.com/yourorg/app:latest .
docker push registry.digitalocean.com/yourorg/app:latest

Do the same for the Nginx image if you plan to customize it. Otherwise, keep using the official nginx:alpine image.

5. Spin Up a DigitalOcean Droplet

Use the doctl CLI or the web console:

  • Create a 2‑GB droplet (Ubuntu 24.04). Enable IPv6 if you need it.
  • Set up SSH keys for secure access.
  • Allocate a floating IP if you want a stable address.

6. Install Docker and Docker Compose on the Droplet

SSH into the droplet and run:

sudo apt update && sudo apt install -y docker.io docker-compose
sudo usermod -aG docker $USER

Log out and back in to apply group changes.

7. Deploy with Docker Compose

On the droplet, clone your repo or copy the docker-compose.yml and related files. Edit the server_name in nginx.conf to match your domain. Then run:

docker compose pull
docker compose up -d

Nginx will now serve your application, handling HTTPS if you added the certificates. Check the logs with docker compose logs -f nginx to verify no errors.

8. Automate Future Updates

  • Use Docker Hub webhooks or a CI pipeline (GitHub Actions, GitLab CI) to build and push images on every commit.
  • Add a docker compose.yml section that pulls the latest tag.
  • Set up docker compose pull && docker compose up -d as a script, and use systemd or supervisord to restart it on boot.

Common Pitfalls and Fixes

  • Port conflicts: Ensure the droplet’s firewall allows ports 80 and 443. On Ubuntu, enable them with ufw allow 'Nginx Full'.
  • File ownership: Nginx inside a container might not read files owned by root. Mount volumes with :ro and set proper permissions in the image.
  • DNS propagation: After pointing your domain to the droplet’s IP, it can take up to 48 hours for changes to propagate fully.
  • Scaling: For high traffic, add a second web service instance and let Nginx load‑balance between web1 and web2 using the upstream directive.

Optional: Use DigitalOcean Managed Database

If your app relies on a database, consider DigitalOcean’s Managed Database service. Export the connection string as an environment variable and mount it in the web service’s environment section. This keeps your database credentials out of Docker Hub and reduces maintenance overhead.

FAQs

Q: Can I use a single docker-compose.yml for both development and production?
A: Yes, but you should parameterize environment variables and use different docker-compose.override.yml files to adjust settings like logging levels or database URLs.

Q: What if I want to use Docker Swarm instead of Compose on DigitalOcean?
A: Swarm provides built‑in load balancing and scaling

Comment utiliser Docker Compose : guide complet et exemples
How to Dockerize a NodeJS app? (With Typescript, Nginx, and Docker ...
Comprehensive Guide: Setting Up a VPS with DigitalOcean, Configuring ...
sadomovalex's blog: Use nginx running in Docker container to serve .NET ...

Written by Erica Hollis

Erica Hollis is a News Correspondent covering technology, society, and the changing landscape of everyday life. Her work explores the connections between innovation and public interest, translating complex developments into accessible reporting while examining their opportunities, challenges, and lasting effects.


You Might Like