Wat is een Dockerfile en hoe werkt het?

Auteur: Gepubliceerd

In het kort: een Dockerfile is een tekstbestand met instructies waarmee Docker een applicatie-image bouwt: een pakket met de code, benodigde tools en instellingen. Vanuit zo’n image kun je containers starten: geïsoleerde processen met een vooraf ingerichte omgeving. Een Dockerfile beschrijft dus hoe je de applicatie klaarmaakt om te draaien, maar is zelf geen draaiende container.

Dockerfile, image en container — drie verschillende dingen

Je kunt een Dockerfile vergelijken met een recept, een image met het pakket dat volgens dat recept is samengesteld, en een container met een draaiend exemplaar van dat pakket. Met één image kun je meerdere containers aanmaken, bijvoorbeeld meerdere instanties van dezelfde applicatie.

In een Dockerfile leg je onder meer de basisomgeving, de te kopiëren bestanden, de te installeren afhankelijkheden en het standaardstartcommando vast. Daardoor hoef je niet elke server handmatig volgens een aparte instructie in te richten. Na een wijziging in de code of afhankelijkheden bouw je doorgaans een nieuwe image.

Een container is geen volledige virtuele machine: hij gebruikt de systeemkernel van de omgeving waarin de container-engine draait. Een image helpt de applicatieomgeving consistent te maken, maar neemt niet alle verschillen tussen computers weg. Zo blijven de processorarchitectuur, netwerkconfiguratie en toegang tot bestanden van belang.

Welke instructies bevat een Dockerfile?

Het bestand heet meestal Dockerfile, zonder extensie. Elke instructie beschrijft een specifieke bouwstap of een instelling van de image. Dit zijn de meest voorkomende:

Het onderscheid tussen RUN en CMD is essentieel. RUN wordt uitgevoerd tijdens het bouwen van de image, terwijl CMD pas wordt uitgevoerd wanneer de container start. Afhankelijkheden installeren doe je doorgaans met RUN, en de server starten met CMD.

Er is ook ENTRYPOINT, dat het hoofdprogramma van de container bepaalt. Je kunt dit combineren met CMD om standaardargumenten aan dat programma door te geven. Voor een eerste eenvoudig voorbeeld volstaat CMD.

Eenvoudig voorbeeld: een HTML-pagina in een container

Stel dat je lokaal een eenvoudige pagina wilt draaien zonder Python op je computer te installeren. Je hebt een werkende installatie van Docker nodig en een map met twee bestanden: index.html en Dockerfile.

Zet het volgende in index.html:

<!doctype html>
<html lang="nl">
<meta charset="utf-8">
<title>Docker-voorbeeld</title>
<h1>De pagina draait in een container</h1>
</html>

Het bestand Dockerfile kan er zo uitzien:

FROM python:3.13-slim
WORKDIR /app
COPY index.html .
EXPOSE 8000
CMD ["python", "-m", "http.server", "8000", "--bind", "0.0.0.0"]

Docker gebruikt een image met Python, stelt /app in als werkmap en kopieert de pagina ernaartoe. Bij het starten van de container wordt een eenvoudige HTTP-server gestart. Het adres 0.0.0.0 betekent dat de server op alle netwerkinterfaces van de container luistert, zodat hij via de gepubliceerde poort bereikbaar is.

Voer in de terminal, vanuit de map met deze bestanden, het volgende uit:

docker build -t mijn-pagina .
docker run --rm -p 127.0.0.1:8080:8000 mijn-pagina

Het eerste commando bouwt de image en geeft die de naam mijn-pagina. De punt wijst de huidige map aan als buildcontext: de verzameling bestanden die beschikbaar is voor het bouwproces. Het tweede commando start een container en koppelt de lokale poort 8080 aan poort 8000 van de container.

Open http://localhost:8080 in je browser. Door de poort aan 127.0.0.1 te binden, is deze alleen vanaf de lokale computer bereikbaar. Je stopt de server met Ctrl+C; de optie --rm verwijdert de container nadat deze is gestopt. Dit is een oefenvoorbeeld, geen configuratie voor een productieserver.

Wat beïnvloedt de snelheid en veiligheid van het bouwen?

Docker kan dankzij de cache resultaten van eerdere stappen hergebruiken. Als je bestanden wijzigt die een instructie gebruikt, kan het nodig zijn die stap en de volgende, afhankelijke stappen opnieuw uit te voeren. Daarom kopieer je bij een applicatie met bibliotheken vaak eerst het bestand met afhankelijkheden en installeer je de pakketten. Pas daarna kopieer je de code, die vaker verandert.

Het bestand .dockerignore sluit onnodige bestanden uit van de buildcontext. Meestal gaat het om de map .git, lokale omgevingen, logs en bestanden met geheimen. Dit vermindert de hoeveelheid overgedragen gegevens en het risico dat vertrouwelijk materiaal onbedoeld wordt meegenomen.

Sla geen wachtwoorden of tokens op in een Dockerfile en kopieer ze niet naar de image. Een geheim in een latere stap verwijderen garandeert niet dat het ook uit eerdere lagen van de image verdwijnt. Geef geheimen die tijdens het bouwen nodig zijn door via de secret-mechanismen van BuildKit. Gegevens die de draaiende applicatie nodig heeft, geef je door via een passende configuratie van de runtime-omgeving.

Overweeg in productie de applicatie te draaien als een gebruiker zonder beheerdersrechten. Houd ook de versie van de basisimage in de gaten: een tag kan na verloop van tijd naar een gewijzigde image verwijzen, terwijl een digest specifieke inhoud identificeert. Raadpleeg de officiële documentatie van de gekozen image voor beschikbare versies en de manier waarop je updates uitvoert.

Wanneer heb je een Dockerfile nodig en wanneer Compose?

Een Dockerfile beantwoordt de vraag: ‘Hoe bouw ik een image?’ Met Docker Compose beschrijf en start je een verzameling diensten, bijvoorbeeld een applicatie, database en cache, inclusief hun netwerken, poorten en volumes. Een volume is een mechanisme om gegevens te bewaren onafhankelijk van de levensduur van één container.

Deze tools kunnen samenwerken: Compose kan een image bouwen volgens een Dockerfile en die vervolgens naast een kant-en-klare database-image starten. Als je uitsluitend kant-en-klare images gebruikt, heb je niet altijd een eigen Dockerfile nodig.

Begin met het bouwen en starten van één eenvoudige image. Vervang vervolgens de voorbeeldpagina door je eigen applicatie, leg de afhankelijkheden expliciet vast en controleer welke bestanden daadwerkelijk in de image moeten komen.

Zie ook: Wat is een API?

Lees ook

Lees hoe PHP-FPM PHP-verzoeken verwerkt, verschilt van een webserver en hoe je processen afstemt op verkeer en hostingcapaciteit.
Ontdek hoe BIND als open DNS-serversoftware domeinen beheert, welke rollen het vervult en wanneer zelf beheren zinvol is.
Lees wat het Poolse REGON-register en -nummer betekenen, hoe ze verschillen van NIP en KRS en hoe je bedrijfsgegevens controleert.