Skip to main content

Werken met Docker images

Als we gebruik maken van software containers, dan worden die aangemaakt vanuit een image. Je kan dat zien als de 'harde schijf' van je container, al doen we de waarheid daarmee wel wat geweld aan. De image hoeft immers een flink aantal onderdelen (zoals de kernel) niet te bevatten, omdat die gedeeld wordt met het host operating systeem. De image kan je zelf aanmaken 'from scratch', maar in de meeste omstandigheden zal je al een base image vinden om van te vertrekken. Een korte zoektocht op bijvoorbeeld https://hub.docker.com zal je leren dat er al vele duizenden images zijn om mee te werken.

warning

Let op bij het gebruik van publieke repositories: er is geen enkele kwaliteitsgarantie bij wat je daar vindt. Meer zelfs, in het verleden werden al auteurs van containers betrapt op het smokkelen van malware in hun base images.

Er zijn gelukkig enkele officiële images die wel uitvoerig getest worden voor ze gebruikt worden.

docker hub

Uiteraard is het steeds ook zo dat je die images kan gebruiken als basis om daarna zelf wijzigingen aan te brengen. Een typisch voorbeeld is om de 'standaard' Nginx container te gebruiken om nadien zelf de nginx config en web-bestanden toe te voegen.

Met het commando docker images zie je een lijst van beschikbare images op je eigen systeem. Initieel is dat leeg, maar je kan die zelf inladen met docker pull.

Dit kunnen we eenvoudig testen met een bestaande image:

docker pull nginx

In de output zal je merken dat de verschillende lagen (daar komen we later op terug) worden binnengehaald. Bovenstaand commando zal je echter niet zo vaak gebruiken: als je een container wil starten waarvan de container nog niet werd binnengehaald, dan zal dat automatisch gebeuren bij de eerste start. Als je bijvoorbeeld docker run nginx uitvoert, zal daarvoor automatisch de laatste nginx-image binnengehaald worden als er nog geen nginx-image lokaal bestaat.

tip

Gebruik in productie steeds tags bij het gebruik van images. Bovenstaand commando vervang je dus beter door docker run nginx:1.21.6. Op die manier heb je zeker een stabiele container die geen major upgrades doet zonder dat je daar zelf voor kiest. De keerzijde van de medaille is dan uiteraard wel dat je dat ook zelf moet doen en niet mag vergeten...

Details opvragen over de image kan ons veel leren over hoe die opgesteld is:

docker image inspect nginx

[
{
"Id": "sha256:fa5269854a5e615e51a72b17ad3fd1e01268f278a6684c8ed3c5f0cdce3f230b",
"RepoTags": [
"nginx:latest"
],
"RepoDigests": [
"nginx@sha256:859ab6768a6f26a79bc42b231664111317d095a4f04e4b6fe79ce37b3d199097"
],
"Parent": "",
"Comment": "",
"Created": "2022-04-20T10:43:12.055940177Z",
"Container": "3c8758320eb6a5293e75ce1ff5afe91584a72b4ee400792f34985a27673ffbc2",
"ContainerConfig": {
"Hostname": "3c8758320eb6",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.6",
"NJS_VERSION=0.7.2",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
],
"Image": "sha256:e158bbfdf1201dbc8876232cef4465c5f69c1fd0986f05ee48291a92debc21a0",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGQUIT"
},
"DockerVersion": "20.10.12",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.6",
"NJS_VERSION=0.7.2",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Image": "sha256:e158bbfdf1201dbc8876232cef4465c5f69c1fd0986f05ee48291a92debc21a0",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGQUIT"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 141522124,
"VirtualSize": 141522124,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/db0f5721130d01a8ff586fecfe02a217ee8b3cc8f52e3dca471488ddcdbf75db/diff:/var/lib/docker/overlay2/4678eddd86bf9ac9b80894a6ce48f04294da2e79fdb591ee37f0426b96adfdd3/diff:/var/lib/docker/overlay2/0c6f5107dcd94cc6e502f505e1b8c59e901f033825261991c00603c550e0eb3a/diff:/var/lib/docker/overlay2/102d55f9ddc394f117def4204649a573a8710348cdcf9505f4c4218e7416b944/diff:/var/lib/docker/overlay2/5699e5a910a4abf02649e62600e2e76b0f38608032c96bbb6ac2aa873fe42ef6/diff",
"MergedDir": "/var/lib/docker/overlay2/56a9b41882bdcfc9850bfa3c24ed8a63a1137f4e940911c43ddc0270c7d53995/merged",
"UpperDir": "/var/lib/docker/overlay2/56a9b41882bdcfc9850bfa3c24ed8a63a1137f4e940911c43ddc0270c7d53995/diff",
"WorkDir": "/var/lib/docker/overlay2/56a9b41882bdcfc9850bfa3c24ed8a63a1137f4e940911c43ddc0270c7d53995/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:9c1b6dd6c1e6be9fdd2b1987783824670d3b0dd7ae8ad6f57dc3cea5739ac71e",
"sha256:4b7fffa0f0a4a72b2f901c584c1d4ffb67cce7f033cc7969ee7713995c4d2610",
"sha256:f5ab86d69014270bcf4d5ce819b9f5c882b35527924ffdd11fecf0fc0dde81a4",
"sha256:c876aa251c80272eb01eec011d50650e1b8af494149696b80a606bbeccf03d68",
"sha256:7046505147d7f3edbf7c50c02e697d5450a2eebe5119b62b7362b10662899d85",
"sha256:b6812e8d56d65d296e21a639b786e7e793e8b969bd2b109fd172646ce5ebe951"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]

Bovenstaande output leert ons bijvoorbeeld dat de image uit 6 lagen bestaat. Die kan je zien als commits bij Git. Het is dus zowel mogelijk om lagen toe te voegen als te verwijderen. Containers die gebaseerd zijn op images met te veel lagen kunnen daardoor iets trager worden, dat is dus een aandachtspunt.

Registries

We maakten al kennis met Docker Hub. Dat is zonder twijfel de bekendste registry voor container images. Je kan daar zelf ook images op plaatsen, al staan die zonder betalend abonnement steeds publiek. Maar er zijn zeker ook andere opties: cloud-platformen zoals Azure, AWS of GCP hebben ook registries aan boord, en dat is ook zo voor CI/CD-platformen. Denk daarbij bijvoorbeeld aan Gitlab, waar jullie per project ook een registry zullen vinden om je containers naar op te laden.

warning

Bij het toekennen van een nieuwe TAG kies je best je username op de registry als eerste deel. Op die manier zal je vlot kunnen pushen (=container toevoegen).

bv. ksven/myimage:1.0

De typische werkwijze om te pushen naar een registry:

# login
docker login registry.example.com -u <username> -p <token>

# build je container met een specifieke tag
docker build -t registry.example.com/group/project/image .

# push naar de registry
docker push registry.example.com/group/project/image

Bijhorende Labs