- Inleiding
- Hoofdstuk 1 Aan de slag met Docker: Essentiële commando's.
- Hoofdstuk 2 Je eerste Docker-image bouwen met een Dockerfile.
- Hoofdstuk 3 Multi-container-applicaties beheren met Docker Compose.
- Hoofdstuk 4 Een script schrijven om container-updates te automatiseren.
- Hoofdstuk 5 Algemene taken vereenvoudigen met hulpscripts.
- Hoofdstuk 6 Geavanceerde Dockerfile-technieken voor geoptimaliseerde builds.
- Hoofdstuk 7 Builds en pushes automatiseren met GitHub Actions.
- Hoofdstuk 8 Scripten voor ontwikkelomgevingen.
- Hoofdstuk 9 Scripts voor continuous integration en testen.
- Hoofdstuk 10 Aangepaste entrypoint-scripts maken voor flexibele containers.
- Hoofdstuk 11 Docker-contexten beheren in Bash-scripts.
- Hoofdstuk 12 Netwerkcreatie en -beheer scripten.
- Hoofdstuk 13 Volumebeheer en datapersistentie automatiseren.
- Hoofdstuk 14 Een script om ongebruikte Docker-resources op te ruimen.
- Hoofdstuk 15 Back-up en herstel van Docker-volumes scripten.
- Hoofdstuk 16 Docker-image-pruning automatiseren.
- Hoofdstuk 17 Health checks voor je containers scripten.
- Hoofdstuk 18 Een Python-script bouwen om te interageren met de Docker-API.
- Hoofdstuk 19 Een gebruikersbeheerscript maken voor gedeelde Docker-omgevingen.
- Hoofdstuk 20 De implementatie van een full-stack-applicatie scripten.
- Hoofdstuk 21 Een script voor het inspecteren en formatteren van containerinformatie.
- Hoofdstuk 22 Het taggen en pushen van images naar een register automatiseren.
- Hoofdstuk 23 De veilige verwerking van secrets in Docker scripten.
- Hoofdstuk 24 Een script om containers netjes te stoppen en te verwijderen.
- Hoofdstuk 25 Geavanceerd scripten: Docker-commando's combineren voor complexe workflows.
Handige Docker scripts
Inhoudsopgave
Inleiding
Er is een duidelijk moment in de reis van elke Docker-gebruiker dat zich voordoet als een kleine openbaring. Het komt vaak na het typen van docker run met een dozijn vlaggen voor de twintigste keer in een uur, of na het met zorgvuldigheid uitvoeren van een reeks docker ps, docker stop en docker rm commando's om een lokale omgeving op te schonen. Het is het moment dat je je in je stoel terugleunt, naar de opdrachtprompt staart en denkt: "Er moet een efficiëntere manier zijn om dit te doen." Je hebt, natuurlijk, helemaal gelijk. Het pad van herhalende handmatige commando's naar gestroomlijnde efficiëntie is bestukt met scripts.
Docker heeft fundamenteel veranderd hoe we software bouwen, verschepen en uitvoeren. Het biedt een ongelooflijke belofte: een consistente, geïsoleerde en draagbare omgeving voor elke applicatie. Door een applicatie en zijn afhankelijkheden te verpakken in een enkele, gestandaardiseerde eenheid genaamd een container, lost Docker het klassieke probleem "het werkt op mijn machine" op dat ontwikkelaars al decennia lastigvalt. Deze containerisatiebenadering biedt een lichtgewicht alternatief voor traditionele virtuele machines door het besturingssysteem te virtualiseren in plaats van de onderliggende hardware. Deze efficiëntie betekent dat je meerdere containers op een enkele host kunt draaien, elk met zijn eigen geïsoleerde set processen en bronnen.
De kracht van Docker ligt in zijn eenvoud en zijn robuuste commandoregelinterface (CLI). Met een paar commando's kun je een image uit een register zoals Docker Hub halen, deze als container uitvoeren en een complexe applicatie, zoals een database of een webserver, in seconden werkend krijgen. Dit is een monumentale sprong vooruit ten opzichte van de dagen van handmatige installaties en complex afhankelijkheidsbeheer. Maar het vertrouwen op uitsluitend handmatig getypte commando's is alsof je een sportwagen bezit en er alleen maar in eerste versnelling mee rijdt. Je ervaart de kernfunctionaliteit, maar mis de snelheid, kracht en elegantie waar het echt voor in staat is.
Hier komt scripting in beeld. Een script is in zijn kern een set instructies opgeslagen in een bestand, bedoeld om uitgevoerd te worden door een programma. Voor Docker-gebruikers betekent dit meestal shellscripts (zoals Bash) of scripts geschreven in een hogere taal zoals Python. Deze scripts nemen de individuele, atomaire commando's van de Docker CLI en vlechten ze samen tot krachtige, geautomatiseerde workflows. Ze transformeren meerstappige, foutgevoelige handmatige processen in een enkel, betrouwbaar commando. Ze zijn de sleutel tot het ontsluiten van het volledige potentieel van je Docker-omgeving.
Denk aan de routinetaak die je dagelijks uitvoert. Een specifieke ontwikkelomgeving opstarten met meerdere gekoppelde containers. Een back-up maken van een cruciale databasevolume. Ongebruikte images en containers opschonen om schijfruimte vrij te maken. Een draaiende applicatie updaten naar een nieuwe imageversie zonder downtime. Elke van deze workflows omvat een reeks Docker-commando's, en elk is een perfect kandidaat voor automatisering door scripting. Een goed geschreven script zorgt ervoor dat deze taken elke keer consistent worden uitgevoerd, waardoor het risico op menselijke fouten wordt geëlimineerd, zoals het vergeten van een commando-regelvlag of het verkeerd typen van een containernaam.
Dit boek is voortgekomen uit de praktische behoefte aan die automatisering. Hoewel er talloze bronnen beschikbaar zijn om je de fundamenten van Docker te leren — wat een image is, hoe je een Dockerfile schrijft, het doel van een container — stoppen velen er. Ze geven je de bouwstenen, maar laten niet altijd zien hoe je ze kunt samenvoegen tot iets groters. Dit boek is anders. Het is niet zomaar nog een gids voor Docker-commando's; het is een praktische, hands-on encyclopedie van nuttige scripts ontworpen om real-world problemen op te lossen en je leven als ontwikkelaar, systeembeheerder of DevOps-engineer aanzienlijk makkelijker te maken.
We gaan verder dan de basis docker run en docker build commando's om de kunst van scripting te verkennen. Dit boek is een verzameling recepten, een toolkit van kant-en-klaar oplossingen voor de veelvoorkomende, en soms minder veelvoorkomende, uitdagingen waar je tegenaan loopt bij het werken met Docker. Elk hoofstuk is gewijd aan een specifieke taak en biedt een compleet, werkend script dat je direct kunt gebruiken. Nog belangrijker: we leggen uit hoe elk script werkt, met uitleg over de commando's, de logica en de gebruikte technieken, zodat je de scripts niet alleen kunt gebruiken, maar ook kunt begrijpen, aanpassen en uitbreiden om aan je unieke vereisten te voldoen.
Voor wie is dit boek? Het is voor de ontwikkelaar die een consistente, één-commando setup wil creëren voor hun lokale ontwikkelomgeving. Het is voor de systeembeheerder die Docker-hosts moet beheren en routinematige onderhoudstaken zoals back-ups en opschoning wil automatiseren. Het is voor de DevOps-professional die robuuste continuous integration en continuous deployment (CI/CD) pipelines bouwt. In wezen is dit boek voor iedereen die dat moment van "er moet een betere manier zijn" heeft meegemaakt en klaar is om automatisering te omarmen.
De enige voorwaarde is een basisbegrip van Docker. Je moet bekend zijn met kernconcepten zoals images, containers, volumes en netwerken. Je moet Docker geïnstalleerd hebben en enige ervaring hebben met het uitvoeren van basispcommando's. Je hoeft echter geen scripting-goeroe te zijn. We beginnen met eenvoudige shellscripts en introduceren geleidelijk geavanceerdere technieken en zelfs het gebruik van de Docker API met Python, zodat het materiaal toegankelijk is ongeacht je huidige scriptingvaardigheid.
Gedurende de hoofdstukken van dit boek begeven we ons op een reis van simpel naar complex. We beginnen met het waarborgen van een stevige basis, met behandeling van essentiële commando's en de fundamenten van het bouwen van images met een Dockerfile en het beheren van multi-container setups met Docker Compose. Deze vroege hoofdstukken leggen de basis, zodat je de benodigde bouwstenen tot je beschikking hebt voordat we ze gaan samenvoegen tot geautomatiseerde workflows. Ze dienen als een herhaling en een basislijn voor het scriptwerk dat volgt.
Vanaf daar duiken we met hoofd en nek in de wereld van automatisering. Je leert hoe je een script schrijft dat automatisch een nieuwe versie van een image kan ophalen en een container herstart om een update te voltooien, een hoeksteen van het onderhouden van draaiende applicaties. We verkennen de creatie van generieke helperscripts die een breed scala aan veelvoorkomende taken kunnen vereenvoudigen, waardoor je commandoregelinteracties met Docker krachtiger en minder uitgebreid worden. Deze scripts zijn ontworpen als praktische tools die je direct in je workflow kunt integreren.
Een belangrijk deel van onze reis zal gewijd zijn aan de fijne kunst van bronnenbeheer. Docker-omgevingen, zeker die intensief gebruikt worden voor ontwikkeling en testen, kunnen snel vervuild raken met ongebruikte images, volumes en gestopte controllers, wat waardevolle schijfruimte verbruikt. We bieden en dissecteren scripts specifiek ontworpen om deze rommel veilig en efficiënt op te schonen. Je leert hoe je het wegprunen van oude images kunt automatiseren en hoe je een script implementeert dat intelligent alleen de bronnen verwijdert die niet meer nodig zijn.
Data is het bloed van veel applicaties, en het beheren ervan binnen een gecontaineriseerde wereld brengt zijn eigen uitdagingen met zich mee. We pakken dit aan met hoofdstukken over het scripten van het beheer van Docker-volumes. Je leert hoe je robuuste scripts schrijft om een van de meest kritische administratieve taken uit te voeren: het back-uppen van je belangrijke data uit een volume en, net zo belangrijk, het herstellen ervan. Dit biedt een veiligheidsnet en is een essentiële vaardigheid voor iedereen die stateful applicaties in Docker draait.
Naarmate je vaardigheid groeit, begeven we ons in geavanceerder gebied. We kijken naar geavanceerde Dockerfile-technieken die je helpen kleinere, veiliger en efficiëntere images te maken. Een geoptimaliseerde image bouwt sneller, verbruikt minder schijfruimte en heeft een kleiner aanvalsoppervlak, wat allemaal cruciaal is in een productieomgeving. We laten je zien hoe je je Dockerfiles kunt structureren om optimaal gebruik te maken van Docker's laagcachingmechanisme voor snellere builds.
Automatisering strekt zich verder uit dan je lokale machine, en moderne softwareontwikkeling is diep verstrengeld met CI/CD-platforms. Een toegewijd hoofdstuk begeleidt je door het proces van het gebruik van GitHub Actions om het bouwen en pushen van je Docker-images naar een register te automatiseren. Dit overbrugt de kloof tussen je coderepository en je deployment-omgeving, en creëert een naadloze pipeline van commit naar container-image.
We zullen ook verkennen hoe scripts specifiek kunnen worden afgestemd op ontwikkelomgevingen. Dit omvat scripts die complexe applicatiestacks opzetten, verschillende Docker-contexten beheren voor het schakelen tussen lokale en externe Docker-daemons, en het scripten van de creatie van aangepaste netwerken om te zorgen dat je containers kunnen communiceren op de manier die je applicatie vereist. Deze scripts helpen consistentie af te dwingen binnen een team van ontwikkelaars, zodat iedereen in een identieke omgeving werkt.
De interactie met containers stopt niet zodra ze draaien. We onderzoeken hoe je health checks kunt scripten om de status van je applicaties te monitoren en hoe je aangepaste entrypoint-scripts kunt maken die je containers flexibeler en configureerbaarder maken tijdens runtime. Je leert zelfs hoe je de CLI kunt omzeilen en direct kunt interacteren met de Docker Engine via zijn API, wat een heel nieuwe wereld van automatiseringsmogelijkheden opent met talen zoals Python.
Beveiliging is een vanzelfsprekend belang in elke omgeving, en Docker is geen uitzondering. Een toegewijd hoofdstuk richt zich op het scripten van de veilige afhandeling van geheimen, een kritiek aspect van het deployen van applicaties die verbinding moeten maken met databases of andere beschermde diensten. We kijken naar verschillende strategieën om gevoelige informatie aan je containers te leveren zonder deze in je images of scripts vast te leggen, wat een veelvoorkomend maar gevaarlijk anti-patroon is.
Tot slot brengen we alles samen door complexe, real-world workflows aan te pakken. We lopen door het scripten van de deployment van een full-stack applicatie, van het bouwen van de images tot het lanceren van de onderling verbonden diensten. We behandelen ook scripts voor administratieve taken zoals het beheren van gebruikers in een gedeelde Docker-omgeving, het netjes stoppen en verwijderen van containers om schone shutdowns te garanderen, en het creëren van aangepaste tools voor het inspecteren en formatteren van container-informatie om de exacte output te krijgen die je nodig hebt.
De filosofie achter de scripts in dit boek is een van praktische toepasbaarheid en aanpasbaarheid. Ze zijn zo duidelijk en rechttoe geschreven mogelijk, met commentaar om de complexere delen uit te leggen. Maar ze zijn niet bedoeld als onveranderlijke artefacten. Je wordt aangemoedigd ze te nemen, ze te wijzigen, ze te breken en ze opnieuw te bouwen om perfect aan je behoeften te voldoen. Het doel is niet alleen om je een bibliotheek van scripts te bieden, maar om je te voorzien van de kennis om je eigen scripts te creëren.
Om het meest uit dit boek te halen, moedig ik je aan een actieve lezer te zijn. Lees niet alleen de tekst; start je terminal op en draai de scripts. Experimenteer met de commando's en probeer de code aan te passen om te zien wat er gebeurt. De beste manier om scripting te leren is door het te doen, en de beste manier om een tool te begrijpen is door hem te gebruiken. Zet een veilige, lokale Docker-omgeving op waar je vrij kunt experimenteren zonder angst om iets kritisch te breken.
De reis van een handmatige, commando-voor-commando Docker-gebruiker naar een meester in automatisering is een lonende. Het bespaart je tijd, vermindert fouten, en stelt je uiteindelijk in staat om je te richten op de interessantere en creatieve aspecten van je werk. De mogelijkheid om een complex proces in te kapselen in een enkel, uitvoerbaar script is een superkracht in de wereld van softwareontwikkeling en -operaties.
Dit boek is je gids om die superkracht te ontwikkelen. Het is tijd om verder te gaan dan de plak van herhalend typen en de elegantie van automatisering te omarmen. Laten we stoppen met typen en beginnen met scripten.
HOOFDSTUK EÉN: Aan de slag met Docker: Essentiële commando's.
Voordat men een symfonie kan componeren, moet men eerst leren de individuele noten te spelen. In de wereld van Docker-automatisering zijn onze noten de command-line interface (CLI)-commando's. Dit zijn de fundamentele werkwoorden die ons in staat stellen onze intenties te communiceren aan de Docker-daemon, de motor die onze gecontaineriseerde wereld aandrijft. Hoewel het uiteindelijke doel van dit boek is om deze commando's in elegante en krachtige scripts te verweven, moet die reis beginnen met een solid begrip van de commando's zelf. Dit hoofdstuk is je gereedschapskist, een begeleide rondleiding door de essentiële tools waar je keer op keer naar zal grepen. Het meesteren van deze commando's is de eerste en meest cruciale stap naar vaardigheid in Docker en, daardoor, in de automatisering ervan.
We zullen de complete levenscyclus van een container verkennen, van het vinden van het juiste softwarepakket in een publieke register tot het draaien, inspecteren, beheren van de staat en ten slotte het opruimen ervan. Elk commando is een bouwsteen. Het begrijpen niet alleen van wat een commando doet, maar ook van de diverse opties en de context waarin het meest effectief is, is van vitaal belang. Dit zijn de tools die je zult gebruiken om de geavanceerde geautomatiseerde workflows in de komende hoofdstukken te bouwen. Zie dit als je basisopleiding, zodat je woordenschat stevig is voordat je begint met poëzie schrijven.
Onze reis begint waar de meeste Docker-workflows beginnen: met een image. Een image is een blauwdruk, een alleen-lezen sjabloon die de applicatie, zijn bibliotheken en zijn afhankelijkheden bevat. Deze images worden meestal opgeslagen in een register, wat een repository is voor het opslaan en distribueren ervan. Het meest voorkomende en publieke register is Docker Hub. Het eerste wat je vaak moet doen is de officiële image zoeken voor de software die je wilt gebruiken. Hiervoor is het <code>docker search</code>-commando een nuttige, alhoewel basale, startpunt. Het bevraagt Docker Hub naar images die overeenkomen met je zoekterm.
Als je bijvoorbeeld images wilt vinden met betrekking tot de populaire webserver Nginx, voer je uit:
docker search nginx
De output biedt een lijst met images met kolommen voor de naam, een korte beschrijving, het aantal sterren (een ruwe populariteitsmaat) en of de image officieel is. Officiële images zijn een gecureerde set repositories van Docker, die een gecontroleerd en goed gedocumenteerd startpunt bieden voor veelvoorkomende software. Het is bijna altijd best practice om de officiële image te gebruiken als er een beschikbaar is, aangezien ze worden onderhouden met oog voor beveiliging en stabiliteit.
Zodra je de image hebt geïdentificeerd die je wilt gebruiken, zoals de officiële <code>nginx</code>-image, moet je deze van het register naar je lokale machine halen. Dit is de taak van het <code>docker pull</code>-commando. Dit commando download de imagelagen die nodig zijn om de volledige image op je systeem te assembleren. De syntaxis is eenvoudig en vereist de naam van de image en, optioneel, een tag. Een tag wordt gebruikt om een image te versie, zoals <code>1.21</code> of <code>latest</code>. Als geen tag is opgegeven, kiest Docker standaard voor de tag <code>latest</code>.
Om de officiële Nginx-image op te halen, voer je uit:
docker pull nginx
Dit is equivalent aan <code>docker pull nginx:latest</code>. Om een specifieke versie op te halen, geef je de tag op zoals: <code>docker pull nginx:1.21</code>. Het gebruik van specifieke versietags in plaats van <code>latest</code> is een cruciaal praktyk voor het creëren van reproduceerbare omgevingen en betrouwbare scripts. De <code>latest</code>-tag kan op elk moment worden bijgewerkt door de image-onderhouder, wat betekent dat je script van de ene op de andere dag anders kan gedragen. Het vastpinnen aan een specifieke versie zorgt ervoor dat je altijd met precies dezelfde software werkt. Na het pullen kun je alle images op je lokale machine zien met het <code>docker images</code>-commando.
Met een image gedownload naar je machine heb je de blauwdruk. De volgende logische stap is om die blauwdruk te gebruiken om iets reëls te construeren: een container. Een container is een uitvoerbaar exemplaar van een image. Het commando om een container te maken en te starten is <code>docker run</code>, waarschijnlijk het belangrijkste en meest functierijke commando in de Docker CLI. De basisvorm is simpel, maar de kracht ligt in de menigte vlaggen die gebruikt kunnen worden om te configureren hoe de container draait.
De simpelste mogelijke uitvoering van dit commando is met een image zoals <code>hello-world</code>, die specifiek voor dit doel is ontworpen.
docker run hello-world
Wanneer je dit uitvoert, ontvouwt zich een reeks gebeurtenissen. Docker controleert of de <code>hello-world</code>-image aanwezig is op je lokale systeem. Zo niet, haalt hij hem automatisch op van Docker Hub. Daarna maakt hij een nieuwe container aan van die image. Hij voert het in de image ingesloten commando uit, wat in dit geval een vriendelijk bericht naar je terminal print. Ten slotte, zodra het commando klaar is, stopt de container. Dit simpele voorbeeld demonstreert de kernfunctie van het aanmaken en draaien van een container.
Voor de meeste real-world applicaties heb je echter meer controle nodig. Je wilt containers op de achtergrond draaien, met ze interacteren, ze aan je netwerk blootleggen en ze persistente data geven. Hier komen de vlaggen voor <code>docker run</code> van pas. Laten we beginnen met het onderscheiden tussen twee primaire draaimodi: interactief en detached (op de achtergrond).
Een interactieve container is een container waarmee je je terminal verbindt, zodat je direct commando's in kunt voeren. Dit wordt bereikt met de <code>-it</code>-vlaggen. De <code>-i</code>-vlag houdt standaard invoer (STDIN) open, en de <code>-t</code>-vlag reserveert een pseudo-TTY, wat je eigenlijk een commandoprompt binnen de container geeft. Dit is perfect om een image te verkennen of een eenmalige taak uit te voeren. Om bijvoorbeeld een Ubuntu-container te draaien en een bash-shell erin te krijgen, gebruik je:
docker run -it ubuntu /bin/bash
Je terminalprompt zou veranderen, en je zou nu commando's binnen de Ubuntu-container uitvoeren. Dit is ongelooflijk nuttig voor debugging of ontwikkeling. Wanneer je <code>exit</code> typt, wordt het bash-proces beëindigd en stopt de container.
De alternatieve modus is detached-modus, gespecificeerd met de <code>-d</code>-vlag. Dit is het paardewerk voor het draaien van langdurige diensten zoals webservers, databases of API's. Wanneer je een container in detached-modus start, start Docker de container en geeft je de prompt op je host-terminal terug, terwijl de container op de achtergrond blijft draaien. Het commando print de unieke ID van de zojuist aangemaakte container als bevestiging. Om bijvoorbeeld een Nginx-webserver op de achtergrond te starten:
docker run -d nginx
Je hebt nu een draaiende webserver, maar hoe ben je erbij? Standaard zijn geïsoleerd van het netwerk van de host. Om een service die in een container draait te exposen, moet je een poort van de host-machine mappen naar een poort binnen de container met de <code>-p</code>-vlag. Het formaat is <code>-p [host_poort]:[container_poort]</code>. Als we onze Nginx-server willen bereiken op poort 8080 van onze lokale machine, mappen we die naar poort 80 binnen de container, wat de standaardpoort is waar Nginx op luistert.
docker run -d -p 8080:80 nginx
Als je nu een webbrowser opent en naar <code>http://localhost:8080</code> navigeer, zie je de standaard Nginx-welkomstpagina, geserveerd vanuit je container. Deze poortmapping is fundamenteel om gecontaineriseerde applicaties bruikbaar te maken.
Wanneer je een container start, wijst Docker een willekeurige, vaak whimsical gegenereerde naam toe, zoals vigilant_murdock of dreamy_bassi. Hoewel amusant, zijn deze namen niet nuttig voor automatisering. Als je betrouwbaar naar een specifieke container wilt verwijzen in een script, moet je hem een voorspelbare naam geven. De <code>--name</code>-vlag stelt je in staat om dit te doen. Een goed genaamde container is de eerste stap naar een beheersbare omgeving.
docker run -d -p 8080:80 --name mijn-webserver nginx
Nu hoef je in plaats van de willekeurige naam of ID te zoeken, deze container gewoon mijn-webserver te noemen in volgende commando's, wat veel handiger is en essentieel voor het schrijven van robuuste scripts.
Een ander kritisch concept is datapersistentie. Het bestandssysteem binnen een container is standaard ephemer (kortstondig). Dit betekent dat als je de container verwijdert, alle data die erin is aangemaakt of gewijzigd, voor altijd verloren is. Dit is prima voor stateless applicaties, maar rampzalig voor alles wat staat moet behouden, zoals een database. Docker lost dit op met volumes. Een volume is een mechanisme voor het persisteren van data gegenereerd door en gebruikt door Docker-containers. We duiken diep in volume-beheerscripts in Hoofdstuk 13, maar het basisgebruik met <code>docker run</code> is nu essentieel om te kennen.
De <code>-v</code>-vlag wordt gebruikt om een volume in een container te mounten. Je kunt Docker het volume laten beheren (een named volume) of een specifieke directory van je host-machine in de container mappen (een bind mount). Voor een MySQL-database wil je misschien de datadirectory persisteren:
docker run -d --name mijn-database -e MYSQL_ROOT_PASSWORD=mijngeheimewachtwoord -v mysql-data:/var/lib/mysql mysql
In dit commando hebben we ook de <code>-e</code>-vlag geïntroduceerd, die een omgevingsvariabele binnen de container instelt. Dit is een veelvoorkomende manier om configuratiedetails, zoals wachtwoorden of instellingen, door te geven aan de applicatie in de container. Het <code>-v mysql-data:/var/lib/mysql</code>-gedeelte vertelt Docker om een named volume genaamd mysql-data aan te maken (als die nog niet bestaat) en deze te mounten op het <code>/var/lib/mysql</code>-pad binnen de container. Nu blijft, zelfs als je de mijn-database-container verwijdert, de mysql-data-volume bestaan, en kun je hem aan een nieuwe container koppelen om je werk voort te zetten.
Tot slot, voor veel tijdelijke taken, zoals het draaien van een testsuite of een build-proces, maak je een container, die zijn actie uitvoert en daarna stopt. Standaard blijft deze gestopte container op je systeem bestaan. Met de tijd kan dit leiden tot veel rommel. De <code>--rm</code>-vlag vertelt Docker de container automatisch te verwijderen zodra hij afsluit. Dit is een fantastische huishoudfunctie.
docker run --rm -it ubuntu echo "Deze container verdwijnt als ik klaar ben."
Zodra het echo-commando voltooid is, wordt de container direct en automatisch verwijderd, zodat je systeem schoon blijft. Het gebruik van <code>--rm</code> voor kortstondige, eentaak-containers is een best practice die de opstapeling van gestopte containers voorkomt.
Zodra je containers hebt draaien, met name in detached-modus, heb je een manier nodig om te zien wat er aan de hand is. Het primaire commando hiervoor is <code>docker ps</code>. Op zichzelf lijst dit commando alle draaiende containers op je systeem. De output is een nette tabel die verschillende nuttige informatie toont: de container-ID, de image waaruit hij is gemaakt, het commando dat hij draait, wanneer hij is aangemaakt, zijn huidige status, eventuele poortmappings en zijn naam.
Deze weergave is cruciaal voor een snel overzicht van je actieve omgeving. Echter, het vertelt maar een deel van het verhaal. Om alle containers te zien, inclusief die gestopt of geëxited zijn, moet je de <code>-a</code>-vlag toevoegen.
docker ps -a
Dit commando is je go-to voor een complete inventaris. Je ziet containers die succesvol zijn geëxited (Status Exited (0)) en die gefaald zijn (bijv. Exited (1)). Dit is vaak de eerste stap in het debuggen waarom een container niet draait zoals verwacht.
Voor scripting-doeleinden is de standaard tabelvormige output van <code>docker ps</code> niet altijd ideaal. Het is ontworpen voor menselijke ogen. Wanneer je een lijst met containers moet doorgeven aan een ander commando, wil je vaak alleen de IDs. De <code>-q</code>-vlag (quiet) wijzigt de output om alleen de container-IDs te tonen, één per regel. Om bijvoorbeeld een lijst te krijgen van alle container-IDs, draaiende of gestopt:
docker ps -a -q
Deze output kan direct in andere commando's gebruikt worden. Een veelvoorkomend patroon om alle gestopte containers te verwijderen is bijvoorbeeld command substitution: <code>docker rm $(docker ps -a -f "status=exited" -q)</code>. Hier hebben we ook de <code>-f</code>- (of <code>--filter</code>-)vlag geïntroduceerd, waarmee je de lijst kunt verfijnen op basis van bepaalde criteria, in dit geval de status van de container. Deze combinatie van filteren en quiet-output is een krachtige techniek die de basis vormt van veel opruimscripts.
Weten dat een container draait is vaak niet genoeg. Je wilt de output zien of ermee interacteren. Voor detached-containers, wier output niet met je terminal is verbonden, is het <code>docker logs</code>-commando essentieel. Het haalt de logs (standaarduitvoer en standaardfout) op uit een container.
docker logs mijn-webserver
Dit toont alle logs die door de Nginx-container zijn gegenereerd sinds de start. Voor een continu draaiende service wil je de logs misschien in realtime volgen, vergelijkbaar met het <code>tail -f</code>-commando in Linux. De <code>-f</code>-vlag (follow) voor <code>docker logs</code> doet precies dat.
docker logs -f mijn-webserver
Je terminal zal nu de logs streamen naarmate ze gegenereerd worden, wat onmisbaar is voor live monitoring en debugging.
Soms moet je meer dan alleen logs bekijken; je moet een commando binnen een al draaiende container uitvoeren. Je wilt bijvoorbeeld een configuratiebestand in je draaiende Nginx-container inspecteren of de inhoud van een database controleren. Dit is de taak van het <code>docker exec</code>-commando. Het stelt je in staat om een commando "te executeren" in een draaiende container.
Om een interactieve shell in onze draaiende mijn-webserver-container te krijgen, gebruik je:
docker exec -it mijn-webserver /bin/bash
Dit lijkt veel op het <code>docker run -it</code>-commando, maar het cruciale verschil is dat <code>docker exec</code> koppelt aan een bestaande, draaiende container, terwijl <code>docker run</code> een nieuwe aanmaakt. Het gebruik van <code>exec</code> is de standaardmanier om administratieve taken op een draaiende service uit te voeren zonder hem te hoeven stoppen en herstarten.
De levenscyclus van een container gaat niet alleen over creatie; het gaat ook over controle. Je zul je containers vaak moeten stoppen, starten en herstarten. De commando's hiervoor zijn eenvoudig: <code>docker stop</code>, <code>docker start</code> en <code>docker restart</code>. Het <code>docker stop</code>-commando stopt een container netjes door eerst een SIGTERM-signaal te sturen, zodat de applicatie een schone shutdown kan uitvoeren. Als het niet stopt binnen een genadeperiode (meestal 10 seconden), volgt Docker op met een SIGKILL-signaal om het gedwongen te beëindigen.
docker stop mijn-webserver
Eenmaal gestopt, verschijnt de container niet meer in de standaard <code>docker ps</code>-output, maar hij bestaat nog en is zichtbaar met <code>docker ps -a</code>. Om hem terug tot leven te wekken, gebruik je <code>docker start</code>.
docker start mijn-webserver
De container hervat met zijn vorige configuratie, inclusief naam en eventueel gekoppelde volumes. Het <code>docker restart</code>-commando is gewoon een handige shortcut die een stop volgt door een start, wat handig is voor het toepassen van configuratiewijzigingen die een herstart van de service vereisen.
Een goed onderhouden Docker-omgeving is een schone. Met de tijd kunnen gestopte containers en ongebruikte images zich ophopen, wat aanzienlijke schijfruimte verbruikt. We hebben al de <code>--rm</code>-vlag voor <code>docker run</code> gezien, maar je hebt ook commando's nodig om bestaande resources handmatig op te schonen. Het <code>docker rm</code>-commando wordt gebruikt om een of meer gestopte containers te verwijderen.
docker rm [container_id_of_naam]
Je kunt een draaiende container niet verwijderen tenzij je de <code>-f</code>- (force-)vlag gebruikt, maar de schonere aanpak is altijd om hem eerst te stoppen en daarna te verwijderen. Je kunt ook een lijst met container-IDs doorgeven om meerdere containers tegelijk te verwijderen, een techniek die, zoals gezegd, perfect is voor scripting.
Op dezelfde manier kunnen images nog meer ruimte innemen dan containers. Het <code>docker rmi</code>-commando wordt gebruikt om een of meer images te verwijderen. Een image kan niet verwijderd worden als deze momenteel door een container wordt gebruikt, zelfs niet door een gestopte. Je moet eerst de afhankelijke containers verwijderen voordat je de image kunt verwijderen waar ze op gebaseerd zijn.
docker rmi nginx:1.21
Deze handmatige opruimcommando's zijn effectief, maar ze zijn ook ideale kandidaten voor automatisering. Later hoofdstukken laten zien hoe je scripts bouwt die intelligente ongebruikte resources vinden en verwijderen, wat je tijd en schijfruimte bespaart.
Ten slotte is er één commando dat fungeert als universele tool voor diepgaande inspectie: <code>docker inspect</code>. Dit commando kan gebruikt worden op containers, images, volumes en netwerken. Het retourneert een gedetailleerde JSON-array met een schat aan informatie over het gespecificeerde Docker-object. De output kan in eerste instantie overweldigend zijn, maar het is een ongelooflijk krachtige bron voor automatisering.
docker inspect mijn-webserver
Dit print een groot JSON-object naar het scherm, dat alles over de container gedetailleerd beschrijft: de staat, de configuratie, de netwerkinstellingen (inclusief het interne IP-adres), de volume-koppelingen en nog veel meer.
De ware kracht van <code>docker inspect</code> voor scripting wordt ontgrendeld met de <code>--format</code>-vlag. Deze vlag stelt je in staat om een Go-template op te geven om specifieke stukken informatie uit de JSON-output te extraheren. In plaats van een gigantisch JSON-bestand te parsen met een tool zoals <code>jq</code>, kun je Docker vragen om je alleen het datapunt te geven dat je nodig hebt. Om bijvoorbeeld alleen het interne IP-adres van een container op te halen:
docker inspect --format='{{.NetworkSettings.IPAddress}}' mijn-webserver
Deze mogelijkheid om de staat en configuratie van elk Docker-object precies op te vragen, maakt <code>docker inspect</code> een hoeksteen van geavanceerde scripting. Je kunt het gebruiken om dynamische informatie op te halen, zoals het IP-adres van een container, en dit in andere commando's of configuratiebestanden te voeden, wat echt dynamische en intelligente automatisering creëert.
Deze commando's—<code>pull</code>, <code>run</code>, <code>ps</code>, <code>logs</code>, <code>exec</code>, <code>stop</code>, <code>rm</code>, <code>rmi</code> en <code>inspect</code>—vormen de kernwoordenschat van Docker. Ze zijn de essentiële tools die je elke dag zult gebruiken. Door hun functies en opties te begrijpen, heb je de benodigde basis gelegd. Je kunt nu de volledige levenscyclus van een container handmatig beheren. Met deze stevige greep op de individuele bouwstenen zijn we nu klaar voor de volgende stap: het definiëren van onze eigen blauwdrukken voor applicaties door te leren hoe we een Dockerfile construeren.
This is a sample preview. The complete book contains 27 sections.