Terug na blog
Augustus 19, 2026Gidse

Hoe om toepassings met Docker Compose op 'n VPS te ontplooi

'n Praktiese produksiegids tot Docker Compose v2 op Ubuntu: installeer die enjin, skryf 'n Compose-lêer met netwerke en volumes, hanteer geheime, sit 'n reverse proxy voor, dateer op met nul-paniek-uitrol, en rugsteun genoemde volumes.

Hoe om toepassings met Docker Compose op 'n VPS te ontplooi

Docker Compose is die gewone manier om 'n klein stapel op een VPS te laat loop: 'n webtoepassing, 'n databasis, 'n Redis-kas, en 'n reverse proxy, beskryf in een YAML-lêer. Dit is nie Kubernetes nie. Jy sal nie multi-node-oorname kry nie. Jy sal 'n herhaalbare, hersienbare opstelling kry wat jy binne minute op 'n nuwe Hiddence-VPS kan herskep — juis wat die meeste syprojekte en klein produkte nodig het.

Hierdie artikel aanvaar jy wil iets nader aan produksie hê as docker run op 'n Vrydagaand. Ons installeer Docker Engine en die Compose-inprop, skep 'n nie-root ontplooi-gebruiker, skryf 'n Compose-lêer met gesondheidskontroles en herbeginbeleide, hou geheime uit Git, publiseer slegs die reverse-proxy-poorte na die internet, en definieer 'n opdaterings- en rugsteunroetine. Die voorbeeldstapel is 'n tipiese webtoepassing plus PostgreSQL plus Caddy, maar dieselfde patroon werk vir Node, PHP, Python, of 'n klomp werkers.

Hoekom Compose op 'n enkele VPS steeds sin maak

Mense spring na Kubernetes omdat dit modes is, en spandeer dan die naweek aan YAML vir een webwerf. Compose bly leesbaar. Jy weergawes die lêer, jy dokumenteer omgewingsveranderlikes, en jy kan 'n verandering diff voordat jy dit toepas. Isolasie is goed genoeg: 'n gekompromitteerde toepassinghouer behoort nie die databasis se UNIX-soket te hou as jy netwerke en minste-voorreg-gebruikers gebruik het nie. Hulpbronlimiete keer dat een geheuelek die hele VPS vries.

  • Een lêer beskryf die hele stapel
  • Genoemde volumes oorleef houerherskepping
  • Interne Docker-netwerke hou Postgres van die publieke internet af
  • restart: unless-stopped dek die meeste herbeginne
  • Maklik om na 'n tweede VPS te kopieer wanneer jy die eerste ontgroei

Vereistes

Gebruik 'n VPS met genoeg RAM vir die toepassing plus Postgres. 'n 2 GB-plan is 'n realistiese minimum vir toepassing + databasis + proxy. Ubuntu 24.04 word aanvaar. Moenie Docker vanaf 'n ewekansige Snap installeer sonder om te lees wat dit aan cgroups doen nie; die stappe hieronder gebruik Docker se amptelike apt-bewaarplek.

  • Ubuntu 22.04/24.04, root of sudo
  • 2 GB RAM aanbeveel (1 GB slegs vir piepklein stapels sonder Postgres)
  • 'n Domein wat na die VPS wys as jy outomatiese HTTPS wil hê
  • Git of 'n ander manier om die projek na die bediener te kopieer

Stap 1: Installeer Docker Engine en Compose v2

Compose v2 is 'n inprop wat as docker compose (met 'n spasie) aangeroep word, nie die ou docker-compose Python-binêre nie. Installeer albei vanaf Docker se bewaarplek sodat jy huidige sekuriteitskolle kry.

bash
ssh root@YOUR_VPS_IP
apt update && apt -y install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

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

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

docker version
docker compose version

Stap 2: Ontplooi-gebruiker en gidsuitleg

Om Compose as root te laat loop werk, maar 'n toegewyde gebruiker met lidmaatskap in die docker-groep is skoner. Sit die projek in /opt of /srv, nie in /root nie, sodat rugsteune en toestemmings duidelik is. Moet nooit die gids wat .env bevat wêreld-skryfbaar maak nie.

bash
adduser --disabled-password --gecos '' deploy
usermod -aG docker deploy
mkdir -p /srv/app
chown deploy:deploy /srv/app
chmod 750 /srv/app

# Log in as deploy for the rest of the file editing:
# su - deploy
# cd /srv/app

Stap 3: Skryf 'n produksie-ingestelde Compose-lêer

Die lêer hieronder is 'n sjabloon. Vervang die toepassingbeeld met joune. Postgres word nie na 0.0.0.0:5432 gepubliseer nie — slegs Caddy word op 80 en 443 gepubliseer. Gesondheidskontroles keer dat 'n reverse proxy verkeer stuur na 'n toepassing wat nog die databasis migreer. Pin beeldetikette; latest is hoe verrassingsbreuke gebeur.

bash
# /srv/app/compose.yaml
services:
  caddy:
    image: caddy:2.8-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      app:
        condition: service_healthy

  app:
    image: ghcr.io/example/webapp:1.4.2
    restart: unless-stopped
    env_file: .env
    environment:
      DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health"]
      interval: 10s
      timeout: 3s
      retries: 10
    networks:
      - frontend
      - backend

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    env_file: .env
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - backend

networks:
  frontend: {}
  backend: {}

volumes:
  pgdata:
  caddy_data:
  caddy_config:

Stap 4: Geheime, .env en Caddyfile

Sit wagwoorde in .env op die bediener, chmod 600, en commit nooit daardie lêer nie. Genereer wagwoorde met openssl rand -base64 32. Die Caddyfile hoef slegs na die toepassing se diensnaam op die Docker-netwerk te reverse-proxy.

bash
# /srv/app/.env (permissions 600)
POSTGRES_USER=app
POSTGRES_PASSWORD=change-me-long-random
POSTGRES_DB=app
# plus any APP_SECRET / NEXTAUTH_SECRET your image needs

# /srv/app/Caddyfile
app.example.com {
    encode gzip
    reverse_proxy app:8000
}

chmod 600 /srv/app/.env
cd /srv/app
docker compose up -d
docker compose ps
docker compose logs -f --tail=100

Stap 5: Firewall, logboeke en hulpbronlimiete

UFW moet slegs 22, 80 en 443 toelaat. Docker omseil soms UFW vir gepubliseerde poorte; as jy 'n streng gasheer-firewall nodig het, soek die huidige Docker + UFW-wisselwerking vir jou Ubuntu-weergawe op, of publiseer poorte slegs op 127.0.0.1 en sit 'n gasheer-Caddy voor. Stel geheuelimiete in Compose sodat Postgres nie die VPS kan opeet nie.

bash
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

# Optional in compose.yaml under app or db:
#    deploy:
#      resources:
#        limits:
#          memory: 512M

# Logs (do not let json-file grow forever):
# { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }
# in /etc/docker/daemon.json then: systemctl restart docker

Stap 6: Opdaterings en terugrol

Die vervelige opdatering wat werk: trek nuwe beelde, up -d, dophou gesondheidskontroles, hou die vorige etiket in git sodat jy terug kan pin. Moenie docker compose down op 'n produksiedatabasis doen nie tensy jy van plan is om verkeer te stop. down -v vee volumes uit — dit is 'n uitvee, nie 'n herbegin nie.

bash
cd /srv/app
git pull   # if the Compose file lives in git

# Change the image tag in compose.yaml, then:
docker compose pull
docker compose up -d
docker compose ps

# Rollback: set the old tag, pull, up -d again
# NEVER: docker compose down -v   # this deletes named volumes

Rugsteun genoemde volumes

'n VPS-momentopname is goed. 'n Logiese Postgres-dump is beter as jy op 'n ander masjien moet herstel. Skeduleer dit met cron. Toets 'n herstel een keer, anders het jy nie rugsteune nie — jy het lêers wat jy hoop rugsteune is.

bash
# Postgres dump while the db container is running:
docker compose exec -T db pg_dump -U app app | gzip > /var/backups/app-$(date +%F).sql.gz

# Copy off-box
# scp /var/backups/app-*.sql.gz backup-host:~

# Restore sketch (maintenance window):
# gunzip -c app-2026-08-19.sql.gz | docker compose exec -T db psql -U app app

Foutopsporing

Lees docker compose ps en docker compose logs service. Beeldtrek-mislukkings is gewoonlik ghcr/docker hub-tempolimiete of 'n private beeld sonder 'n aanmelding. 502 vanaf Caddy beteken die toepassing is nie gesond nie of die proxy-gasheernaam is verkeerd (gebruik die Compose-diensnaam, nie localhost nie, van binne die Caddy-houer). Toestemmingfoute op volumes beteken dikwels die beeld loop as uid 1000 terwyl die gasheergids root is.

  • compose: command not found — jy het die ou binêre naam geïnstalleer; gebruik docker compose
  • poort is al toegeken — iets anders besit 80/443 (Apache, Nginx, 'n ander Caddy)
  • databasisverbinding geweier — toepassing het begin voordat Postgres gereed was; gebruik healthcheck + depends_on-voorwaarde
  • skyf vol — docker system df, dan prune ongebruikte beelde versigtig
  • toestemming geweier op docker.sock — gebruiker nie in docker-groep nie, of jy het 'n nuwe aanmeldsessie nodig

Sekuriteit

Moenie databasispoorte publiseer nie. Moenie privileged: true laat loop nie. Moenie /var/run/docker.sock in 'n toepassinghouer monteer nie tensy jy doelbewus 'n houerbestuurder skryf. Hou die enjin opgedateer. Skandeer jou eie beelde as jy hulle bou. .env op skyf is steeds 'n geheimlêer — beperk wie na die boks kan ssh.

  • Geen publieke 5432 / 3306 / 6379 nie
  • Pin beeld-digests of ten minste onveranderlike etikette
  • chmod 600 .env
  • Unattended-upgrades vir die gasheer-OS saak nog steeds
  • Een Compose-projek per toepassing hou die ontploffingsradius kleiner

Wenke

  • Sit compose.yaml in git; hou .env.example sonder ware geheime
  • Gebruik profiele vir opsionele werkers (docker compose --profile workers up -d)
  • Dophou docker stats wanneer jy die VPS grootte gee
  • Vir bind-mounts van bronkode is dit nie die produksiepatroon nie — bak 'n beeld
  • As die stapel tot verskeie VPS'e groei, kyk dan na orkestrasie — nie vroeër nie

'n Produksie-agtige Compose-opstelling op een VPS is: amptelike Docker-pakkette, 'n toegeslote .env, 'n YAML-lêer wat nie die databasis publiseer nie, gesondheidskontroles, 'n reverse proxy op 80/443, UFW, beeldetikette wat jy kan terugrol, en Postgres-dumps wat jy werklik een keer herstel het. Begin vanaf die sjabloon in hierdie artikel, vervang die toepassingbeeld, en behandel docker compose down -v as 'n vernietigende opdrag met dieselfde respek as rm -rf.