Docker compose med den tilhørende docker-compose.yaml filen er en metode som gjør noe av den samme forenklingen for å kjøre containere som Dockerfile gjør for å bygge containere. Ofte trenger man å legge til mange flagg og opsjoner når man starter en container og dette kan gi lange og uoversiktlige docker container run-kommandoer. Man kan gjøre dette på en mye mer ryddig og systematisk måte ved å definere alt som skal skje når man starter en container i en docker-compose.yaml fil. Man kan i en slik fil også velge å starte flere samtidige containere som skal samarbeide om å gi den tjenesten man ønsker. For eksempel kan man med Docker compose samtidig starte både en webserver og en database-server som webserveren henter dataene sine fra. Generelt kan man bruke dette til å sette opp mange forskjellig typer oppsett av samtidige containere på en ryddig og oversiktlig måte. Dermed er det også enkelt å endre på konfigurasjonen og stoppe og starte hele clusteret av containere for å få alt til å virke som man ønsker.
YAML sto opprinnelig for "Yet Another Markup Language" og er som XML et maskinlesbart format som også er inspirert av Python i den forstand at riktig innrykk i teksten er viktig og det fører til feilmeldinger om dette ikke er riktig definert. Derfor må man være svært nøye med innrykk/antall mellomrom og også med å ha mellomrom på riktige steder. Dette gir noe av de samme syntaks-problemene som ved bash-scripting, derfor er det også her en god strategi å sakte bygge opp en docker-compose.yaml fil og teste hver gang man gjør endringer.
services: hello: image: hello-world:latest |
Tidligere var det vanlig å starte med en linje av typen version: '3.0'
som forteller hvilken Yaml-versjon som
skal brukes, men det er ikke lenger nødvendig. Filen viser alle services som skal være med. I dette er det kun en som vi gir navnet 'hello'.
Deretter følger hvilket image som skal brukes. Dermed er man klar til å kjøre hello-world containeren med:
root@os180:~/compose# docker compose up [+] Running 1/1 ✔ Container compose-hallo-1 Created Attaching to hallo-1 hallo-1 | hallo-1 | Hello from Docker! |
Tidligere var kommandoen docker-compose up
og hvis man prøver det får man nå en feilmelding.
Hvis man her ikke markerer at 'hello' er en av tjenestene og skriver filen slik:
services: hello: image: hello-world:latest |
får man med en gang en feilmelding:
root@os180:~/compose# docker compose up services.image must be a mapping |
services: nginx: image: nginx:latest |
og starte tjenesten med
root@os180:~/compose# docker compose up -d [+] Running 1/1 ✔ Container compose-ng1-1 Started root@os180:~/compose# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 14d123a939af nginx:latest “/docker-entrypoint.…” 8 seconds ago Up 7 seconds 80/tcp compose-ng1-1 |
Hvis dette er første gang man laster ned nginx-imaget, vil det først lastes ned på samme måte som når
man kjører docker run nginx
. Deretter kan man stoppe det hele med:
root@os180:~/compose# docker compose down [+] Running 2/2 ✔ Container compose-ng1-1 Removed ✔ Network compose_default Removed |
Docker compose rydder opp etter seg ved å fjerne containeren som ble kjørt.
Hvis man ønsker at port 80 som nginx default bruker som source port skal vises som port 8080 på host'en som kjører containeren, kan man gjøre det ved å definere følgende i yaml-filen:
services: nginx: image: nginx:latest ports: - 8080:80 |
Generelt kan alle parametre og opsjoner man kan gi til docker container run
defineres i yaml-filen. Deretter kan man starte nginx:
root@os180:~/compose# docker compose up -d [+] Running 0/1 ⠙ Network compose_default Creating [+] Running 2/2d ✔ Network compose_default Created ✔ Container compose-ng1-1 Started root@os180:~/compose# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6ba1338871fa nginx:latest “/docker-entrypoint.…” 34 seconds ago Up 33 seconds 0.0.0.0:8080->80/tcp compose-ng1-1 |
og man vil kunne få en hilsen fra nginx:
# curl localhost:8080 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> |
Videre kan man på en enkel måte definere en mappe på host'en som nginx skal hente sine web-sider fra ved å legge til følgende rett under ports: i yaml-filen:
volumes: - ./innhold:/usr/share/nginx/html:ro |
Dette gjør at man nå vil få opp innhold/index.html filen på host'en når man starter nginx.
Følgende yaml-fil definerer to containere som leverer forskjellig innhold på henholdsvis port 8080 og 8081:
services: nginx: image: nginx:latest ports: - 8080:80 volumes: - ./innhold:/usr/share/nginx/html:ro nginx2: image: nginx:latest ports: - 8081:80 volumes: - ./innhold2:/usr/share/nginx/html:ro |
Dermed kan man starte begge containerene samtidig og se at de virker som de skal. Og stoppe begge etterpå.
root@os180:~/compose# docker compose up -d --remove-orphans [+] Running 3/3 ✔ Network compose_default Created 0.4s ✔ Container compose-ng1-1 Started 0.9s ✔ Container compose-ng2-1 Started 0.8s root@os180:~/compose# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f0343357eb3a nginx:latest “/docker-entrypoint.…” 6 seconds ago Up 6 seconds 0.0.0.0:8081->80/tcp compose-ng2-1 cc1dfa99cf5c nginx:latest “/docker-entrypoint.…” 6 seconds ago Up 6 seconds 0.0.0.0:8080->80/tcp compose-ng1-1 root@os180:~/compose# curl localhost:8080 hei root@os180:~/compose# curl localhost:8081 hei fra 2 root@os180:~/compose# docker compose down [+] Running 3/3 ✔ Container compose-ng2-1 Removed 0.8s ✔ Container compose-ng1-1 Removed 0.9s ✔ Network compose_default Removed |
Om man går inn i den ene nginx og installerer ping og ifconfig (med apt install iputils-ping net-tools) vil man kunne se at man kan kommunisere over det lokale private nettverket med den andre containeren ved å bruke navnet som er definert i yaml-filen:
# docker exec -it f2 bash root@f2d45f6e9bf5:/# ping nginx2 PING nginx2 (192.168.32.3) 56(84) bytes of data. 64 bytes from test_nginx2_1.test_default (192.168.32.3): icmp_seq=1 ttl=64 time=0.137 ms |
De to containerene har IPer 192.168.32.3 og 192.168.32.2 og kan kommunisere med hverandre som på andre nettverk. Dette gjør det mulig å sette opp relistiske systemer, ikke minst for å teste kode som man utvikler for dette service-scenariet.
Hvis man for eksempel ønsker å gi containeren et eget navn, kan man bruke variabelen container_name.
services: nginx: build: ./nginx ports: - 8080:80 |
Dermed vil docker-compose prøve å bygge et image fra Dockerfile i mappen ./nginx og starte en container med det image't som er resultatet av denne byggingen. Og man kan sette opp en oversiktlig mappestruktur som definerer alle containerene som er med i et compose-prosjekt.
Opptak av forelesningen inndelt etter temaer:
linux10del1.mp4
(04:26) Grunnleggende om hva virtualisering er. Hardware, hypervisor og gjeste-OS
linux10del2.mp4
(17:30) Hvorfor virtualisering? Isolasjon, Ressurssparing, Fleksibilitet, Programvare-utvikling, Skytjenester
linux10del3.mp4
(07:39) Historie, Sensitive og priviligerte instruksjoner
linux10del4.mp4
(03:09) Hardwarestøttet virtualisering, hypervisor i kernel mode, gjeste-OS i user mode
linux10del5.mp4
(02:56) Poll med gjennomgang av svar på hva som IKKE er en av fordelene vet virtualisering: effiktivitet
linux10del6.mp4
(04:20) Oppsummering av hardwarestøttet virtualisering
linux10del7.mp4
(08:01) Type 1 & Type 2 hypervisor, binær oversettelse, paravirtualisering
Alle disse fordelene gjelder også for containere og Docker, bortsett fra den første, isolasjon og sikkerhet. Men fleksibiliteten blir enda større med containere.
https://www.cs.oslomet.no/teaching/materials/MS100A/html/NSA.html
Eksempel: