Docker Compose — Labor
Kestus: 4 tundi
Eeldused: Loeng antud (teenus, võrk, volume, miks mitu konteinerit). Nädal 5 Flask + Dockerfile olemas. Kui udu — tagasi loengusse. Siit edasi ainult käed külge.
Keskkond: Docker seal kus töötad — kohalik / WSL / server. Kood ja käsud VS Code'is. localhost = masin kus Docker jookseb.
Õpiväljundid
Selle labi lõpuks sa:
- Ehitad kolme-teenuse stacki üks teenus korraga, testides igal sammul
- Diagnoosid viis tüüpilist Compose-viga veateate järgi (kadunud parool, vale host-nimi, 502, kadunud andmed,
.env) - Selgitad miks teenused suhtlevad nime, mitte IP järgi
- Selgitad miks andmed lähevad volume'i, mitte konteinerisse — ja tõestad seda
- Taastad puhta seisu ise tehtud sasi järel
Labi loogika: baas → laienda → viga → paranda → laienda → viga → taasta. Sa ei kopeeri valmis docker-compose.yml-i. Sa ehitad selle teenus haaval, lõhud igal võtmekohal meelega, ja saad aru miks. Tervet faili näed üks kord — edasi ainult "lisa see teenus" / "lisa need read".
Osa 1 · Baas — üks teenus
Mine nädal 5 kausta, kus on app/ (Flask + Dockerfile) ja käivita et ikka töötab:
localhost:5000 vastab? Peata (Ctrl+C). Nüüd sama Compose'iga. Loo app/ kõrvale docker-compose.yml. Ainus kord terve fail — edasi lisad ridu:
Sama vastus, aga nüüd üks käsk. Ära edasi mine enne kui vastab.
Tip
build: ./app ei leia Dockerfile'i — tee on suhteline docker-compose.yml suhtes, mitte terminali kausta suhtes.
Osa 2 · Andmebaas ilma paroolita
Lisa teine teenus. Näita ainult uut tükki — lisa web alla, sama taande tasandile:
Käivita ainult db ja vaata logi:
Vaata mis juhtub. db sureb kohe, logis midagi stiilis Database is uninitialized and superuser password is not specified.
Diagnoosi enne kui parandad
PostgreSQL image keeldub käivitumast ilma parooli. Miks arvad, et image on teadlikult tehtud niimoodi keelduma, mitte vaikeparooliga käivituma?
Paranda — lisa db-le keskkonnamuutujad:
Otsi logist database system is ready to accept connections. Tuleb paari sekundiga.
Osa 3 · Vale aadress andmebaasile
Flask peab teadma kus db on. Proovime meelega valesti — IP-ga. Lisa web-le:
app.py-s loe muutuja ja tee test-route (kasuta oma nädal 5 rakendust; kui vaja, lihtne kontroll):
os.environ["DATABASE_URL"] kaudu — täpne kood on su enda rakenduse asi)
Viga. 127.0.0.1 konteineri sees tähendab seda sama konteinerit, mitte db-konteinerit.
Diagnoosi
Iga konteiner on oma localhost. web konteineri 127.0.0.1 ei ole db konteiner. Compose annab teenustele nime-põhise aadressi. Mis on siis õige host web-i jaoks?
Paranda — IP asemel teenuse nimi db:
Ühendus OK. db on DNS-nimi Compose sisevõrgus — mitte miski, mille sa määrasid, vaid mille Compose ise teenuse nimest tegi.
Osa 4 · Laienda — nginx ja 502
Paneme nginx'i Flaski ette (pöördproksi). Loo nginx/default.conf — meelega vale teenuse nimega (app, mitte web):
Lisa nginx teenus:
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- web
502 Bad Gateway.
Diagnoosi
Vaata docker compose logs nginx. nginx otsib teenust app, aga docker-compose.yml-is on ta nimega web. nginx ei leia app-i sisevõrgust. Kus on kirjaviga — konfiguratsioonis või compose-failis?
Paranda — default.conf-is app → web:
nginx loeb konfiguratsiooni käivitudes, seega taaskäivita see teenus:
Vastus tuleb — nüüd läbi pordi 80 ja nginx'i. Eemalda web-lt ports: 5000:5000 (kogu liiklus käib läbi nginx'i, Flask ei pea otse väljas olema):
Osa 5 · Andmed kaovad
Kirjuta andmebaasi midagi (oma rakenduse route kaudu, või käsitsi):
docker compose exec db psql -U postgres -d appdb -c "CREATE TABLE test (id int); INSERT INTO test VALUES (1);"
docker compose exec db psql -U postgres -d appdb -c "SELECT * FROM test;"
Rida on olemas. Nüüd tee see, mida sa iga päev teed — kustuta stack ja käivita uuesti:
docker compose down
docker compose up -d
docker compose exec db psql -U postgres -d appdb -c "SELECT * FROM test;"
Tabelit pole. Andmed kadusid.
Diagnoosi
down kustutas konteinerid. PostgreSQL kirjutas andmed konteineri sisemisse failisüsteemi, mis kadus koos konteineriga. Kus peaksid andmed elama, et konteineri kustutamine neid ei puudutaks?
Paranda — lisa db-le volume ja faili lõppu volumes: sektsioon:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret123
POSTGRES_DB: appdb
volumes:
- pgdata:/var/lib/postgresql/data
Faili lõppu (teenustega samal tasandil):
docker compose up -d
docker compose exec db psql -U postgres -d appdb -c "CREATE TABLE test (id int); INSERT INTO test VALUES (1);"
docker compose down
docker compose up -d
docker compose exec db psql -U postgres -d appdb -c "SELECT * FROM test;"
Rida on alles. Volume elab konteinerist eraldi.
Mõtle
docker compose down -v (tähega v) kustutab ka volume'i. Millal sa seda tahaksid, ja miks Docker ei tee seda vaikimisi?
Osa 6 · Parool failis
secret123 on docker-compose.yml-is kahes kohas, tavatekstis. Läheb GitHubi = lekkis. (Märteni .env, teine fail.) Vii .env-i.
Loo .env (sama kaust kui compose):
Asenda compose-failis väärtused meelega vale süntaksiga kõigepealt ($NIMI, ilma sulgudeta):
docker compose config näitab lõplikku faili muutujatega asendatuna. Vaata — asendus ei toimi ootuspäraselt.
Diagnoosi
Compose ootab ${NIMI} (lokkis sulgudega), mitte $NIMI. Paranda kõik kolm kohta.
Paranda:
jaweb DATABASE_URL-is samamoodi ${POSTGRES_PASSWORD} / ${POSTGRES_DB}.
Warning
Lisa .env kohe .gitignore-i. echo ".env" >> .gitignore ja kontrolli git status — .env ei tohi olla jälgitavate failide seas.
Osa 7 · Taasta ja koristus
Mõtle
docker compose stop vs down vs down -v — kolm eri taset. Millal kumbagi? (Peatab / kustutab konteinerid / kustutab ka andmed.)
Volume püsib down järel — kontrolli:
pgdata on seal. Täielikuks puhastuseks: docker compose down -v.
Lõppkontroll — oskad ilma juhendita
- Ehitad kolme-teenuse stacki üks teenus korraga
-
curl localhostvastab läbi nginx'i (mitte otse Flaski pordilt) - Selgitad miks host on
db, mitte127.0.0.1ega IP - 502 nägemisel tead kohe: teenuse nimi konfiguratsioonis vs compose'is
- Tõestad et volume säilitab andmed üle
down/up - Parool on
.env-is (${NIMI}süntaks),.envon.gitignore-is -
docker compose pson tühi kui pead selle tühjaks tegema
Lisaülesanded (kui jõuad ette)
- Healthcheck: lisa
db-lehealthcheck, muudaweb depends_on→condition: service_healthy. Millaldepends_onüksi ei piisa? - Neljas teenus: Redis või pgAdmin stacki (vt kodutöö) — teenus haaval, testi eraldi.
- Skaleerimine:
docker compose up -d --scale web=3. Mis läheb katki port-mapping'uga, ja miks vajaks see nginx load-balancer'it?
Veaotsing
| Veateade | Põhjus | Lahendus |
|---|---|---|
db sureb (Exit 1) |
POSTGRES_PASSWORD puudub |
Lisa environment |
could not translate host name |
Kasutad IP/127.0.0.1, mitte teenuse nime |
Host = teenuse nimi (db) |
502 Bad Gateway |
Vale teenuse nimi proxy_pass-is |
Nimi konfiguratsioonis = nimi compose'is |
Andmed kaovad down järel |
Volume puudub | Lisa volumes |
${NIMI} ei asendu |
.env puudub, või $NIMI ilma sulgudeta |
${NIMI} + .env samas kaustas |
| Muudatus ei rakendu | Image/konfiguratsioon vana | docker compose up -d --build, konfi puhul restart |
Tabel 6.1. Iga rida on viga, mille sa selles labis ise tekitasid ja parandasid.
Allikad
| Allikas | URL | Miks |
|---|---|---|
| Docker Compose | https://docs.docker.com/compose/ | Kõik võtmesõnad |
| Compose file spec | https://docs.docker.com/reference/compose-file/ | depends_on, volumes, environment |
| PostgreSQL image | https://hub.docker.com/_/postgres | POSTGRES_PASSWORD |
Compose config |
https://docs.docker.com/reference/cli/docker/compose/config/ | Muutujate silumiseks |