MarzleyTech Learn

Home / Learn / DevOps & cloud: from zero to deploying and running real systems / Project: deploy a real web app with Docker, Nginx, HTTPS and automatic deploys

Project: deploy a real web app with Docker, Nginx, HTTPS and automatic deploys

Time to put it all together. In this project you deploy a small web app to a cloud server the way professionals do: containers, a reverse proxy, HTTPS, a CI/CD pipeline and backups. It's an excellent portfolio piece.

What you'll build

TEXT
GitHub repo ──push──► GitHub Actions (test, build image) ──► registry
                                                            │
                                         server pulls new image and restarts
                                                            ▼
Users ──HTTPS──► Nginx (reverse proxy, Let's Encrypt) ──► app container ──► database container (volume)
                                                                            │
                                                                nightly backup → object storage

What you need

  • A small cloud server (VPS) with Ubuntu: from a big cloud's free tier or a VPS provider. Some Kenyan hosting companies also offer VPS plans billed in shillings.
  • A domain name (see domains).
  • A GitHub account.
  • An app: any small Node, Python or PHP app (or one from the projects subject).

Step 1: prepare the server

Follow the checklist from Linux servers for DevOps: SSH keys, a deploy user, updates, firewall (22, 80, 443). Then install Docker:

Terminal
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker deploy    # log out and in again

Step 2: containerise the app

Write a Dockerfile and compose.yaml like in the Docker lesson. Test locally: docker compose up -d, open the app in your browser.

Step 3: point the domain

Create an A record for app.yourdomain.co.ke pointing to the server's public IP. DNS changes can take minutes to hours.

Step 4: Nginx as a reverse proxy with HTTPS

Install Nginx and Certbot on the server:

Terminal
sudo apt install -y nginx certbot python3-certbot-nginx
NGINX
# /etc/nginx/sites-available/app
server {
    server_name app.yourdomain.co.ke;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
Terminal
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d app.yourdomain.co.ke     # free HTTPS certificate, auto-renews

In compose.yaml, publish the app only on localhost ("127.0.0.1:3000:3000") so it's reachable through Nginx, not directly from the internet.

Step 5: automatic deploys

In GitHub Actions (see CI/CD):

  1. On every push to main: run tests.
  2. Build the image and push it to GitHub Container Registry, tagged with the commit ID.
  3. SSH into the server and run:
Terminal
cd /home/deploy/app
docker compose pull
docker compose up -d
docker image prune -f

Store the SSH key and server address as repository secrets.

Step 6: backups

Terminal
# /home/deploy/backup.sh (run nightly with cron)
docker compose exec -T db mysqldump -u root -p"$DB_ROOT_PASSWORD" shop | gzip > /home/deploy/backups/shop-$(date +%F).sql.gz
find /home/deploy/backups -name "*.sql.gz" -mtime +14 -delete

Copy backups off the server too (object storage or another location). Test restoring a backup at least once; a backup you can't restore isn't a backup.

Step 7: monitoring

  • An uptime monitor that alerts you when the site is down (many have free plans).
  • Check docker compose logs, disk space and memory regularly (next lesson covers proper monitoring).

Document it for your portfolio

Write a README with: the architecture diagram, what each part does, how to deploy, how backups work, and what you'd improve. Link it on your CV and LinkedIn.

Think about it: After deploying, the site works over HTTP but HTTPS fails. What would you check?Show answer

Check the DNS A record points to the server, port 443 is open in both UFW and the cloud firewall, Certbot completed without errors, the Nginx config passes nginx -t and was reloaded, and the server_name matches the domain exactly. Then check Nginx error logs.

Summary

  • Prepare a hardened server, install Docker and containerise your app.
  • Point a domain, put Nginx in front as a reverse proxy and add free HTTPS with Certbot.
  • Automate deploys with GitHub Actions and a container registry.
  • Back up nightly, store copies off the server, test restores and add uptime monitoring.

Check yourself

  1. Which tool gets free Let's Encrypt HTTPS certificates for Nginx? (one word)

    Show answer

    certbot

  2. Which Nginx command tests the configuration before reloading? (write like nginx -t)

    Show answer

    nginx -t

  3. Is a backup useful if you've never tested restoring it? (yes or no)

    Show answer

    no

Lesson 10 of 14 in DevOps & cloud: from zero to deploying and running real systems · Written by · Course notes