Skip to content
-
Subscribe to our newsletter & never miss our best posts. Subscribe Now!
Devnix Blog

Tech Trends, Software Engineering & Cloud Insights

Devnix Blog

Tech Trends, Software Engineering & Cloud Insights

  • Home
  • Privacy Policy
  • Home
  • Privacy Policy
Close

Search

Subscribe
Docker Compose Deployment

Step‑by‑Step Guide to Build a CI/CD Pipeline with Docker, Nginx, and GitHub Actions on a Linux VPS

By Devnix
May 30, 2026 1 Min Read
0


Step‑by‑Step Guide to Build a CI/CD Pipeline with Docker, Nginx, and GitHub Actions on a Linux VPS

Modern web services need fast, reliable, and repeatable deployments. Manually pulling code, rebuilding containers, and updating the web server is error‑prone and slows down delivery. This tutorial shows how to automate the entire workflow: a Docker‑based application, an Nginx reverse proxy, and a GitHub Actions pipeline that pushes new releases straight to a Linux VPS.

Prerequisites

  • A fresh Linux VPS (Ubuntu 22.04 LTS recommended) with root or sudo access.
  • Basic familiarity with ssh, Git, and Docker concepts.
  • A GitHub repository containing the source code you want to deploy.
  • Domain name pointing to your VPS IP (optional but recommended for Nginx TLS).

1. Install Docker Engine and Docker Compose

Docker isolates your application and its dependencies, while Docker Compose orchestrates multi‑container setups.

# Update package index
sudo apt-get update

# Install required packages
sudo apt-get install -y ca-certificates curl gnupg lsb-release

# Add Docker’s official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

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

# Install Docker Engine and Compose plugin
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Verify installation
docker version
docker compose version

2. Create a Sample Node.js Application

For illustration we’ll use a minimal Express server.

# On your local machine
mkdir myapp && cd myapp
git init

# package.json
cat > package.json <<'EOF'
{
  "name": "myapp",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}
EOF

# index.js
cat > index.js <<'EOF'
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.send('Hello from Dockerized Node.js!');
});

app.listen(port, () => {
  console.log(`App listening on port ${port}`);
});
EOF

# Install dependencies
npm install

# Commit to GitHub (replace URL with your repo)
git add .
git commit -m "Initial commit"
git remote add origin git@github.com:youruser/yourrepo.git
git push -u origin master

3. Write a Dockerfile

The Dockerfile builds a lightweight image based on node:18-alpine.

# Dockerfile
FROM node:18-alpine

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package*.json ./
RUN npm ci --only=production

# Bundle source code
COPY . .

# Expose port 3000 (the internal container port)
EXPOSE 3000

# Run the application
CMD [ "npm", "start" ]

4. Define docker‑compose.yml

Docker Compose will spin up the app container and a small watchtower service that auto‑updates images when a new version is pushed.

# docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    container_name: myapp
    restart: unless-stopped
    environment:
      - NODE_ENV=production
    ports:
      - "127.0.0.1:3000:3000"   # Bind to localhost; Nginx will expose publicly
    networks:
      - appnet

  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --interval 30 myapp
    networks:
      - appnet

networks:
  appnet:
    driver: bridge

5. Set Up Nginx as a Secure Reverse Proxy

Nginx will listen on port 80 (or 443 with TLS) and forward traffic to the Docker container listening on 127.0.0.1:3000. This separation keeps the container isolated from the public internet.

# Install Nginx
sudo apt-get install -y nginx

# Create a new server block
sudo tee /etc/nginx/sites-available/myapp.conf > /dev/null <<'EOF'
server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EOF

# Enable the configuration
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

For HTTPS, obtain a free certificate with certbot (not covered here) and adjust the listen directive to 443 ssl.

6. Create a GitHub Actions Workflow for CI/CD

The workflow builds the Docker image, pushes it to the VPS via SSH, and triggers a container restart.

# .github/workflows/deploy.yml
name: Deploy to VPS

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Log in to VPS (SSH)
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /opt/myapp
            git pull origin main
            docker compose pull
            docker compose up -d --build

Store VPS_HOST, VPS_USER, and VPS_SSH_KEY as encrypted GitHub secrets. The script assumes the repository has already been cloned to /opt/myapp on the VPS.

7. Deploy the Stack to Your Cloud VPS

Now that the pipeline is ready, clone the repository onto the server, start the stack, and let GitHub Actions handle future releases.

# SSH into your VPS
ssh youruser@your-vps-ip

# Create a directory for the project
sudo mkdir -p /opt/myapp
sudo chown $USER:$USER /opt/myapp
cd /opt/myapp

# Clone the repo
git clone git@github.com:youruser/yourrepo.git .
# Initial Docker Compose up
docker compose up -d --build

At this point the application is reachable via your domain name, and every push to main will automatically rebuild and redeploy the container. For a production‑grade environment you can rely on DevNix Cloud VPS to provide the underlying compute, SSD storage, and network performance required for a smooth CI/CD workflow.

Conclusion

By combining Docker, Nginx, and GitHub Actions you achieve a repeatable, zero‑downtime deployment pipeline that scales with your codebase. The VPS acts as a lightweight, cost‑effective host, while the CI/CD process guarantees that every commit is tested, built, and pushed without manual intervention. Extend this foundation with automated TLS renewal, health‑check monitoring, or a more sophisticated orchestrator like Kubernetes when your traffic grows.

Tags:

CI/CD pipelinedocker deploymentGitHub ActionsLinux VPSnginx reverse proxy
Author

Devnix

Follow Me
Other Articles
Previous

Step‑by‑Step Guide to Automate Daily MySQL Backups on a Linux VPS

Next

Step‑by‑Step Guide to Install and Configure WireGuard VPN on a Linux VPS

No Comment! Be the first one.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • WordPress Image Optimization: Native Settings vs Plugins vs CDN vs Server‑Side Solutions
  • Understanding Database Connection Pooling in Cloud Deployments
  • Odoo User Access Rights Audit Checklist – Secure Your ERP Without Over‑Privileging
  • WordPress Caching Showdown: Built‑In, Plugins, Server‑Side, or CDN?
  • Cloud VPS vs Managed WordPress Hosting vs Static Site Hosting: Which Platform Delivers the Best Uptime and Security for Small‑Business Websites?

Archives

  • June 2026
  • May 2026

Categories

  • Backup Strategies
  • Cloud VPS Performance
  • Docker Compose Deployment
  • Odoo Email Configuration
  • Odoo Inventory
  • Odoo Invoicing
  • Odoo Multi-Company Configuration
  • Odoo Subscriptions
  • Odoo User Management
  • Server Security
  • WordPress Migration
  • WordPress Performance Optimization

About Devnix Blog

A forward-thinking tech publication covering software engineering, cloud infrastructure, and modern digital transformation. Built for developers and tech enthusiasts.

Our Services

  • Cloud VPS Hosting
  • Managed ERP Solutions
  • DevOps Automation
  • Server Security & Optimization

Partners

  • Odoo Stack
  • Odoo Backup
  • Devnix Solutions
Copyright 2026 — Devnix Blog. All rights reserved. Devnix Solutions