Skip to content

Opdracht 8 - Docker Compose

Doel

⚠️ Deze opdracht bouwt voort op de vorige opdracht, dus zorg ervoor dat je die hebt afgerond!

Tijdens deze opdracht leer je hoe je Docker Compose gebruikt om meerdere containers eenvoudig te beheren. Je automatiseert de opstartprocedure van een multi-container applicatie, waardoor je minder handmatige configuratie nodig hebt.

Na deze opdracht kan je:

  • Een docker-compose.yml bestand schrijven en begrijpen.
  • Meerdere containers opstarten en configureren met Docker Compose.
  • Logs en statusinformatie van alle containers in een Compose-project bekijken.

Docker Compose installatie controleren

In de vorige opdracht hebben we reeds twee containers gestart binnen hetzelfde Docker netwerk. We hebben deze ook al met elkaar laten communiceren.

Dit omvatte echter veel manuele stappen, wat minder onderhoudbaar is. We hebben een manier nodig om dit proces te automatiseren. Docker Compose is hiervoor een handige tool. Hiermee kan je meerdere containers starten en configureren met een enkel commando. Je plaatst een gelijkaardige configuratie als bij het docker run commando in een bestand. Docker Compose zal deze configuratie interpreteren, de nodige volumes en netwerken aanmaken, en vervolgens de containers starten en configureren. Dit bestand is eenvoudig te delen met andere ontwikkelaars en kan ook gebruikt worden om de containers te starten in een productieomgeving.

Indien je alle stappen uit opdracht 5 hebt gevolgd, zou Docker Compose reeds geïnstalleerd moeten zijn. Je kan dit controleren door de geïnstalleerde versie op te vragen:

Bash
docker compose version

⚠️ Let op: we gebruiken hier de Docker Compose plugin (= Docker Compose v2) aangezien het docker-compose script verouderd is. Sommige online tutorials gebruiken nog het oude script. Het is dus belangrijk om de juiste commando's te gebruiken!

Mocht Docker Compose niet geïnstalleerd zijn, dan kan je dit doen met het volgende commando:

Bash
sudo apt install -y docker-compose-plugin

Docker Compose gebruiken

We gaan nu een Docker Compose configuratiebestand maken. Dit bestand zal de configuratie bevatten voor de todo-applicatie. Maak een nieuw bestand aan met de naam docker-compose.yml in de map getting-started/app. Voeg hierin de onderstaande inhoud toe. Je ziet onderaan dit bestand de definitie van een volume todo-db en een netwerk todo-app. Daarboven zie je een duidelijke beschrijving van de MySQL container. Zoek de gelijkenissen met het docker run commando.

YAML
# getting-started/app/docker-compose.yml
services:
    mysql:
        image: mysql:8.0
        restart: on-failure
        volumes:
            - todo-db:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: letmein
            MYSQL_DATABASE: todos
        networks:
            - todo-app

    # TODO: vul aan met de configuratie voor de todo-app container

volumes:
    todo-db:

networks:
    todo-app:

Stop en verwijder alle vorige containers uit de vorige opdracht. Start vervolgens deze container op met het volgende commando:

Bash
docker compose up

ℹ️ Merk op dat indentatie in YAML bestanden belangrijk is. Zorg ervoor dat de indentatie in het hele bestand consistent is.

Vul dit bestand aan met de code voor de applicatiecontainer. Wijzig niets aan de reeds gegeven code, vul enkel aan waar de TODO staat. Houd hierbij rekening met de volgende zaken voor de todo-app service:

  • moet afhankelijk zijn van de mysql service.
  • moet de poort 3000 van de host naar de poort 3000 van de container mappen.
  • moet de nodige omgevingsvariabelen instellen om verbinding te maken met de MySQL database.
  • moet verbonden zijn met het todo-app netwerk.
  • mag geen hardgecodeerde image gebruiken. In plaats daarvan moet deze de Dockerfile in de huidige directory gebruiken om de image te bouwen.
  • moet automatisch herstarten bij een fout.

Bouw de todo-app image en start de nieuwe container met het volgende commando. Je zal zien dat Docker Compose eerst de image bouwt en vervolgens de todo-app container opstart. Als de databankcontainer al draait van de vorige stap, zal deze niet opnieuw opgestart worden.

Bash
docker compose up --build

Controleer of je de todo-applicatie kan bereiken via je webbrowser op http://localhost:3000.

De restart optie is handig om ervoor te zorgen dat de containers automatisch opnieuw opstarten bij een fout. Dit is vooral nuttig in productieomgevingen waar je wil dat de applicatie altijd beschikbaar is.

Als je nu Ctrl-c uitvoert, sluiten de containers weer af. Hoe kan je ervoor zorgen dat Docker Compose de containers op de achtergrond uitvoert?

De -d optie kan je gebruiken om de containers op de achtergrond uit te voeren:

Bash
docker compose up -d
Hoe kan ik de logs zien van alle containers in het docker-compose.yml bestand? Je kan dit doen met een enkel commando. Welke optie kan ik gebruiken als ik de logs live wil volgen?

Je kan de logs van alle containers bekijken met het volgende commando:

Bash
docker compose logs

Om de logs live te volgen, gebruik je de -f optie:

Bash
docker compose logs -f
Hoe kan ik de status van alle containers in het docker-compose.yml bestand bekijken?

Je kan de status van alle containers bekijken met het volgende commando:

Bash
docker compose ps
Hoe stop ik de containers met een enkel commando als de containers op de achtergrond draaien?

Je kan de containers stoppen met het volgende commando:

Bash
docker compose stop
Hoe verwijder je de containers die met Docker Compose zijn opgestart?

Je kan de containers verwijderen met het volgende commando:

Bash
docker compose down

Als je ook de bijhorende volumes wil verwijderen, dan kan je de -v optie gebruiken:

Bash
docker compose down -v

De opdrachten omtrent Docker en Docker Compose stoppen hier. Verdere uitdieping zal gebeuren binnen het OLOD System Engineering Lab. Onthoud dat Docker en Docker Compose krachtige tools zijn voor het beheren van containerized applicaties. Blijf experimenteren en verkennen om je vaardigheden verder te ontwikkelen! Dit is een must have skill voor elke moderne ontwikkelaar of systeembeheerder.

Oplossing docker-compose.yml

Een mogelijke oplossing voor het docker-compose.yml bestand is de volgende:

YAML
# getting-started/app/docker-compose.yml
services:
    mysql:
        image: mysql:8.0
        restart: on-failure
        volumes:
            - todo-db:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: letmein
            MYSQL_DATABASE: todos
        networks:
            - todo-app

    todo-app:
        build: . # <- verwijst naar de huidige directory
        restart: on-failure
        depends_on:
            - mysql
        ports:
            - 3000:3000
        environment:
            MYSQL_HOST: mysql
            MYSQL_USER: root
            MYSQL_PASSWORD: letmein
            MYSQL_DB: todos
        networks:
            - todo-app

volumes:
    todo-db:

networks:
    todo-app:

Hiermee kan je met één commando de todo-app image bouwen en de containers starten:

Bash
docker compose up --build

Merk op dat de build: . regel in de todo-app service aangeeft dat Docker Compose de Dockerfile in de huidige directory moet gebruiken om de image te bouwen. Hiervoor moet je wel de --build optie gebruiken bij het opstarten van de containers. Als je deze optie weglaat, zal Docker Compose enkel een image bouwen als deze nog niet bestaat.

Uitdaging (optioneel)

Hieronder vind je enkele optionele uitdagingen om je kennis van Docker Compose verder te verdiepen. We laten bewust de stappen richting de oplossing open, zodat je zelf kan experimenteren en leren. We geven op het einde van deze sectie wel de oplossing in een info box.

Adminer

Breid de docker-compose.yml uit met een nieuwe service genaamd adminer. Adminer is een lichtgewicht database beheer tool die je kan gebruiken om de MySQL database te beheren via een webinterface.

Controleer ook of je vanuit de webinterface van Adminer verbinding kan maken met de MySQL database en de todos database kan bekijken.

Health checks

Health checks worden gebruikt om te controleren of de containers correct functioneren. Voeg health checks toe aan de mysql service in het docker-compose.yml bestand.

Pas vervolgens de todo-app en adminer service aan zodat deze wacht tot de mysql service gezond is voordat hij opstart.

Oplossing uitdagingen docker-compose.yml

Een mogelijke oplossing voor de uitdagingen is de volgende:

YAML
# getting-started/app/docker-compose.yml
services:
    mysql:
        image: mysql:8.0
        restart: on-failure
        volumes:
            - todo-db:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: letmein
            MYSQL_DATABASE: todos
        networks:
            - todo-app
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
            interval: 10s
            timeout: 5s
            retries: 5

    todo-app:
        build: . # <- verwijst naar de huidige directory
        restart: on-failure
        depends_on:
            mysql:
                condition: service_healthy
        ports:
            - 3000:3000
        environment:
            MYSQL_HOST: mysql
            MYSQL_USER: root
            MYSQL_PASSWORD: letmein
            MYSQL_DB: todos
        networks:
            - todo-app

    adminer:
        image: adminer
        restart: on-failure
        depends_on:
            mysql:
                condition: service_healthy
        ports:
            - 8080:8080
        networks:
            - todo-app

volumes:
    todo-db:

networks:
    todo-app:

In deze oplossing hebben we een nieuwe service adminer toegevoegd die de Adminer image gebruikt en poort 8080 van de host naar poort 8080 van de container mapt. Aanmelden kan met de volgende gegevens:

  • System: MySQL / MariaDB
  • Server: mysql
  • Username: root
  • Password: letmein

Daarnaast hebben we een health check toegevoegd aan de mysql service die controleert of de MySQL server reageert op pings. De todo-app en adminer service zijn aangepast zodat deze wacht tot de mysql service gezond is voordat hij opstart, door gebruik te maken van depends_on met de condition: service_healthy optie.

Extra informatie