HomeAboutServices PortfolioCase Studies IndustriesCareers FAQ BlogContact 📅 Book a Call Get Free Quote
← Back to Blog

Docker + Nginx + GitHub Actions: Complete CI/CD Setup

A production-ready CI/CD pipeline is no longer a luxury reserved for large engineering teams. With Docker, Nginx, and GitHub Actions, you can set up automated build, test, and deploy on a small VPS in an afternoon. This is the exact setup we use at Digi Innovative Solutions for client projects.

Prerequisites: A Linux VPS (Ubuntu 22.04 or AlmaLinux 9), a domain name, Docker and Docker Compose installed, and a GitHub repository.

Architecture Overview

architectureGitHub Push -> GitHub Actions -> Build Docker Image -> Run Tests -> Push to GitHub Container Registry (GHCR) -> SSH into VPS -> docker compose pull && up -d --force-recreate VPS: Nginx (port 443) -> Docker container (app:3000)

The Dockerfile

Use multi-stage builds to keep the production image small:

dockerfileFROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY --from=builder /app/.next ./.next COPY --from=builder /app/node_modules ./node_modules EXPOSE 3000 CMD ["npm", "start"]

Docker Compose Setup

yamlversion: "3.9" services: app: image: ghcr.io/your-org/your-app:latest restart: unless-stopped env_file: .env expose: ["3000"] db: image: postgres:16-alpine restart: unless-stopped volumes: [pgdata:/var/lib/postgresql/data] env_file: .env volumes: pgdata:

Nginx Reverse Proxy Config

nginxserver { listen 443 ssl http2; server_name yourdomain.com; ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

GitHub Actions Workflow

yamlname: Deploy to Production on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/${{ github.repository }}:latest - uses: appleboy/ssh-action@v1 with: host: ${{ secrets.VPS_HOST }} username: root key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd /opt/myapp docker compose pull docker compose up -d --force-recreate docker system prune -f

SSL with Let's Encrypt

bash# AlmaLinux/RHEL dnf install -y certbot python3-certbot-nginx certbot --nginx -d yourdomain.com -d www.yourdomain.com # Certificates auto-renew via systemd timer

With this setup, every git push to main automatically builds, tests, and deploys your app in 3-5 minutes with zero downtime. This is the baseline DevOps setup we implement for all client projects.

Ready to apply these strategies?

Need a production-ready CI/CD pipeline? Our DevOps team sets up automated deployment end-to-end.

Get a Free Consultation →
💬