Skip to content

Opdracht 6 - Port bindings en volumes

Doel

Tot nu toe hebben we alleen Docker-containers op de CLI gebruikt. De meeste applicaties verwachten echter meer interactie of input. Tijdens deze opdracht gaan we een website opzetten via Docker.

Na deze opdracht kan je:

  • Port bindings gebruiken
  • Volumes gebruiken

Port bindings

Een webserver biedt zijn website aan via poort 80 (HTTP) of via poort 443 (HTTPS). We willen een webserver draaien in een container om snel een website online te zetten. We gebruiken hiervoor de software nginx. De ontwikkelaars bieden ook een Docker image aan voor nginx.

Voer het volgende commando uit:

Bash
docker run nginx
Kan je de website bereiken via http://localhost?

Nee, de website is niet bereikbaar.

Je zal de website niet kunnen bereiken: nginx zit immers in een geïsoleerde container en kan niet bij de host. De host kan dus ook niet bij nginx in de container. Een onbereikbare webserver is niet interessant. Daarom gaan we een poort van de host verbinden met een poort van de container.

Stop de vorige container met Ctrl-c en start een nieuwe container met het volgende commando:

Bash
docker run -p 80:80 nginx
Kan je nu de website bereiken?

Ja, nu kan je de website bereiken via http://localhost.

nginx welkomstpagina

-p zorgt ervoor dat een poort van de container wordt gekoppeld aan een poort van de host. In dit geval wordt poort 80 van de host gekoppeld aan poort 80 van de container.

De poort van de host en de container hoeven niet hetzelfde te zijn. De benodigde poort van de container is bepaald door de maker van de image, maar de poort van de host kan je zelf kiezen.

Stop de vorige container en start een nieuwe container met het volgende commando:

Bash
docker run -p 8123:80 nginx

In dit geval wordt poort 8123 van de host gekoppeld aan poort 80 van de container.

Als je een hard refresh1 doet (Ctrl-F5), dan zal je zien dat de website niet meer bereikbaar is op http://localhost. Welke URL moet je nu invoeren?

Je moet nu http://localhost:8123 invoeren.

Volumes

De website die we zien is de standaardwebsite van nginx. Dit is niet zo interessant, we willen graag dat onze website wordt getoond.

Container file system

Start opnieuw een webserver en zorg dat je deze kan zien in jouw webbrowser.

Bash
docker run -p 8001:80 nginx

Open een tweede terminal en zoek het ID van de nginx-webservercontainer op met docker container ls (80852258314d in onderstaand voorbeeld).

Bash
1
2
3
$ docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS        PORTS                                     NAMES
80852258314d   nginx     "/docker-entrypoint. ..."   2 seconds ago   Up 1 second   0.0.0.0:8001->80/tcp, [::]:8001->80/tcp   elegant_cartwright

Volgens de documentatie op Docker Hub bevindt de website zich in de directory /usr/share/nginx/html in de container. Het commando docker exec laat je een commando uitvoeren in een container. In dit geval gebruiken we de commando's ls en cat om de code van de website te tonen. Je geeft het ID van de container mee als eerste argument en vervolgens het commando dat je wil uitvoeren.

Je bent niet verplicht om het volledige container ID in te geven, de eerste paar karakters zijn voldoende zolang ze uniek zijn en Docker weet welke container je bedoelt.

Bash
$ docker exec 80852258314d ls /usr/share/nginx/html
50x.html
index.html

$ docker exec 80852258314d cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Een container is een image met een veranderlijke laag bovenop. Met docker exec -it kunnen we inloggen op de container alsof het een gewone Linux-machine is.

Bash
$ docker exec -it 80852258314d /bin/bash
root@80852258314d:/#
Installeer nano op de container. Welke commando's heb je hiervoor nodig?
Bash
apt update
apt install -y nano

Pas de website naar eigen wens aan, bijvoorbeeld door je naam toe te voegen. Vernieuw vervolgens de webpagina in de browser op de host.

Kan je de aangebrachte wijzigingen daar ook zien?

Ja, de wijzigingen zijn zichtbaar.

Verlaat de container met exit en start nu nog een nginx-container op poort 8002. Je zou nu twee websites moeten kunnen bezoeken in de webbrowser (poort 8001 en 8002).

Bash
docker run -p 8002:80 nginx

Bekijk nu op dezelfde manier als bij de eerste container de inhoud van /usr/share/nginx/html/index.html.

Zijn deze bestanden gelijk aan elkaar?

Nee, de bestanden zijn niet gelijk aan elkaar. De wijzigingen die je hebt aangebracht in de eerste container zijn niet zichtbaar in de tweede container.

Het bestand index.html van de eerste container bevat jouw wijzigingen, maar het bestand index.html van de tweede container bevat weer de originele waarde. Ondanks dat ze dezelfde image delen, heeft elke container zijn eigen bestandssysteem. De data wordt dus niet gedeeld tussen containers. Dat is logisch, want een container is een volledig geïsoleerde omgeving. Later gaan we dieper in op het bestandssysteem van Docker.

Sluit beide containers af met Ctrl-c.

De containers staan op dit moment nog op de host, maar zijn niet meer actief. Je kan dus niet meer surfen naar de website.

Hoe kan je een lijst zien van alle beschikbare Docker-containers (inclusief de inactieve)?
Bash
docker ps -a

Of

Bash
docker container ls -a
Met welk commando kan je de container waarin je de website hebt aangepast opnieuw opstarten? Kan je weer naar de website surfen? Kan je jouw wijzigingen aan de website nog zien?
Bash
docker start -a <CONTAINER ID>

Je kan weer naar de website surfen, en de wijzigingen die je hebt aangebracht zijn nog steeds zichtbaar.

Zolang de container bestaat op de host, blijven de wijzigingen aanwezig. Alleen is dit geen goede oplossing! Als de container verwijderd wordt, zijn de wijzigingen ook weg. Containers worden vaak bijgewerkt of vervangen, waardoor de kans op dataverlies enorm groot is.

Met welk commando kan je een container verwijderen?

De container kan je verwijderen met (op voorwaarde dat de container niet actief is):

Bash
docker rm <CONTAINER ID>

Als de container actief is, moet je de container eerst stoppen met docker stop <CONTAINER ID>.

Steeds inloggen met docker exec is zeer omslachtig en maakt het gebruik van je eigen tools moeilijk.

De data persistent maken

Om de data persistent te maken, kunnen we data opslaan via bind mounts of named volumes. In deze opdracht gebruiken we bind mounts. Deze koppelen een directory op het bestandssysteem van de host met een directory in de container. Je kan deze bind mounts gebruiken om data te delen tussen containers of om data te delen met de host.

We gaan een bind mount gebruiken om de website te delen tussen de nginx-container en de host. Maak hiervoor een map ~/website aan op de host. Plaats in deze map een eigen website.

Een eenvoudige HTML-pagina

Je kan een website maken met een eenvoudige HTML-pagina, maar je kan ook een website uit Web Development I gebruiken.

Hieronder een voorbeeld van een eenvoudige HTML-pagina:

HTML
<!DOCTYPE html>
<html>
<head>
<title>Mijn website</title>
</head>
<body>
<h1>Mijn website</h1>
<p>Dit is mijn eerste website.</p>
</body>
</html>

Sla deze code op in een bestand met de naam index.html.

Start de container opnieuw op, maar nu met de optie -v om de bind mount te koppelen aan de container:

Bash
docker run -p 8001:80 -v ~/website:/usr/share/nginx/html/ nginx
Zie je jouw website in de browser? Wat gebeurt er als je iets aanpast aan de bestanden in ~/website op de host en dan de webbrowser ververst?

Ja, je ziet jouw website in de browser. Als je iets aanpast aan de bestanden in ~/website op de host en dan de webbrowser ververst, dan zie je de wijzigingen.

Dit is een handige feature als je bv. een Docker container gebruikt voor lokaal development. Je kan dan de code aanpassen op de host en de wijzigingen zijn meteen zichtbaar in de container.

Opruimen

Verwijder alle containers die je hebt aangemaakt tijdens deze opdracht. Gebruik hiervoor commando's die je kent uit de vorige opdracht.

Welk(e) commando('s) heb je hiervoor gebruikt?

Minimaal heb je volgende commando's nodig:

Bash
docker system prune -a --volumes

Je mag ook de map ~/website verwijderen, deze is niet meer nodig.


  1. Dit is een hard refresh, wat zeer handig is bij het debuggen van websites. De website wordt volledig opnieuw opgevraagd aan de webserver, zonder de lokale cache te gebruiken. Meer info kan je vinden op https://www.minitool.com/news/f5-vs-ctrl-f5.html