Skip to main content

Docker Compose

În mod clasic, pentru rularea unor containere, este nevoie să rulați comanda aferentă de rulare (docker run) și să dați toți parametrii necesari. Acest proces poate deveni anevoios dacă este repetat pentru pornirea mai multor containere. Un mod de a „salva” configurația de rulare este să ne creăm scripturi. Problema în rularea mai multor scripturi este pierderea uniformității în configurare (ce container la ce rețea se conectează, cu cine comunică, etc.).

Docker Compose este un utilitar creat de către Docker folosit pentru centralizarea configurării de rulare a containerelor în manieră declarativă. Utilizând fișiere de configurare YAML (Yet Another Markup Language), Docker Compose centralizează procesul de configurare într-o manieră naturală, declarativă.

Mai mult decât atât, formatul pentru fișierele Compose este utilizat și în cadrul Docker Swarm, orchestratorul creat de Docker pentru gestiunea serviciilor Docker, despre care vom discuta mai târziu.

tip

Veți observa că, în acest laborator, folosim termenii de servicii și containere în mod interschimbabil. Acest lucru se întâmplă pentru că Docker Swarm lucrează cu servicii, în timp ce Docker Compose cu containere. Ne referim la ambii termeni în același context deoarece configurația este, în proporție de 90%, identică, indiferent de utilizarea Swarm sau Compose.

Instalare

Pentru sisteme Windows și MacOS, Docker Compose face parte din instalarea de Docker Desktop for Windows/Mac. Pentru Linux, instalarea se realizează conform ghidului oficial.

Elemente cheie

Formatul unui fișier YAML

Fișierele YAML sunt folosite de obicei pentru a scrie configurări în mod declarativ. Formatul este unul foarte ușor de înțeles și folosit, astfel:

  • se folosesc elemente de tip „cheie:valoare
  • aliniatele indentate reprezintă proprietăți copii ale paragrafelor anterioare
  • listele se delimitează prin „-”.

Exemplu de fișier Docker Compose

docker-compose.yml
version: "3.8"
services:
api:
build: . # construiește imaginea dintr-un Dockerfile
image: nume-imagine-registru:versiune # folosește o imagine din registrul curent
environment:
NODE_ENV: development
VARIABILA_DE_MEDIU: valoare
ports:
- "5000:80"
networks:
- network-laborator-2

postgres:
image: postgres:12
secrets:
- parola-mea-ultra-secreta
environment:
PGPASSWORD_FILE: /run/secrets/parola-mea-ultra-secreta
volumes:
- volum-laborator-2:/var/lib/postgresql/data
- ./scripturi-initializare/init-db.sql:/docker-entrypoint-init.d/init-db.sql
networks:
- network-laborator-2

volumes:
volum-laborator-2:

networks:
network-laborator-2:

secrets:
parola-mea-ultra-secreta:
file: './parola-mea-nu-atat-de-secreta.txt'

Version

Descrie ce funcționalități vor fi încărcate la rularea utilitarului Docker Compose.

danger

Este obligatoriu să treceți versiunea în orice fișier Docker Compose.

Services

Descrie serviciile/containerele ce vor rula după ce configurația este pornită de către Compose. Fiecare serviciu reprezintă un container care va avea numele și configurația serviciului. În exemplul de mai sus, containerele se vor numi api și postgres. Cele mai importante proprietăți ale services sunt următoarele:

  • build - specifică directorul unde se află Dockerfile-ul de la care se va efectua construirea containerului
  • image - specifică numele imaginii folosite pentru rularea containerului
  • ports - o listă de intrări de tipul „port_gazdă:port_serviciu” unde este realizată expunerea și maparea de porturi
  • volumes - o listă de intrări de tipul „volum_gazdă:cale_serviciu” unde sunt precizate mapările de volume; aceleași reguli care se aplică la rularea clasică sunt menținute și aici; „volum_gazdă” poate fi un volum standard sau un bind mount
  • networks - lista de rețele din care face parte serviciul/containerul
  • secrets - lista de secrete ce vor fi folosite în cadrul serviciului/containerului
  • environment - obiect cu intrări de tipul „nume_variabilă_mediu_serviciu:valoare” care injectează variabilele de mediu specificate la rularea serviciului/containerului.
caution

Opțiunile build și image sunt disjuncte.

tip

Secretele trebuie trecute și în cadrul variabilelor de mediu, conform documentației. De exemplu, în configurația Postgres, secretele trebuie trecute în variabile de mediu speciale, sufixate cu _FILE, alături de calea lor completă (adică /run/secrets/NUME_SECRET).

Volumes

Descrie volumele utilizate în cadrul configurației. Volumele se trec sub formă de obiecte. Dacă nu se dorește schimbarea configurației implicite, valoarea este un câmp gol.

tip

Proprietatea top-level volumes trebuie scrisă pe același nivel de indentare ca services. Nu trebuie confundată cu proprietatea copil volumes din interiorul configurației serviciilor.

Networks

Descrie rețelele utilizate în cadrul configurației. Rețelele se trec sub formă de obiecte. Dacă nu se dorește schimbarea configurației implicite, valoarea este un câmp gol. Un exemplu de configurație de rețea este următorul (unde folosim o rețea care deja există, pentru că a fost creată independent de fișierul Docker Compose):

networks:
reteaua-mea-care-de-fapt-exista:
external: true
name: reteaua-originala-care-deja-exista

În cazul de mai sus, reteaua-mea-care-de-fapt-exista este doar o „redenumire” a unei rețele deja existente.

tip

Proprietatea top-level networks trebuie scrisă pe același nivel de indentare ca services. Nu trebuie confundată cu proprietatea copil networks din interiorul configurației serviciilor.

Secrets

Descrie secretele utilizate în cadrul configurației. Acestea rețin informații sensibile într-o manieră securizată, criptată, în cadrul Swarm. În Compose, secretele nu sunt securizate, însă au fost introduse pentru a ușura tranziția către Swarm. În cadrul Docker Compose, secretele pot proveni doar din fișiere externe, care trebuie specificate pentru fiecare secret în parte.

tip

Proprietatea top-level secrets trebuie scrisă pe același nivel de indentare ca services. Nu trebuie confundată cu proprietatea copil secrets din interiorul configurației serviciilor.

Comenzi Docker Compose

Comenzile pentru interacțiunea cu Docker Compose seamănă, ca sintaxă, cu cele clasice de Docker atât pentru versiunea 1 cât și pentru versiunea 2. Mai jos, puteți observa cele mai utilizate comenzi. Pentru versiunea 1, utilitarul este docker-compose, iar pentru versiunea 2 utilitarul este tot docker cu parametrul compose, iar pe restul le puteți studia în documentația oficială pentru versiunea 1, respectiv documentația oficială pentru versiunea 2. Diferența principala între versiunea 1 si 2 este ca exista mai multe opțiuni cum ar fi listarea stivelor de containere prin opțiunea ls.

$ docker-compose start                       # pornește containerele V1
$ docker-compose stop # oprește containerele V1
$ docker-compose pause # pune în stare de pauză containerele unui serviciu (se trimite SIGPAUSE) V1
$ docker-compose unpause # scoate din starea de pauză containerele V1
$ docker-compose ps # listează containerele active V1
$ docker-compose up # face build, recreează, pornește și atașează containere la un serviciu V1
$ docker-compose up -d # serviciile rulează în fundal, detașate de terminalul care le-a inițializat V1
$ docker-compose up --build # creează imaginile înainte de pornire V1
$ docker-compose -f my-docker-compose.yml up # se folosește fișierul de Compose specificat în loc de cel implicit V1
$ docker-compose down # oprește containerele și le șterge, împreună cu rețelele, volumele și imaginile create la up V1
$ docker-compose rm # șterge toate containerele oprite (se poate specifica la final și numele containerului care trebuie șters) V1
$ docker-compose rm -s -v # cu -s se opresc toate containerele și cu -v se șterg și volumele anonime atașate V1
$ docker compose start # pornește containerele V2
$ docker compose pause # pune în stare de pauză containerele unui serviciu (se trimite SIGPAUSE) V2
$ docker compose unpause # scoate din starea de pauză containerele V2
$ docker compose ps # listează containerele active V2
$ docker compose ls # listează toate stivele de containere V2
$ docker compose -p my-project -f my-docker-compose.yml up # se folosește fișierul de Compose specificat în loc de cel implicit si cu un nume de proiect V2
$ docker compose down # oprește containerele și le șterge, împreună cu rețelele, volumele și imaginile create la up V2
$ docker compose rm # șterge toate containerele oprite (se poate specifica la final și numele containerului care trebuie șters) V2
$ docker compose rm -s -v # cu -s se opresc toate containerele și cu -v se șterg și volumele anonime atașate V2

Combinarea mai multor fișiere Docker Compose

Docker Compose este recomandat să fie utilizat doar în etapa de dezvoltare locală. Pentru medii de testare sau producție, se folosește Docker Swarm (sau alte orchestratoare, precum Kubernetes).

Tocmai pentru că este folosit în etapa de dezvoltare, Docker Compose are un mecanism de a combina mai multe fișiere Compose pentru a crea diferite configurații de rulare, fără a replica părțile comune.

Pentru a rula o configurație de Compose bazată pe mai multe fișiere YAML, puteți folosi comanda de mai jos.

$ docker-compose -f fisier-compose-1.yml -f fisier-compose-2.yml up --build        # V1
$ docker compose -f fisier-compose-1.yml -f fisier-compose-2.yml up --build # V2

În comanda de mai sus, informațiile din fisier-compose-2.yml vor suprascrie/completa informațiile din fisier-compose-1.yml. Acest lucru este util pentru a testa rapid diverse configurații.