Kaip diegti programas su Docker Compose VPS serveryje
Praktinis gamybos vadovas Docker Compose v2 Ubuntu: įdiekite variklį, parašykite Compose failą su tinklais ir tomais, tvarkykite paslaptis, pastatykite atvirkštinį tarpinį serverį priekyje, atnaujinkite ramiais paleidimais ir darykite vardinių tomų atsargines kopijas.

Docker Compose yra įprastas būdas paleisti nedidelį rinkinį viename VPS: žiniatinklio programa, duomenų bazė, Redis talpykla ir atvirkštinis tarpinis serveris, aprašyti viename YAML faile. Tai ne Kubernetes. Negausite kelių mazgų perjungimo. Gausite kartotinę, peržiūrimą sąranką, kurią per kelias minutes galite atkurti naujame Hiddence VPS — būtent to reikia daugumai šalutinių projektų ir mažų produktų.
Šis straipsnis daro prielaidą, kad norite kažko arčiau gamybos nei docker run penktadienio vakarą. Įdiegsime Docker Engine ir Compose papildinį, sukursime diegimo naudotoją be root, parašysime Compose failą su healthcheck ir paleidimo iš naujo politikomis, paslaptis laikysime iš Git, į internetą paskelbsime tik atvirkštinio tarpinio serverio prievadus ir apibrėšime atnaujinimo bei atsarginių kopijų rutiną. Pavyzdinis rinkinys yra tipiška žiniatinklio programa plius PostgreSQL plius Caddy, bet tas pats šablonas tinka Node, PHP, Python ar krūvai workerių.
Kodėl Compose viename VPS vis dar prasmingas
Žmonės šoka prie Kubernetes, nes tai madinga, tada savaitgalį leidžia YAML vienai svetainei. Compose lieka skaitomas. Versijuojate failą, dokumentuojate aplinkos kintamuosius ir galite palyginti pakeitimą prieš jį taikydami. Izoliacija pakankama: pažeistas programos konteineris neturėtų laikyti duomenų bazės UNIX lizdo, jei naudojote tinklus ir mažiausių teisių naudotojus. Ištekliaus ribos sustabdo atminties nutekėjimą nuo viso VPS užšaldymo.
- Vienas failas aprašo visą rinkinį
- Vardiniai tomai išlieka atkuriant konteinerius
- Vidiniai Docker tinklai laiko Postgres nuo viešo interneto
- restart: unless-stopped padengia daugumą paleidimų iš naujo
- Lengva nukopijuoti į antrą VPS, kai išaugate pirmąjį
Reikalavimai
Naudokite VPS su pakankamai RAM programai ir Postgres. 2 GB planas yra realistiškas minimumas programai + duomenų bazei + tarpiniam serveriui. Daroma prielaida Ubuntu 24.04. Nediegikite Docker iš atsitiktinio Snap neskaitę, ką jis daro cgroups; toliau pateikti žingsniai naudoja oficialią Docker apt saugyklą.
- Ubuntu 22.04/24.04, root arba sudo
- Rekomenduojama 2 GB RAM (1 GB tik mažyčiams rinkiniams be Postgres)
- Domenas, nukreiptas į VPS, jei norite automatinio HTTPS
- Git ar kitas būdas nukopijuoti projektą į serverį
1 veiksmas: įdiekite Docker Engine ir Compose v2
Compose v2 yra papildinys, kviečiamas kaip docker compose (su tarpu), ne senasis docker-compose Python dvejetainis. Įdiekite abu iš Docker saugyklos, kad gautumėte dabartinius saugos pataisymus.
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 version2 veiksmas: diegimo naudotojas ir katalogų išdėstymas
Compose paleisti kaip root veikia, bet skirtas naudotojas su naryste docker grupėje yra švaresnis. Projektą dėkite į /opt arba /srv, ne į /root, kad atsarginės kopijos ir teisės būtų akivaizdžios. Niekada nedarykite katalogo, kuriame yra .env, rašomo visiems.
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/app3 veiksmas: parašykite gamybai skirtą Compose failą
Toliau pateiktas failas yra šablonas. Pakeiskite programos atvaizdą savuoju. Postgres neskelbiamas į 0.0.0.0:5432 — tik Caddy skelbiamas 80 ir 443. Healthcheck sustabdo atvirkštinį tarpinį serverį nuo srauto siuntimo programai, kuri vis dar migruoja duomenų bazę. Prisegkite atvaizdų žymas; latest yra tai, kaip nutinka staigūs gedimai.
# /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:4 veiksmas: paslaptys, .env ir Caddyfile
Slaptažodžius dėkite į .env serveryje, chmod 600 ir niekada neįtraukite to failo į commit. Generuokite slaptažodžius su openssl rand -base64 32. Caddyfile tereikia atvirkštinio tarpinio serverio į programos paslaugos vardą Docker tinkle.
# /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=1005 veiksmas: užkarda, žurnalai ir ištekliaus ribos
UFW turėtų leisti tik 22, 80 ir 443. Docker kartais apeina UFW skelbiamiems prievadams; jei reikia griežtos šeimininko užkardos, pažiūrėkite dabartinę Docker + UFW sąveiką jūsų Ubuntu versijai arba skelbkite prievadus tik 127.0.0.1 ir priekyje statykite šeimininko Caddy. Compose nustatykite atminties ribas, kad Postgres negalėtų suvalgyti VPS.
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 docker6 veiksmas: atnaujinimai ir grąžinimai
Nuobodus atnaujinimas, kuris veikia: traukite naujus atvaizdus, up -d, stebėkite healthcheck, ankstesnę žymą laikykite git, kad galėtumėte prisegti atgal. Nenaudokite docker compose down gamybos duomenų bazėje, nebent ketinate nustoti priimti srautą. down -v ištrina tomus — tai ištrynimas, ne paleidimas iš naujo.
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 volumesDarykite vardinių tomų atsargines kopijas
VPS momentinė kopija gera. Loginis Postgres dump geresnis, jei reikia atkurti kitoje mašinoje. Suplanuokite tai su cron. Kartą išbandykite atkūrimą, kitaip neturite atsarginių kopijų — turite failus, kuriais tikitės, kad jie yra atsarginės kopijos.
# 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 appTrikčių šalinimas
Skaitykite docker compose ps ir docker compose logs service. Atvaizdų traukimo gedimai paprastai yra ghcr/docker hub greičio ribos arba privatus atvaizdas be prisijungimo. 502 iš Caddy reiškia, kad programa nesveika arba tarpinio serverio mazgo vardas neteisingas (iš Caddy konteinerio naudokite Compose paslaugos vardą, ne localhost). Teisių klaidos tomuose dažnai reiškia, kad atvaizdas veikia kaip uid 1000, o šeimininko katalogas yra root.
- compose: command not found — įdiegėte senąjį dvejetainį vardą; naudokite docker compose
- port is already allocated — kažkas kitas valdo 80/443 (Apache, Nginx, kitas Caddy)
- database connection refused — programa paleido prieš Postgres parengtį; naudokite healthcheck + depends_on condition
- disk full — docker system df, tada atsargiai prune nenaudojamus atvaizdus
- permission denied on docker.sock — naudotojas ne docker grupėje arba reikia naujos prisijungimo sesijos
Saugumas
Neskelbkite duomenų bazės prievadų. Nenaudokite privileged: true. Nemontuokite /var/run/docker.sock į programos konteinerį, nebent sąmoningai rašote konteinerių tvarkyklę. Laikykite variklį atnaujintą. Skenuokite savo atvaizdus, jei juos kuriate. .env diske vis tiek yra slaptas failas — apribokite, kas gali ssh į dėžę.
- Jokio viešo 5432 / 3306 / 6379
- Prisegkite atvaizdų santraukas arba bent nekintamas žymas
- chmod 600 .env
- Unattended-upgrades šeimininko OS vis dar svarbūs
- Vienas Compose projektas programai sumažina sprogimo spindulį
Patarimai
- compose.yaml dėkite į git; .env.example laikykite be tikrų paslapčių
- Naudokite profilius neprivalomiems workeriams (docker compose --profile workers up -d)
- Stebėkite docker stats, kai dydinate VPS
- Šaltinio kodo bind mounts — tai ne gamybos šablonas; iškepkite atvaizdą
- Jei rinkinys auga iki kelių VPS, tada žiūrėkite orkestravimą — ne anksčiau
Gamybai artima Compose sąranka viename VPS: oficialūs Docker paketai, užrakintas .env, YAML failas, kuris neskelbia duomenų bazės, healthcheck, atvirkštinis tarpinis serveris 80/443, UFW, atvaizdų žymos, kurias galite grąžinti, ir Postgres dump, kurį iš tikrųjų kartą atkūrėte. Pradėkite nuo šio straipsnio šablono, pakeiskite programos atvaizdą ir docker compose down -v traktuokite kaip destruktyvią komandą su ta pačia pagarba kaip rm -rf.