Inleiding tot Docker Compose

1. Overzicht

Bij intensief gebruik van Docker wordt het beheer van meerdere verschillende containers al snel omslachtig.

Docker Compose is een tool die ons helpt dit probleem op te lossen en Verwerk gemakkelijk meerdere containers tegelijk.

In deze tutorial zullen we de belangrijkste functies en krachtige mechanismen bekijken.

2. De YAML-configuratie uitgelegd

Kortom, Docker Compose werkt door veel regels toe te passen die erin zijn gedeclareerd een docker-compose.yml configuratiebestand.

Deze YAML-regels, zowel door mensen leesbaar als machinaal geoptimaliseerd, bieden ons een effectieve manier om het hele project in een paar regels van tienduizend voet te fotograferen.

Bijna elke regel vervangt een specifieke Docker-opdracht, zodat we uiteindelijk alleen maar hoeven uit te voeren:

docker-compose

We kunnen tientallen configuraties laten toepassen door Compose onder de motorkap. Dit bespaart ons het gedoe om ze te scripten met Bash of iets anders.

In dit bestand moeten we het versie van het Compose-bestandsformaat, ten minste één onderhoud, en optioneel volumes en netwerken:

versie: "3.7" diensten: ... volumes: ... netwerken: ... 

Laten we eens kijken wat deze elementen eigenlijk zijn.

2.1. Diensten

Allereerst, Diensten raadpleeg de configuratie van de containers.

Laten we bijvoorbeeld een docker-webtoepassing nemen die bestaat uit een front-end, een back-end en een database: we splitsen die componenten waarschijnlijk op in drie afbeeldingen en definiëren ze als drie verschillende services in de configuratie:

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

Er zijn meerdere instellingen die we op services kunnen toepassen, en we zullen ze later diepgaand onderzoeken.

2.2. Volumes en netwerken

VolumesAan de andere kant zijn dit fysieke gebieden met schijfruimte die worden gedeeld tussen de host en een container, of zelfs tussen containers. Met andere woorden, een volume is een gedeelde map in de host, zichtbaar vanuit sommige of alle containers.

Evenzo netwerken definieer de communicatieregels tussen containers en tussen een container en de host. Gemeenschappelijke netwerkzones zorgen ervoor dat de services van containers door elkaar kunnen worden ontdekt, terwijl privézones ze zullen scheiden in virtuele sandboxen.

Nogmaals, we zullen er meer over leren in de volgende sectie.

3. Een dienst ontleden

Laten we nu beginnen met het inspecteren van de belangrijkste instellingen van een service.

3.1. Een afbeelding trekken

Soms is de afbeelding die we nodig hebben voor onze service al gepubliceerd (door ons of door anderen) in Docker Hub of een andere Docker Registry.

Als dat het geval is, verwijzen we ernaar met de beeld attribuut, door de afbeeldingsnaam en tag op te geven:

services: my-service: afbeelding: ubuntu: laatste ... 

3.2. Een afbeelding opbouwen

In plaats daarvan moeten we mogelijk een afbeelding van de broncode bouwen door het Dockerfile.

Deze keer gebruiken we de bouwen trefwoord, waarbij het pad naar de Dockerfile wordt doorgegeven als de waarde:

services: mijn-aangepaste-app: build: / pad / naar / dockerfile / ... 

We kunnen ook een URL gebruiken in plaats van een pad:

services: mijn-aangepaste-app: build: //github.com/my-company/my-project.git ... 

Bovendien kunnen we een beeld naam in combinatie met de bouwen attribuut, dat de afbeelding een naam geeft zodra deze is gemaakt, zodat deze beschikbaar is voor gebruik door andere services:

services: mijn-aangepaste-app: build: //github.com/my-company/my-project.git afbeelding: mijn-project-afbeelding ... 

3.3. Het netwerk configureren

Docker-containers communiceren onderling in netwerken die, impliciet of via configuratie, zijn gemaakt door Docker Compose. Een service kan communiceren met een andere service op hetzelfde netwerk door er simpelweg naar te verwijzen op basis van containernaam en poort (bijvoorbeeld netwerkvoorbeelddienst: 80), op voorwaarde dat we de poort toegankelijk hebben gemaakt via de blootleggen trefwoord:

services: network-example-service: image: karthequian / helloworld: latest expose: - "80" 

In dit geval zou het trouwens ook werken zonder het bloot te stellen, omdat de blootleggen richtlijn staat al in de afbeelding Dockerfile.

Om een ​​container van de host te bereiken, de poorten moeten declaratief worden weergegeven via de poorten trefwoord, waardoor we ook kunnen kiezen of de poort anders wordt blootgesteld in de host:

services: netwerk-voorbeeld-service: image: karthequian / helloworld: nieuwste poorten: - "80:80" ... mijn-aangepaste-app: afbeelding: mijnapp: nieuwste poorten: - "8080: 3000" ... mijn- aangepaste-app-replica: afbeelding: myapp: laatste poorten: - "8081: 3000" ... 

Poort 80 is nu zichtbaar vanaf de host, terwijl poort 3000 van de andere twee containers beschikbaar zal zijn op poorten 8080 en 8081 in de host. Dit krachtige mechanisme stelt ons in staat om verschillende containers te laten draaien die dezelfde poorten blootleggen zonder botsingen.

Ten slotte kunnen we aanvullende virtuele netwerken definiëren om onze containers te scheiden:

services: netwerk-voorbeeld-service: image: karthequian / helloworld: nieuwste netwerken: - mijn-gedeeld-netwerk ... een andere-service-in-hetzelfde-netwerk: afbeelding: alpine: nieuwste netwerken: - mijn-gedeelde- netwerk ... een andere-service-in-zijn-eigen-netwerk: afbeelding: alpine: nieuwste netwerken: - mijn-privé-netwerk ... netwerken: mijn-gedeeld-netwerk: {} mijn-privé-netwerk: {} 

In dit laatste voorbeeld kunnen we dat zien een andere-service-in-hetzelfde-netwerk zal kunnen pingen en poort 80 van kunnen bereiken netwerk-voorbeeldservice, terwijl een andere-service-in-zijn-eigen-netwerk zal niet.

3.4. De volumes instellen

Er zijn drie soorten volumes: anoniem, genaamd, en gastheer degenen.

Docker beheert zowel anonieme als benoemde volumes, ze automatisch mounten in zelf gegenereerde mappen in de host. Hoewel anonieme volumes nuttig waren met oudere versies van Docker (vóór 1.9), zijn benoemde volumes tegenwoordig de aanbevolen manier om te gaan. Met hostvolumes kunnen we ook een bestaande map in de host specificeren.

We kunnen hostvolumes configureren op serviceniveau en benoemde volumes op het buitenste niveau van de configuratie, om deze laatste zichtbaar te maken voor andere containers en niet alleen voor de containers die ze toebehoren:

services: volumes-voorbeeld-service: image: alpine: nieuwste volumes: - mijn-naam-globaal volume: / mijn-volumes / naam-globaal-volume - / tmp: / mijn-volumes / host-volume - / home: / my-volumes / readonly-host-volume: ro ... another-volumes-example-service: image: alpine: laatste volumes: - my-named-global-volume: / another-path / the-same-named- global-volume ... volumes: my-named-global-volume: 

Hier hebben beide containers lees- / schrijftoegang tot het mijn-naam-globaal-volume gedeelde map, ongeacht de verschillende paden waaraan ze het hebben toegewezen. De twee hostvolumes zijn in plaats daarvan alleen beschikbaar voor volumes-voorbeeld-service.

De / tmp map van het bestandssysteem van de host is toegewezen aan de / mijn-volumes / host-volume map van de container.

Dit deel van het bestandssysteem is beschrijfbaar, wat betekent dat de container niet alleen bestanden kan lezen, maar ook kan schrijven (en verwijderen) op de hostcomputer.

We kunnen een volume in de modus alleen-lezen koppelen door : ro aan de regel, zoals voor de /huis map (we willen niet dat een Docker-container onze gebruikers per ongeluk wist).

3.5. De afhankelijkheden aangeven

Vaak moeten we een afhankelijkheidsketen tussen onze services creëren, zodat sommige services eerder worden geladen (en na) andere. We kunnen dit resultaat bereiken door de hangt af van trefwoord:

services: kafka: afbeelding: wurstmeister / kafka: 2.11-0.11.0.3 afhankelijk_on: - dierenverzorger ... dierenverzorger: afbeelding: wurstmeister / dierenverzorger ... 

We moeten ons er echter van bewust zijn dat Compose niet wacht op het dierentuinmedewerker service om het laden te voltooien voordat u de kafka service: het wacht gewoon tot het start. Als we een service volledig moeten laden voordat we een andere service starten, moeten we in Compose meer controle krijgen over de opstart- en afsluitvolgorde.

4. Omgevingsvariabelen beheren

Werken met omgevingsvariabelen is eenvoudig in Compose. We kunnen statische omgevingsvariabelen definiëren, en ook dynamische variabelen definiëren met de ${} notatie:

services: database: afbeelding: "postgres: $ {POSTGRES_VERSION}" omgeving: DB: mydb USER: "$ {USER}" 

Er zijn verschillende methoden om deze waarden aan Compose te geven.

Men plaatst ze bijvoorbeeld in een .env bestand in dezelfde map, gestructureerd als een .eigendommen het dossier, key = waarde:

POSTGRES_VERSION = alpine USER = foo

Anders kunnen we ze in het besturingssysteem instellen voordat we de opdracht aanroepen:

export POSTGRES_VERSION = alpine export USER = foo docker-compose up 

Ten slotte kunnen we het handig vinden om een ​​eenvoudige oneliner in de schaal te gebruiken:

POSTGRES_VERSION = alpine USER = foo docker-compose up 

We kunnen de benaderingen combineren, maar laten we in gedachten houden dat Compose de volgende prioriteitsvolgorde gebruikt, waarbij de minder belangrijke door de hogere worden overschreven:

  1. Stel een bestand op
  2. Shell omgevingsvariabelen
  3. Environment-bestand
  4. Dockerfile
  5. Variabele niet gedefinieerd

5. Schalen en replica's

In oudere Compose-versies mochten we de instanties van een container schalen via het docker-compose schaal opdracht. Nieuwere versies hebben het verouderd en vervangen door de schaal keuze.

Aan de andere kant kunnen we Docker Swarm - een cluster van Docker Engines - exploiteren en onze containers declaratief automatisch schalen via de replica's attribuut van de inzetten sectie:

services: worker: image: dockersamples / examplevotingapp_worker networks: - frontend - backend deploy: mode: gerepliceerde replica's: 6 resources: limieten: cpus: '0.50' geheugen: 50M reserveringen: cpus: '0.25' geheugen: 20M ... 

Onder inzetten, we kunnen ook veel andere opties specificeren, zoals de drempels voor resources. Stel echter samen beschouwt het geheel inzetten sectie alleen bij implementatie naar Swarm, en negeert het anders.

6. Een voorbeeld uit de echte wereld: Spring Cloud-gegevensstroom

Hoewel kleine experimenten ons helpen de afzonderlijke versnellingen te begrijpen, zal het zien van de real-world code in actie zeker het grote geheel onthullen.

Spring Cloud Data Flow is een complex project, maar eenvoudig genoeg om begrijpelijk te zijn. Laten we het YAML-bestand downloaden en uitvoeren:

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

Compose zal elk onderdeel downloaden, configureren en starten, en dan doorkruisen de logboeken van de container in een enkele stroom in de huidige terminal.

Het past ook unieke kleuren toe op elk van hen voor een geweldige gebruikerservaring:

Mogelijk krijgen we de volgende foutmelding bij het uitvoeren van een gloednieuwe Docker Compose-installatie:

lookup registry-1.docker.io: niet zo'n host

Hoewel er verschillende oplossingen zijn voor deze veelvoorkomende valkuil, is het gebruik van 8.8.8.8 aangezien DNS waarschijnlijk de eenvoudigste is.

7. Levenscyclusbeheer

Laten we eindelijk de syntaxis van Docker Compose eens nader bekijken:

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

Hoewel er veel opties en opdrachten beschikbaar zijn, moeten we in ieder geval weten welke opties en opdrachten het hele systeem correct kunnen activeren en deactiveren.

7.1. Opstarten

We hebben gezien dat we de containers, de netwerken en de volumes die zijn gedefinieerd in de configuratie met kunnen maken en starten omhoog:

docker-compose

Na de eerste keer kunnen we echter gewoon gebruiken begin om de services te starten:

docker-compose start

In het geval dat ons bestand een andere naam heeft dan de standaardnaam (docker-compose.yml), kunnen we de -f en het dossier vlaggen om een ​​alternatieve bestandsnaam op te geven:

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

Compose kan ook op de achtergrond worden uitgevoerd als een daemon wanneer het wordt gestart met de -d keuze:

docker-compose up -d

7.2. Afsluiten

Om de actieve services veilig te stoppen, kunnen we gebruik maken van hou op, waarmee containers, volumes en netwerken worden behouden, samen met elke wijziging die eraan wordt aangebracht:

docker-compose stop

Om de status van ons project te resetten, rennen we gewoon naar beneden, die alles zal vernietigen, met uitzondering van externe volumes:

docker-compose neer

8. Conclusie

In deze tutorial hebben we geleerd over Docker Compose en hoe het werkt.

Zoals gewoonlijk kunnen we de bron vinden docker-compose.yml bestand op GitHub, samen met een nuttige reeks tests die onmiddellijk beschikbaar zijn in de volgende afbeelding: