Docker Compose: webová aplikace a PostgreSQL v jednom souboru
Praktický compose.yaml pro webovou aplikaci s PostgreSQL a Redisem – sítě, volumes, healthcheck, depends_on, .env, nasazení na VPS za Nginx a užitečné příkazy.
Jakmile má aplikace víc částí – backend, databázi, cache – ruční docker run s dlouhými parametry přestane bavit. Docker Compose popíše celé prostředí v jednom YAML souboru a spustí ho jedním příkazem. Ukážeme si kompletní, produkčně použitelný příklad.
Compose v2
Dnes se používá Compose v2 jako plugin Dockeru: příkaz docker compose (s mezerou). Starší docker-compose (s pomlčkou) je zastaralý. Doporučený název souboru je compose.yaml; docker-compose.yml funguje také. Klíč version: na začátku souboru už není potřeba.
docker compose version
Struktura projektu
app/
├── compose.yaml
├── .env
├── Dockerfile
└── src/...
Kompletní compose.yaml
services:
web:
build: .
restart: unless-stopped
env_file: .env
environment:
DATABASE_URL: postgres://app:${POSTGRES_PASSWORD}@db:5432/app
REDIS_URL: redis://redis:6379/0
ports:
- "127.0.0.1:8000:8000"
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 3s
retries: 10
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:
A .env vedle něj (nepatří do Gitu):
POSTGRES_PASSWORD=dlouhe-nahodne-heslo
SECRET_KEY=dalsi-nahodny-retezec
Compose soubor .env ve stejné složce načte automaticky pro dosazení ${...} proměnných. env_file: navíc předá jeho obsah do kontejneru web.
Co je na tom důležité
Síť a jména služeb. Compose vytvoří pro projekt vlastní síť a služby se navzájem najdou podle jména. Aplikace se k databázi připojuje na hostitele db, ne localhost. To je nejčastější chyba začátečníků: localhost uvnitř kontejneru je kontejner sám.
Porty. Databáze a Redis nemají sekci ports – nejsou dostupné zvenku, jen pro ostatní služby v síti. Aplikace je publikovaná jen na 127.0.0.1, protože před ní bude Nginx. Port publikovaný na 0.0.0.0 by Docker otevřel do internetu i přes pravidla UFW.
depends_on s healthcheckem. Samotné depends_on čeká jen na start kontejneru, ne na to, až databáze přijímá spojení. condition: service_healthy počká na úspěšný healthcheck.
Volumes. Pojmenované volumes pgdata a redisdata přežijí docker compose down i rebuild. Zmizí jen s docker compose down -v – s tímto přepínačem opatrně.
Základní příkazy
docker compose up -d # spustit vše na pozadí
docker compose up -d --build # přestavět image a spustit
docker compose ps # stav služeb
docker compose logs -f web # logy jedné služby
docker compose exec web sh # shell v běžícím kontejneru
docker compose exec db psql -U app app
docker compose restart web
docker compose pull # stáhnout novější image
docker compose down # zastavit a odstranit kontejnery (data zůstanou)
docker compose config # výsledná konfigurace po dosazení proměnných
docker compose config je skvělý na ladění – ukáže, jestli se proměnné z .env dosadily správně.
Migrace a jednorázové příkazy
docker compose run --rm web python manage.py migrate
docker compose run --rm web python manage.py createsuperuser
run --rm spustí nový dočasný kontejner a po dokončení ho smaže.
Vývoj vs. produkce
Pro lokální vývoj chcete připojený zdrojový kód a reload. Vytvořte compose.override.yaml, který Compose načte automaticky:
services:
web:
volumes:
- ./src:/app/src
command: ["python", "-m", "flask", "--app", "src.app", "run", "--host=0.0.0.0", "--port=8000", "--debug"]
Na serveru tento soubor nemějte (nebo spouštějte explicitně docker compose -f compose.yaml up -d).
Nginx před aplikací
Na VPS typicky běží Nginx přímo na hostiteli a řeší HTTPS (Certbot). Konfigurace serveru:
server {
server_name app.example.cz;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Pak sudo certbot --nginx -d app.example.cz.
Aktualizace aplikace
git pull
docker compose up -d --build
docker image prune -f
Compose znovu vytvoří jen kontejnery, jejichž konfigurace nebo image se změnily. Databáze poběží dál. Tento postup můžete zautomatizovat podle článku o deployi přes GitHub Actions.
Časté problémy
| Příznak | Příčina |
|---|---|
connection refused na localhost:5432 |
v kontejneru použijte db:5432 |
| aplikace padá při startu, DB „ještě není“ | chybí healthcheck + condition: service_healthy |
po změně hesla v .env se nelze přihlásit |
Postgres čte POSTGRES_PASSWORD jen při první inicializaci prázdného volume |
| změny v kódu se neprojeví | chybí --build |
Nezapomeňte na zálohy databáze – volume není záloha. Postup najdete v článku Docker volumes a zálohy.