- Docker Compose vă permite să definiți și să gestionați mai multe containere dintr-un singur fișier YAML, facilitând lucrul cu aplicații bazate pe microservicii.
- Secțiunea de servicii este obligatorie și este completată cu rețele, volume, configurații și secrete pentru controlul comunicării, persistenței și configurării.
- Exemple precum Flask+Redis sau o aplicație full stack cu frontend, backend și bază de date arată cum Compose simplifică dezvoltarea și implementarea.
- L comenzi docker compune sus, jos, ps și busteni Acestea formează fluxul de lucru de bază pentru ridicarea, depanarea și oprirea stivelor de containere.

Dacă ați experimentat deja cu containere și ați realizat că o aplicație „reală” necesită mai multe servicii care rulează simultan (bază de date, API, frontend, cache etc.), veți întâlni în cele din urmă Docker Compose. Acest instrument vă permite să configurați toată infrastructura respectivă cu un singur fișier și câteva comenzi, fără a fi nevoie să jonglezi cu terminale și scripturi nesfârșite.
În acest tutorial, veți învăța ce este Docker Compose, cum funcționează fișierul său compose.yaml și cum să orchestrați cu ușurință aplicații multi-container: de la exemple simple cu Flask și Redis până la arhitecturi mai complexe cu frontend, backend și bază de date. De asemenea, veți acoperi aspecte precum rețelele, volumele, configurațiile, secretele și comenzile cheie pentru a lucra confortabil în medii de dezvoltare și în medii mai solicitante.
Ce este Docker Compose și de ce merită folosit?
Docker Compose este o extensie Docker care vă permite să definiți și să gestionați mai multe containere ca și cum ar fi o singură aplicație. În loc să porniți fiecare serviciu manual cu comanda și parametrii săi `docker run`, descrieți totul într-un fișier YAML și îl porniți cu o singură comandă.
Frumusețea programului Compose constă în faptul că multe aplicații moderne sunt construite pe microservicii care rulează în containere individuale : o bază de date, o API, un frontend, un sistem de așteptare, o memorie cache de tip Redis și așa mai departe. Docker recomandă ca fiecare container să ruleze un singur serviciu, așa că, dacă încerci să încadrezi totul într-o singură imagine, ajungi la un monstru dificil de scalat și întreținut.
Ai putea rula două sau mai multe servicii în același container, dar asta anulează o bună parte din avantajele Docker : dacă unul se defectează, le trage pe celelalte în jos, nu poți scala doar partea care primește cea mai mare încărcare, iar gestionarea jurnalelor, resurselor și erorilor devine o mare harababură.
Cu Docker Compose definești fiecare serviciu separat, specificând modul în care se conectează între ele, ce date persistă, ce porturi expun, ce variabile de mediu utilizează și așa mai departe. În acest fel, dacă un container eșuează, restul pot continua să funcționeze în funcție de modul în care îl configurezi, iar scalarea unei componente specifice este la fel de simplă ca modificarea configurației sale sau a numărului de replici.
În plus, Compose se integrează perfect în fluxurile de lucru CI/CD și în implementările de producție . Îl poți utiliza direct cu instrumente precum Portainer sau Docker Swarm, iar dacă lucrezi cu Kubernetes, proiecte precum Kompose îți permit să traduci un fișier compose.yaml în manifeste Kubernetes fără a fi nevoie să rescrii totul manual.
Cerințe preliminare pentru urmarea tutorialului Docker Compose
Pentru a urmări cu ușurință exemplele din acest tutorial, trebuie să aveți instalate Docker și Docker Compose . În prezent, există două căi principale:
- Motor Docker + Docker Compose instalate ca binare independente.
- DockerDesktop, care include Docker Engine, Docker Compose și o interfață grafică.
Este important să aveți cunoștințe de bază despre comenzile Docker (imagini, containere, porturi, volume) și să nu vă fie teamă să utilizați linia de comandă. Exemplele sunt de obicei bazate pe Linux (de exemplu, Ubuntu 22.04), dar logica se aplică în egală măsură atât pentru Windows , cât și pentru macOS cu Docker Desktop.
Verificați dacă totul este în ordine rulând ceva simplu precum „docker --version” și „docker compose version” în terminal . Dacă ambele comenzi răspund fără erori, sunteți gata să continuați cu exemplele.
Structura de bază a unui fișier compose.yaml
Inima Docker Compose este fișierul compose.yaml (sau docker-compose.yml)Acolo descriem ce servicii dorim să configurez și cum ar trebui să fie corelate. Deși anterior câmpul era folosit version Pentru a marca versiunea formatului, documentația actuală recomandă să nu o definiți, astfel încât să fie utilizată întotdeauna cea mai recentă versiune a schemei.
În fișierul Compose veți avea mai multe secțiuni posibile, deși doar una este obligatorie: services . De acolo puteți adăuga alte secțiuni în funcție de complexitatea proiectului dumneavoastră:
- Servicii: definiția fiecărui microserviciu (obligatoriu).
- rețelerețele personalizate pentru controlul comunicării dintre containere.
- volumevolume pentru a persista datele sau a le partaja între servicii.
- configuriconfigurația serviciului (de exemplu, fișierele de configurare ale serverului web).
- secretegestionarea informațiilor sensibile (parole, chei API…).
Pe parcursul acestui tutorial, veți vedea cum să combinați toate aceste secțiuni pentru un proiect tipic care include o aplicație, o bază de date și o interfață de programare a aplicațiilor (API) , precum și un exemplu de aplicație web în Python cu Flask și Redis.
Servicii în Docker Compose: nucleul definiției
secțiune serviciile sunt piesa esențială din orice fișier Compose. În acesta definiți fiecare dintre containerele care vor alcătui aplicația dvs., dându-le numele dorit (de exemplu, web, database, api, redis, Etc).
Pentru fiecare serviciu puteți seta o serie de parametri , inclusiv unii care sunt utilizați în mod obișnuit în proiecte din lumea reală:
Parametru build indică unde se află Dockerfile-ul din care va fi construită imaginea serviciului. De obicei, se specifică un context (director) unde se află fișierul Dockerfile al aplicației pe care doriți să o împachetați.
Dacă aveți deja o imagine creată sau doriți să utilizați una din registru, utilizați image să o referențieziNumele respectă formatul [<registry>/][<project>/]<image>[:<tag>|@<digest>]Și dacă trebuie să controlezi când este descărcată sau actualizată imaginea respectivă, poți folosi pull_policy.
Câmpul ports Este folosit pentru a mapa porturile dintre gazdă și containerSintaxa este de tipul [HOST:]CONTAINER[/PROTOCOL]De exemplu, dacă o bază de date PostgreSQL ascultă pe portul 5432 din interiorul containerului și doriți să o expuneți pe portul 5555 al gazdei, ați face ceva de genul: "5555:5432" în lista de porturi.
Politica de repornire este controlată cu restartcare indică ce trebuie făcut atunci când un container se termină din cauza unei erori sau se oprește. Valorile tipice sunt no, always, on-failure y unless-stoppedpermițând serviciilor critice să rămână operaționale chiar dacă se confruntă cu întreruperi ocazionale.
Dacă un serviciu necesită disponibilitatea altuia înainte de a începe, puteți utiliza depends_on pentru a defini dependențele dintre containereUn exemplu clasic este o aplicație care necesită ca baza de date să fie funcțională pentru a evita eșecul conexiunii inițiale.
Pentru configurare și acreditări, aveți două abordări comune: env_file y environment. Cu env_file Indicați unul sau mai multe fișiere .env cu variabilele de mediu, în timp ce în environment Le puteți lista direct în YAML. Cea mai bună practică este să folosiți fișiere. .env pentru a preveni încorporarea parolelor și a datelor sensibile în fișierul compose.yaml.
Parametru volumes permite montarea căilor sau volumelor gazdă În cadrul containerului, veți utiliza atât persistența datelor, cât și partajarea folderelor între servicii. Aici, veți face referire doar la volumele pe care le puteți defini ulterior în secțiunea de mai sus. volumes dacă aveți nevoie ca acestea să fie partajate sau gestionate mai explicit.
Cu aceste câmpuri, puteți deja configura servicii destul de complete. Specificația Compose include mult mai multe opțiuni avansate (sănătate, limite de resurse, comenzi de pornire etc.), dar acestea acoperă deja majoritatea utilizărilor comune.
Exemplul 1: Aplicație web în Python cu Flask și Redis
Un exemplu tipic pentru înțelegerea Docker Compose este crearea unei aplicații web simple în Python , folosind Flask pentru a servi pagini și Redis ca un depozit în memorie pentru un contor de vizitatori. Ideea este că nu trebuie să instalați nici Python, nici Redis pe mașina dvs.: totul rulează în containere.
Fluxul de lucru ar fi cam așa: mai întâi creezi un director pentru proiect și înăuntru adaugi un fișier app.py cu codul Flask. În acel cod folosești „redis” ca nume de gazdă și portul 6379, care este portul implicit pentru serviciul Redis din containerul dvs.
Funcția care gestionează contorul de accesări încearcă să se conecteze la Redis de mai multe ori înainte de a renunța, deoarece containerul Redis poate dura câteva secunde până devine disponibil atunci când deschideți întreaga stivă.
plus app.py, creezi un fișier requirements.txt cu dependențe Python (de exemplu, Flask și redis-py) și un fișier Dockerfile care specifică modul de construire a imaginii aplicației web: imaginea de bază Python (3.7, 3.10 sau orice altceva), directorul de lucru, variabilele de mediu pentru Flask, instalarea gcc și dependențele de sistem, o copie a fișierului requirements.txt, instalarea pachetului și copierea codului.
În Dockerfile marcați și port care va afișa containerul (de exemplu 5000) și definiți comanda implicită, în mod normal flask run --debug sau similar, astfel încât să pornească automat la crearea containerului.
Cu toate acestea pregătite, fișierul compose.yaml definește două servicii: unul numit, de exemplu, web, care este construit din fișierul Dockerfile al proiectului și expune portul 8000 extern (mapând portul 8000 al gazdei la portul 5000 al containerului), și un altul numit redis că Extrageți imaginea oficială Redis din Docker Hub.
Pentru a porni aplicația, pur și simplu navigați la directorul proiectului și rulați comanda „docker compose up” . Compose va descărca imaginea Redis, va construi imaginea aplicației web și va porni ambele servicii în ordinea corectă.
Odată ce este pornit și funcționează, introduceți cu browserul dvs. http://localhost:8000 (o http://127.0.0.1:8000) și ar trebui să vedeți un mesaj de tip „Salut, lume” și un Contor de vizitatori care crește de fiecare dată când reîncarci pagina. Dacă inspectați imaginile locale cu docker image lsVei vedea ceva de genul redis y web create sau descărcate.
Când vrei să oprești totul, poți face asta CTRL+C în terminalul de unde ai lăsat „docker compose up” sau executa docker compose down din directorul proiectului. Aceasta operațiune va opri și va elimina containerele create de acea comandă compose.
Îmbunătățirea fluxului de lucru: Legarea montajelor și Supravegherea compunerii
Lucrul în dezvoltare cu Docker este mai convenabil dacă nu trebuie să reconstruiești imaginea de fiecare dată când modifici codul. Aici intervin Bind Mounts și, în versiuni mai recente, Docker Compose Watch.
O montare Bind implică montarea unui folder de pe mașina dvs. în interiorul containerului. În fișierul compose.yaml, adăugați o secțiune la serviciul web. volumes care mapează directorul proiectului la directorul de lucru din recipient, de exemplu .:/codeÎn acest fel, orice modificare pe care o faceți în editor se reflectă instantaneu în container.
Dacă activați și modul de depanare al Flask cu variabila FLASK_DEBUG=1, comanda flask run Va reîncărca automat aplicația când detectează modificări în fișiere, fără a fi nevoie să o oprească și să o repornească.
Docker Compose Watch merge cu un pas mai departe: poți folosi `docker compose watch` sau `docker compose up --watch` pentru ca Compose să monitorizeze fișierele proiectului și să sincronizeze modificările cu containerele tale într-un mod mai inteligent. Când salvezi un fișier, acesta este copiat în container, iar serverul de dezvoltare actualizează aplicația fără a reporni întregul container.
Încercați, de exemplu, să schimbați mesajul de bun venit în app.py de la „Salut, lume!” la o expresie precum „Salutări de la Docker”Salvați fișierul, reîmprospătați browserul și veți vedea instantaneu noul mesaj, în timp ce contorul de vizite continuă să ruleze fără a-și pierde starea.
Și când termini de lucrat, ca întotdeauna, poți trage docker compose down alin opriți și curățați recipientele care erau în curs de desfășurare cu acea stivă.
Exemplul 2: Aplicație full stack cu frontend, backend și bază de date
Pentru a vedea Docker Compose într-o arhitectură mai realistă, imaginați-vă o aplicație cu listă de activități (Todo List) cu un frontend în Vue.js, un API în Node.js și o bază de date MongoDB. Fiecare parte se află în propriul director și are propriul fișier Dockerfile.
În depozit este posibil să găsiți un folder frontend cu aplicația Vue și cu alta backend cu serverul Node. Backend-ul expune endpoint-uri pentru crearea, listarea, actualizarea și ștergerea sarcinilorși se conectează la MongoDB pentru a le stoca. Frontend-ul consumă aceste endpoint-uri pentru a afișa și gestiona lista de sarcini în browser.
Dosarul docker-compose.yml Se află la rădăcina proiectului și definește trei servicii: frontend, backend y databaseServiciul frontend este construit din fișierul Dockerfile din folderul corespunzător, de obicei expunând portul intern 80 și mapându-l la portul 5173 al gazdei (de exemplu, pentru a utiliza aceeași adresă URL ca în dezvoltarea locală).
Backend-ul este construit din fișierul Dockerfile din directorul backend, expune portul 3000 (atât în interiorul, cât și în exteriorul containerului, dacă vrei să simplifici) și declară o dependență față de baza de date pentru a se asigura că MongoDB este disponibil la pornire.
Serviciul de database utilizați direct Imaginea oficială a MongoDB și construim un volum, să zicem mongodb_dataîn /data/db, unde Mongo stochează datele. Volumul respectiv este declarat în secțiunea superioară. volumes din compose, astfel încât datele să persiste chiar dacă ștergeți și recreați containerele.
În cele din urmă, toate aceste servicii se conectează printr-o rețea personalizată, de exemplu my-network, definit în secțiunea networksAcest lucru permite rezolvarea lor după numele serviciului (backend-ul se poate conecta la Mongo folosind numele de gazdă). database) și că traficul este încapsulat în acea rețea izolată.
Cu configurația gata, rulați docker compose up În centrul proiectului, este responsabil pentru construiți sau descărcați imaginile și lansați cele trei containerePuteți verifica dacă totul este la locul lui cu docker compose ps, apoi accesând http://localhost:5173 pentru a vizualiza aplicația Vue în browser și a crea primele sarcini.
Rețele în Docker Compose: conectarea serviciilor între ele
Rețeaua este stratul care permite containerelor tale să „vadă” și să comunice între ele într-un mod controlat . În mod implicit, Docker creează deja rețele pentru Compose, dar definirea lor explicită îți oferă mai multă claritate și control asupra a ceea ce poate comunica cu ce.
Funcționează simplu: fiecare serviciu include un câmp networks unde indicați rețelele cărora îi aparține, iar apoi în secțiunea superioară networks Definești acele rețele cu configurația lor. Cea mai comună (și recomandată în multe cazuri) abordare este utilizarea driverului. bridge.
O rețea de punți creează o spatiu privat rețea pentru containerele dvs.cu rezoluție DNS automată bazată pe numele serviciului. Aceasta înseamnă că, de exemplu, dacă serviciul bazei de date este apelat databaseOrice alt serviciu din aceeași rețea se poate conecta folosind doar database ca nume de gazdă.
Într-un proiect cu un frontend, un backend și o bază de date, puteți decide, de exemplu, să creați o rețea frontend și o rețea backend. Frontend-ul s-ar conecta la backend, iar backend-ul la baza de date, dar frontend-ul și baza de date nu ar trebui neapărat să partajeze o rețea , reducând astfel suprafața de atac internă.
În cod, acest lucru se traduce prin ceva la fel de simplu ca atribuirea rețelei corespunzătoare fiecărui serviciu și apoi definirea acelor rețele cu punți de driver. La nivel de aplicație, cea mai simplă abordare este utilizarea numele serviciului ca gazdă la configurarea conexiunilor: de app a databaseDe exemplu, pur și simplu indicând faptul că gazda bazei de date este „database”.
Volume în Docker Compose: Persistența datelor
Volumele sunt modalitatea recomandată de a persista informațiile generate de containere , cum ar fi bazele de date , fișierele utilizatorilor, copiile de rezervă etc. De asemenea, sunt utilizate pentru a partaja date între servicii din cadrul aceleiași stive.
În secțiune services Puteți monta volume direct cu volumesDar când vrei ca acel volum să fie accesibil prin mai multe containere sau vrei să îl gestionezi mai explicit, îl definești și în secțiunea superioară. volumes din fișierul compose.yaml.
Imaginați-vă că doriți să configurați un sistem de backup pentru baza de date. Serviciul bazei de date ar trebui să monteze un volum în care stochează datele și un alt serviciu dedicat backup-urilor care montează același volum în modul doar pentru citire pentru a efectua exporturi sau sincronizări fără a atinge containerul principal.
Docker vă permite să reglați fin configurațiile volumului cu mai mulți parametri (tip de driver, opțiuni specifice pentru drivere externe etc.), dar în majoritatea cazurilor este mai practic să lăsați Docker să gestioneze automat volumele fără a vă împotmoli în configurații ciudate.
Important este să clarificați ce foldere din serviciile dvs. trebuie să fie persistente și să le declarați ca volume în Compose, astfel încât să nu pierdeți date atunci când recreați containere sau actualizați imagini.
Configurații: gestionarea fișierelor de configurare
secțiune configs Este conceput pentru a gestiona fișierele de configurare de servicii din stiva dvs., similar volumelor, dar axat în mod special pe configurare.
Gândește-te la un server Apache sau Nginx care rulează în Docker. Probabil va trebui să ajustezi fișierul său de configurare destul de des. Reconstruirea imaginii de fiecare dată când modifici aceste fișiere este ineficientă și enervantă, mai ales în mediile în care parametrii sunt modificați frecvent.
cu configuri Puteți specifica în serviciul pe care îl doriți aplică o configurație specifică și apoi descrieți-l în secțiune configsExistă mai multe moduri de a le defini, cele mai comune fiind:
fileConfigurația este generată dintr-un fișier local.external: dacă este marcat catrueCompose presupune că configurația există deja și este doar referențiată.nameNumele intern al configurației în Docker, util la combinarea cuexternal: true.
În acest fel, puteți actualiza fișierul de configurare de pe mașina dvs. și reconstrui stiva fără a fi nevoie să reconstruiți imaginea de bază , păstrând codul imaginii separat de configurația specifică mediului.
Secrete: acreditări și date sensibile
secțiune secrets rezolvă o problemă clasicăUnde stochez parolele, cheile API și alte informații sensibile fără a le lăsa împrăștiate prin cod sau YAML?
Ca și în cazul configurațiilor, secretele pot fi definite în moduri diferite . Modul obișnuit este:
filesecretul este generat din conținutul unui fișier (de exemplu, un fișier text cu o cheie).environmentSecretul este creat folosind valoarea unei variabile de mediu din sistemul dumneavoastră.external: indică faptul că secretul a fost deja creat și trebuie doar referențiat, util pentru a evita suprascrierea secretelor gestionate din exterior.name: numele intern al secretului, relevant în special la combinareaexternal: truecu secrete create de un alt instrument.
Cu ajutorul secretelor, puteți permite containerelor care au nevoie de acces la aceste credențiale să le citească într-un mod controlat, fără a fi nevoie să le lăsați vizibile în depozitul de cod sau în fișierul compose.yaml în sine, consolidând semnificativ securitatea implementărilor.
Lucrul cu mai multe fișiere Composite și includeri
În proiectele mari, nu este neobișnuit ca aplicația dvs. să fie împărțită în mai multe servicii, uneori gestionate de echipe diferite. În aceste cazuri, este practic să separați configurația în mai multe fișiere Compose pentru a modulariza mai bine arhitectura.
O abordare tipică este de a avea un compose.yaml fișierul principal pentru aplicație și alte fișiere pentru părți ale infrastructurii. De exemplu, puteți mutați definiția Redis sau alte servicii de asistență pentru fișiere infra.yaml și păstrați în fișierul principal doar ceea ce privește direct aplicația dvs.
Pentru a face acest lucru, creați fișierul infra.yaml cu propria secțiune services unde lăsați, de exemplu, serviciul Redis complet. Apoi, în compose.yaml principal, adaugi o secțiune include care indică fișierul infra.yaml.
Când alergi docker compose up Din directorul proiectului, Compose Combinați ambele fișiere și afișează toate serviciile ca și cum ar fi într-un singur YAML, dar logica este în continuare separată și mai organizată.
Această tehnică facilitează întreținerea propriilor fișiere Compose de către diferite echipe și asamblarea aplicației globale folosind include-uri, ceea ce este foarte util în arhitecturi cu zeci de containere sau medii cu multă infrastructură partajată.
Comenzi esențiale Docker Compose
Deși Compose are un catalog bun de comenzi, majoritatea oamenilor folosesc doar câteva dintre ele în mod regulat, zilnic . Merită să le stăpânești, deoarece definesc fluxul de lucru.
Cel mai important este docker compose upAceastă comandă construiește imaginile necesare (dacă nu există deja), creează containerele, configurează rețelele și volumele și pornește toate serviciile definite în fișierul Compose. Este comanda pe care o utilizați atunci când doriți să porniți stiva.
De obicei, este combinată cu opțiunea -d să îl ruleze în modul „detașat”Adică, în fundal. În acest fel, nu umpli terminalul cu jurnale și poți continua să folosești acea sesiune pentru alte comenzi. De exemplu: docker compose up -d.
Pentru a opri și a curăța ceea ce ai ridicat, folosești docker compose downcare oprește și elimină containerele, rețelele și, opțional, imaginile și volumele asociate. Două semnalizatoare foarte comune aici sunt --rmi (pentru a șterge imagini) și -v (pentru a elimina volumele definite în secțiune volumes).
Dacă vrei să vezi ce containere fac parte din proiect și care este starea lor, poți rula docker compose psAceasta listează fiecare serviciu, starea sa (activ, închis etc.) și porturile expuse, ceea ce este foarte util pentru a verifica dacă totul funcționează corect după o up.
Când porniți stiva în modul detașat, jurnalele nu apar în terminal. Pentru a le vizualiza, trebuie să utilizați... docker compose logsfie global, fie prin filtrare după serviciu. Steagul -f Vă permite să urmăriți jurnalele în timp real, foarte util pentru depanarea unui anumit serviciu fără a fi nevoie să accesați interiorul recipientului.
Flux de lucru tipic: definește compose.yaml, executați o docker compose up -d, verificați cu docker compose ps, revizuiți jurnalele cu docker compose logs -f <servicio> Dacă ceva nu merge bine și când ați terminat, folosiți docker compose down să lași totul curat.
Dacă te rătăcești vreodată, docker compose --help Îți arată lista de subcomenzi și opțiuni disponibile pentru a te ajuta să-ți amintești ce face fiecare lucru fără a fi nevoie să consulți documentația.
Având în vedere toate cele de mai sus, acesta este un instrument cheie pentru oricine lucrează cu containere, dincolo de proiecte individuale. Vă permite să dezvoltați direct într-un mediu foarte similar (sau identic) cu cel de producție, servicii de control, rețele și date dintr-un simplu fișier YAML și să evitați o serie de probleme de compatibilitate și implementare care apar inevitabil atunci când lucrați doar „local”, fără containere. Odată ce vă obișnuiți să scrieți un fișier compose.yaml bun pentru proiectele dvs., este destul de dificil să reveniți la această situație.
Scriitor pasionat despre lumea octeților și a tehnologiei în general. Îmi place să îmi împărtășesc cunoștințele prin scriere și asta voi face în acest blog, să vă arăt toate cele mai interesante lucruri despre gadgeturi, software, hardware, tendințe tehnologice și multe altele. Scopul meu este să vă ajut să navigați în lumea digitală într-un mod simplu și distractiv.
