Introduktion til Docker Compose

1. Oversigt

Når du bruger Docker i udstrakt grad, bliver styringen af ​​flere forskellige containere hurtigt besværlig.

Docker Compose er et værktøj, der hjælper os med at løse dette problem og håndter let flere containere på én gang.

I denne vejledning ser vi på dens hovedfunktioner og kraftfulde mekanismer.

2. YAML-konfigurationen forklaret

Kort sagt fungerer Docker Compose ved at anvende mange regler, der er erklæret inden for en enkelt docker-compose.yml konfigurationsfil.

Disse YAML-regler, både menneskeligt læsbare og maskineoptimerede, giver os en effektiv måde at snapshot hele projektet fra ti tusind fod i et par linjer.

Næsten hver regel erstatter en bestemt Docker-kommando, så i sidste ende skal vi bare køre:

docker-komponere op

Vi kan få snesevis af konfigurationer anvendt af Compose under emhætten. Dette sparer os besværet med at script dem med Bash eller noget andet.

I denne fil skal vi specificere version af Compose-filformatet, mindst en serviceog eventuelt volumener og netværk:

version: "3.7" -tjenester: ... bind: ... netværk: ... 

Lad os se, hvad disse elementer faktisk er.

2.1. Tjenester

Først og fremmest, tjenester se containernes konfiguration.

Lad os f.eks. Tage en dockeriseret webapplikation, der består af en frontend, en backend og en database: Vi vil sandsynligvis opdele disse komponenter i tre billeder og definere dem som tre forskellige tjenester i konfigurationen:

tjenester: frontend: image: my-vue-app ... backend: image: my-springboot-app ... db: image: postgres ... 

Der er flere indstillinger, som vi kan anvende på tjenester, og vi vil undersøge dem dybt senere.

2.2. Volumener og netværk

Volumenerderimod er fysiske områder af diskplads delt mellem værten og en container eller endda mellem containere. Med andre ord, et bind er et delt bibliotek i værten, synlig fra nogle eller alle containere.

Tilsvarende netværk definere kommunikationsreglerne mellem containere og mellem en container og værten. Almindelige netværkszoner vil gøre containertjenester synlige af hinanden, mens private zoner adskiller dem i virtuelle sandkasser.

Igen lærer vi mere om dem i næste afsnit.

3. Dissekering af en tjeneste

Lad os nu begynde at inspicere hovedindstillingerne for en tjeneste.

3.1. Trækker et billede

Nogle gange er det billede, vi har brug for til vores service, allerede blevet offentliggjort (af os eller andre) i Docker Hub eller et andet Docker-register.

Hvis det er tilfældet, henviser vi til det med billede attribut ved at angive billednavnet og taggen:

tjenester: min-tjeneste: image: ubuntu: nyeste ... 

3.2. Opbygning af et billede

I stedet skal vi muligvis oprette et billede fra kildekoden ved at læse dets Dockerfil.

Denne gang bruger vi bygge nøgleord, der sender stien til Dockerfilen som værdien:

tjenester: min-brugerdefinerede app: build: / sti / til / dockerfil / ... 

Vi kan også bruge en URL i stedet for en sti:

tjenester: min-brugerdefinerede app: build: //github.com/my-company/my-project.git ... 

Derudover kan vi specificere en billede navn i forbindelse med bygge attribut, som vil navngive billedet, når det er oprettet, hvilket gør det tilgængeligt til brug af andre tjenester:

tjenester: min-brugerdefinerede app: build: //github.com/my-company/my-project.git image: mit-projekt-billede ... 

3.3. Konfiguration af netværk

Docker-containere kommunikerer indbyrdes i netværk oprettet implicit eller gennem konfiguration af Docker Compose. En tjeneste kan kommunikere med en anden tjeneste på det samme netværk ved blot at henvise til den med containernavn og port (for eksempel netværk-eksempel-service: 80), forudsat at vi har gjort porten tilgængelig via udsætte nøgleord:

tjenester: netværk-eksempel-service: billede: karthequian / helloworld: seneste eksponering: - "80" 

I dette tilfælde fungerer det forresten også uden at udsætte det, fordi udsætte direktivet findes allerede i billedet Dockerfile.

For at nå en container fra værten, havnene skal eksponeres deklarativt gennem porte nøgleord, som også giver os mulighed for at vælge, om porten skal eksponeres anderledes i værten:

tjenester: netværk-eksempel-service: image: karthequian / helloworld: nyeste porte: - "80:80" ... min-brugerdefinerede app: image: myapp: nyeste porte: - "8080: 3000" ... my- custom-app-replica: image: myapp: seneste porte: - "8081: 3000" ... 

Port 80 vil nu være synlig fra værten, mens port 3000 til de to andre containere vil være tilgængelig på port 8080 og 8081 i værten. Denne kraftfulde mekanisme giver os mulighed for at køre forskellige containere, der udsætter de samme porte uden kollisioner.

Endelig kan vi definere yderligere virtuelle netværk til at adskille vores containere:

tjenester: netværk-eksempel-service: billede: karthequian / helloworld: nyeste netværk: - mit-delte-netværk ... en anden-tjeneste-i-det samme netværk: billede: alpine: nyeste netværk: - min-delt- netværk ... en anden service-i-sit-eget-netværk: billede: alpine: nyeste netværk: - mit-private-netværk ... netværk: mit-delte-netværk: {} mit-private-netværk: {} 

I dette sidste eksempel kan vi se det en anden service-i-det samme netværk vil være i stand til at pinge og nå port 80 i netværk-eksempel-service, mens en anden service-i-sit-eget-netværk vil ikke.

3.4. Opsætning af lydstyrken

Der er tre typer bind: anonym, som hedderog vært dem.

Docker administrerer både anonyme og navngivne diskenheder, automatisk montering af dem i selvgenererede mapper i værten. Mens anonyme diskenheder var nyttige med ældre versioner af Docker (før 1.9), er navngivne den foreslåede vej at gå i dag. Værtsvolumener giver os også mulighed for at specificere en eksisterende mappe i værten.

Vi kan konfigurere værtsvolumener på serviceniveau og navngivne diskenheder i det ydre niveau i konfigurationen for at gøre sidstnævnte synlige for andre containere og ikke kun for den, de hører til:

services: volumes-eksempel-service: image: alpine: seneste volumes: - my-named-global-volume: / my-volumes / named-global-volume - / tmp: / my-volumes / host-volume - / home: / my-volumes / readonly-host-volume: ro ... another-volumes-example-service: image: alpine: latest volumes: - my-named-global-volume: / another-path / the-same-named- global-volume ... volumes: my-named-global-volume: 

Her vil begge containere have læse- / skriveadgang til my-named-global-volume delt mappe, uanset de forskellige stier, de har kortlagt den til. De to værtsvolumener vil i stedet kun være tilgængelige for mængder-eksempel-service.

Det / tmp mappen til værtens filsystem er tilknyttet / my-volumes / host-volume mappe på containeren.

Denne del af filsystemet kan skrives, hvilket betyder, at containeren ikke kun kan læse, men også skrive (og slette) filer i værtsmaskinen.

Vi kan montere en lydstyrke i skrivebeskyttet tilstand ved at tilføje : ro til reglen, ligesom for /hjem mappe (vi ønsker ikke, at en Docker-container sletter vores brugere ved en fejltagelse).

3.5. Erklæring om afhængigheder

Ofte er vi nødt til at oprette en afhængighedskæde mellem vores tjenester, så nogle tjenester bliver indlæst før (og aflæsset efter) andre. Vi kan opnå dette resultat gennem afhænger af nøgleord:

tjenester: kafka: billede: wurstmeister / kafka: 2.11-0.11.0.3 afhænger af: - zookeeper ... zookeeper: image: wurstmeister / zookeeper ... 

Vi skal dog være opmærksomme på, at Compose ikke vil vente på dyrepasser service for at afslutte indlæsningen inden start af kafka service: den venter simpelthen på, at den starter. Hvis vi har brug for en tjeneste, der skal læsses fuldt ud, inden vi starter en anden tjeneste, skal vi få dybere kontrol med opstarts- og nedlukningsrækkefølgen i Compose.

4. Styring af miljøvariabler

At arbejde med miljøvariabler er let i Compose. Vi kan definere statiske miljøvariabler og også definere dynamiske variabler med ${} notation:

services: database: image: "postgres: $ {POSTGRES_VERSION}" miljø: DB: mydb BRUGER: "$ {USER}" 

Der er forskellige metoder til at give disse værdier til Compose.

For eksempel sætter man dem i en .env fil i samme bibliotek, struktureret som en .ejendomme fil, nøgle = værdi:

POSTGRES_VERSION = alpin USER = foo

Ellers kan vi indstille dem i operativsystemet, før vi kalder kommandoen:

eksport POSTGRES_VERSION = alpin eksport USER = foo docker-compose up 

Endelig kan vi finde praktisk ved hjælp af en simpel one-liner i skallen:

POSTGRES_VERSION = alpine USER = foo docker-komponere op 

Vi kan blande fremgangsmåderne, men lad os huske på, at Compose bruger følgende prioritetsrækkefølge og overskriver de mindre vigtige med de højere:

  1. Skriv fil
  2. Shell miljøvariabler
  3. Miljøfil
  4. Dockerfil
  5. Variabel ikke defineret

5. Skalering og replikaer

I ældre Compose-versioner fik vi lov til at skalere forekomsterne af en container gennem docker-compose-skala kommando. Nyere versioner udfasede det og erstattede det med vægt mulighed.

På den anden side kan vi udnytte Docker Swarm - en klynge af Docker-motorer - og autoskalere vores containere erklærende gennem replikaer attribut for indsætte afsnit:

tjenester: arbejdstager: image: dockersamples / examplevotingapp_worker netværk: - frontend - backend deploy: mode: replikerede replikaer: 6 ressourcer: grænser: cpus: '0,50' hukommelse: 50M reservationer: cpus: '0,25' hukommelse: 20M ... 

Under indsætte, Vi kan også angive mange andre muligheder, som ressourcetærsklerne. Komponere dog betragter helheden indsætte sektion kun, når den implementeres til Swarmog ignorerer det ellers.

6. Et virkeligt eksempel: Spring Cloud Data Flow

Mens små eksperimenter hjælper os med at forstå de enkelte gear, vil det helt klart afsløre det store billede at se den virkelige verdens kode.

Spring Cloud Data Flow er et komplekst projekt, men enkelt nok til at være forståeligt. Lad os downloade dens YAML-fil og køre:

DATAFLOW_VERSION = 2.1.0.RELEASE SKIPPER_VERSION = 2.0.2.RELEASE docker-compose up 

Compose downloader, konfigurerer og starter hver komponent og derefter skær containerens logfiler i en enkelt strøm i den aktuelle terminal.

Det vil også anvende unikke farver på hver enkelt af dem for en fantastisk brugeroplevelse:

Vi får muligvis følgende fejl i at køre en helt ny Docker Compose-installation:

opslag registry-1.docker.io: ingen sådan vært

Mens der er forskellige løsninger på denne almindelige faldgrube ved hjælp af 8.8.8.8 som DNS er sandsynligvis den enkleste.

7. Lifecycle Management

Lad os endelig se nærmere på syntaksen for Docker Compose:

docker-compose [-f ...] [optioner] [COMMAND] [ARGS ...] 

Mens der er mange muligheder og kommandoer til rådighed, skal vi i det mindste kende dem, der aktiverer og deaktiverer hele systemet korrekt.

7.1. Start op

Vi har set, at vi kan oprette og starte containere, netværk og diskenheder defineret i konfigurationen med op:

docker-komponere op

Efter første gang kan vi dog bare bruge Start at starte tjenesterne:

docker-compose start

Hvis vores fil har et andet navn end standardnavnet (docker-compose.yml), kan vi udnytte -f og fil markerer for at angive et alternativt filnavn:

docker-compose -f custom-compose-file.yml start

Compose kan også køre i baggrunden som en dæmon, når den startes med -d mulighed:

docker-komponere op -d

7.2. Lukke ned

For sikkert at stoppe de aktive tjenester kan vi bruge hold op, som bevarer containere, volumener og netværk sammen med enhver ændring foretaget på dem:

docker-compose stop

For at nulstille status for vores projekt i stedet kører vi simpelthen ned, som vil ødelægge alt med kun undtagelse af eksterne volumener:

docker-komponere ned

8. Konklusion

I denne vejledning har vi lært om Docker Compose, og hvordan det fungerer.

Som normalt kan vi finde kilden docker-compose.yml fil på GitHub sammen med et nyttigt batteri af tests, der straks er tilgængelige i følgende billede: