Docker Images maken met een Dockerfile op Ubuntu 20.04 LTS

Docker is virtualisatie op besturingssysteemniveau, voornamelijk bedoeld voor ontwikkelaars en sysadmins. Docker maakt het gemakkelijker om applicaties te maken en in te zetten in een geïsoleerde omgeving.

Een Dockerfile is een script dat verzamelingen commando’s en instructies bevat die automatisch achter elkaar worden uitgevoerd in de dockeromgeving om een nieuw docker image te bouwen.

In deze tutorial laten we zien hoe je met een Dockerfile je eigen Docker image maakt. We zullen details uitleggen over de Dockerfile, zodat je je eigen Docker image kunt bouwen.

Voorwaarden

Voor deze gids gebruiken we Ubuntu 20.04 met 1 GB RAM, 25 GB vrije schijfruimte en 2 CPU’s. Ook zullen we Ubuntu 20.04 gebruiken als basisimage om het eigen Docker image te bouwen.

Inleiding tot het Dockerfile commando

Een Dockerfile is een script dat alle commando’s bevat voor het bouwen van een Docker image. De Dockerfile bevat alle instructies die gebruikt worden om de Docker image te maken met het ‘docker build’ commando.

Voordat je je eerste Dockerfile maakt, moet je bekend zijn met de Dockerfile instructie. Hieronder enkele Dockerfile-instructies die je moet kennen.

VAN

Stel het basis-image in voor het nieuwe image dat je wilt maken. De FROM-instructie initialiseert de nieuwe build-stage en moet bovenaan de Dockerfile staan.

LABEL

Met deze instructie kun je extra informatie over je Docker image toevoegen, zoals de versie, beschrijving, maintainer, enz. De LABEL instructie is een key-value paar waarmee je meerdere labels en meerregelige waarden kunt toevoegen.

RUN

Deze instructie wordt gebruikt om commando’s uit te voeren tijdens het bouwproces van het docker image. Je kunt extra pakketten installeren die nodig zijn voor je Docker images.

ADD

De ADD instructie wordt gebruikt om bestanden, directories, of bestanden op afstand van een URL naar je Docker images te kopiëren, van de ‘src’ naar het absolute pad ‘dest’. Ook kun je het standaard eigendom van je bestand instellen.

ENV

De ENV instructie wordt gebruikt om een omgevingsvariabele te definiëren die gebruikt kan worden tijdens het bouwen en ook in veel inline vervangen kan worden.

CMD

De CMD instructie wordt gebruikt om het standaard commando te definiëren dat moet worden uitgevoerd bij het draaien van de container. En het Dockerfile mag maar één CMD-instructie bevatten, en als er meerdere CMD zijn, wordt de laatste CMD-instructie uitgevoerd.

EXPOSE

Deze instructie wordt gebruikt om de containerpoort op de specifieke netwerkpoorten bloot te stellen tijdens runtime. Het standaard blootgestelde protocol is TCP, maar je kunt aangeven of het TCP of UDP is.

ARG

De ARG instructie wordt gebruikt om een variabele te definiëren die de gebruiker kan doorgeven bij de built-time. Je kunt deze instructie gebruiken in het docker ‘build commando’ tijdens het bouwen met de ‘–build-arg variabele=waarde’ optie en kan worden doorgegeven via het Dockerfile. Ook kun je meerdere ARG gebruiken in de Dockerfile.

ENTRYPOINT

De ENTRYPOINT instructie wordt gebruikt om het eerste en standaard commando te definiëren dat wordt uitgevoerd als de container draait. Definieer het commando om je applicatie te starten met de ENTRYPOINT instructie.

WORKDIR

De WORKDIR instructie wordt gebruikt om de standaard werkdirectory van je Docker image te definiëren. De RUN, CMD, ENTRYPOINT en ADD instructies volgen op de WORKDIR instructie. Je kunt meerdere WORKDIR instructies toevoegen aan je Dockerfile, en als die niet bestaat, wordt hij automatisch aangemaakt.

USER

De USER instructie wordt gebruikt om de standaard gebruiker of gid te definiëren bij het draaien van het image. De RUN, CMD en ENTRYPOINT volgen op de USER instructie in het Dockerfile.

VOLUME

De VOLUME instructie wordt gebruikt om toegang/een gekoppelde directory tussen de container en de hostmachine mogelijk te maken.

Laten we nu beginnen met het maken van het eerste Dockerbestand.

Stap 1 – Docker installeren op Ubuntu 20.04

Voordat we een Dockerfile maken, installeren we Docker op ons Ubuntu 20.04 systeem, dat standaard beschikbaar is in de Ubuntu FocalFossa repository.

Werk alle pakketlijst op de Ubuntu repository bij en installeer Docker met het onderstaande apt commando.

sudo apt update
sudo apt install docker.io

Zodra alle installatie is voltooid, start je de Docker-service en voeg je hem toe aan de systeemstart.

systemctl start docker
systemctl enable docker

Controleer nu de Docker service met onderstaand commando.

systemctl status docker

De Docker service is up and running op de Ubuntu 20.04.

Docker Service starten

Voer vervolgens het onderstaande docker commando uit om te controleren of de installatie correct is.

docker run hello-world

Hieronder zie je het resultaat dat je krijgt.

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Zoals te zien is, krijg je het Hello World bericht van Docker, en is de Docker installatie op Ubuntu 20.04 succesvol afgerond.

Stap 2 – Dockerfile en andere configuraties maken

In deze stap laten we je zien hoe je een aangepaste Dockerafbeelding voor je applicatie bouwt met behulp van de Dockerfile. We zullen een nieuw aangepast Docker image maken op basis van het Ubuntu 20.04 image, voor de PHP-FPM en Nginx diensten, en vervolgens de nieuwe container draaien met een eenvoudig phpinfo script.

Maak eerst een nieuwe projectmap aan en maak een lege Dockerfile.

mkdir -p nginx-image; cd nginx-image/
touch Dockerfile

Bewerk nu het ‘Dockerfile’ script met je eigen editor (voor dit voorbeeld gebruiken we vim).

vim Dockerfile

Voeg bovenaan de regel de base-image Ubuntu 20.04 image toe met behulp van de FROM instructie zoals hieronder.

#Download base image ubuntu 20.04
FROM ubuntu:20.04

Voeg nu gedetailleerde informatie over de aangepaste image toe met de LABEL instructie.

# LABEL about the custom image
LABEL maintainer="[email protected]"
LABEL version="0.1"
LABEL description="This is custom Docker Image for \
the PHP-FPM and Nginx Services."

Voor de apt pakketten installatie slaan we elke interactieve post-installatie stap over met behulp van de omgevingsvariabele ‘DEBIAN_FRONTEND=noninteractive’.

# Disable Prompt During Packages Installation
ARG DEBIAN_FRONTEND=noninteractive

Voer vervolgens het commando ‘apt update’ uit voordat je pakketten installeert.

# Update Ubuntu Software repository
RUN apt update

Installeer nu de pakketten Nginx, PHP-FPM en supervisor. Als alle installatie is voltooid, verwijder dan alle pakketten cache om de grootte van de aangepaste image te verkleinen.

# Install nginx, php-fpm and supervisord from ubuntu repository
RUN apt install -y nginx php-fpm supervisor && \
    rm -rf /var/lib/apt/lists/* && \
    apt clean

Definieer een nieuwe omgevingsvariabele die kan worden doorgegeven op de aangepaste image.

#Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.4/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf

Kopieer nu de Nginx standaard configuratie naar de ‘nginx_vhost’ variabele, vervang de PHP configuratie ‘cgi.fix_pathinfo=1’ door ‘cgi.fix_pathinfo=0’ in het php.ini config bestand, voeg dan de ‘daemon off’ optie toe aan de standaard ‘nginx_conf’ variabele.

# Enable PHP-fpm on nginx virtualhost configuration
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
    echo "\ndaemon off;" >> ${nginx_conf}

Kopieer de aangepaste supervisord configuratie naar de ‘supervisor_conf’ variabele.

#Copy supervisor configuration
COPY supervisord.conf ${supervisor_conf}

Maak een nieuwe directory voor het PHP-FPM sock bestand, verander het eigendom van de web-root directory ‘/var/www/html’ en PHP-FPM directory ‘/run/php’ in de standaard gebruiker ‘www-data’.

RUN mkdir -p /run/php && \
    chown -R www-data:www-data /var/www/html && \
    chown -R www-data:www-data /run/php

Definieer het volume voor de aangepaste image zodat we al die mappen kunnen mounten op de hostmachine.

# Volume configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]

Voeg nu het ‘start.sh’ script toe en definieer het standaard container commando met de CMD instructie zoals hieronder.

# Copy start.sh script and define default command for the container
COPY start.sh /start.sh
CMD ["./start.sh"]

En als laatste open je de standaard HTTP- en HTTPS-poorten op de container met de EXPOSE instructie.

# Expose Port for the Application 
EXPOSE 80 443

Sla op en sluit af.

Hieronder staat het complete Dockerfile script dat we zojuist hebben gemaakt.

# Download base image ubuntu 20.04
FROM ubuntu:20.04

# LABEL about the custom image
LABEL maintainer="[email protected]"
LABEL version="0.1"
LABEL description="This is custom Docker Image for \
the PHP-FPM and Nginx Services."

# Disable Prompt During Packages Installation
ARG DEBIAN_FRONTEND=noninteractive

# Update Ubuntu Software repository
RUN apt update

# Install nginx, php-fpm and supervisord from ubuntu repository
RUN apt install -y nginx php-fpm supervisor && \
    rm -rf /var/lib/apt/lists/* && \
    apt clean
    
# Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.4/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf

# Enable PHP-fpm on nginx virtualhost configuration
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
    echo "\ndaemon off;" >> ${nginx_conf}
    
# Copy supervisor configuration
COPY supervisord.conf ${supervisor_conf}

RUN mkdir -p /run/php && \
    chown -R www-data:www-data /var/www/html && \
    chown -R www-data:www-data /run/php
    
# Volume configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]

# Copy start.sh script and define default command for the container
COPY start.sh /start.sh
CMD ["./start.sh"]

# Expose Port for the Application
EXPOSE 80 443

Vervolgens maken we een nieuwe aanvullende configuratie voor Nginx, supervisord, en het start.sh script.

De ‘standaard’ Nginx virtualhost configuratie zal de sectie voor de PHP-FPM bevatten. In feite kun je het PHP-script uitvoeren met de Aangepaste afbeelding zonder wijzigingen.

Maak een nieuwe Nginx ‘standaard’ virtualhost configuratie met je editor.

vim default

Plak er de volgende configuratie in.

server {
    listen 80 default_server;
 
    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
 
    server_name _;
 
    location / {
        try_files $uri $uri/ =404;
    }
 
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }
}

Opslaan en sluiten.

Vervolgens gaan we de ‘supervisrod.conf’ configuratie maken die zowel Nginx als het PHP-FPM programma bevat dat automatisch zal draaien.

Maak het bestand ‘supervisrod.conf’ aan met je editor.

vim supervisord.conf

Plak er de volgende configuratie in.

[unix_http_server]
file=/dev/shm/supervisor.sock   ; (the path to the socket file)
 
[supervisord]
logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
loglevel=info                ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024)
minprocs=200                 ; (min. avail process descriptors;default 200)
user=root             ;

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
 
[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock ; use a unix:// URL  for a unix socket
 
[include]
files = /etc/supervisor/conf.d/*.conf
 
[program:php-fpm7.4]
command=/usr/sbin/php-fpm7.4 -F
numprocs=1
autostart=true
autorestart=true
 
[program:nginx]
command=/usr/sbin/nginx
numprocs=1
autostart=true
autorestart=true

Opslaan en sluiten.

Maak nu het ‘start.sh’ script met t=jouw editor, het bevat het supervisord commando om te starten.

vim start.sh

Plak de volgende configuratie erin.

#!/bin/sh
/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

Opslaan en sluiten.

Maak het ‘start.sh’ script uitvoerbaar.

chmod +x start.sh

Het resultaat is dat alle configuratie voor onze aangepaste Docker image is gemaakt, hieronder staan alle configuraties die we hebben gemaakt.

tree .

Nu zijn we klaar om een nieuwe aangepaste image te maken op basis van deze configuraties.

Docker Service Status controleren

Stap 3 – Bouw nieuwe aangepaste en voer nieuwe container uit

Om het Docker custom image te maken, ga je naar de projectdirectory ‘nginx-image’ en voer je het commando ‘docker build’ uit zoals hieronder.

docker build -t nginx-image .

Het commando zal het basis-image Ubuntu 20.04 downloaden en een nieuw custom image maken met de naam ‘nginx-image.

Als al het proces is voltooid, controleer dan de lijst met beschikbare Docker-image op je systeem met het volgende commando.

docker image ls

Hieronder zie je het resultaat dat je krijgt.

Docker-afbeeldingen controleren

Zoals te zien is, is het nieuwe aangepaste Docker image ‘nginx-image’ aangemaakt.

Vervolgens gaan we de nieuwe Docker-container draaien op basis van het ‘nginx-image’.

Maak op je lokale machine een nieuwe map genaamd ‘webroot’ aan, waarin alle webbestanden worden opgeslagen.

mkdir -p /webroot

Maak nu een nieuwe container genaamd test-container met behulp van het docker run commando hieronder.

docker run -d -v /webroot:/var/www/html -p 8080:80 --name test-container nginx-image

Opmerking:

  • –naam test-container nginx-image = We maken een nieuwe container aan met de naam ’test-container’, gebaseerd op docker image ‘nginx-image’.
  • -p 8080:80 = test-container container draait op poort 8080 op de host machine.
  • -v /webroot:/var/www/html = /webroot directory op de host machine herschrijft de /var/www/html directory op de container.

Controleer daarna alle draaiende containers op je systeem met het volgende commando.

docker ps

Hieronder staat het resultaat dat je krijgt.

Controleer de lopende container

Als resultaat is de nieuwe container met de naam ’test-container’ op basis van het ‘nginx-image’ en het blootstellen van de poort 8080 up and running.

Stap 4 – Testen

Om er zeker van te zijn dat de container goed draait, maken we een nieuw index.html en phpinfo bestand aan in de ‘/webroot’ root directory op de host machine. Want de ‘/webroot’ directory is gemount in de containerdirectory ‘/var/www/html’.

Maak het bestand index.html aan in de ‘/webroot’ directory met het volgende commando.

echo '<h1>Nginx and PHP-FPM 7.4 inside Docker Container with Ubuntu 20.04 Base Image</h1>' > /webroot/index.html

Test nu de toegang tot je container met het commando curl op poort 8080.

curl server-ip:8080
curl -I server-ip:8080

Als resultaat krijg je de standaard index.html pagina die we zojuist gemaakt hebben.

index.html pagina maken

Maak vervolgens een nieuw PHP bestand ‘info.php’ aan in de ‘/webroot’ directory om er zeker van te zijn dat de PHP-FPM service draait.

Maak het bestand ‘info.php’ aan met het volgende commando.

echo '<?php phpinfo(); ?>' > /webroot/info.php

Open vervolgens je webbrowser en typ je server IP adres met poort ‘8080’ gevolgd door het pad van het ‘info.php’ bestand.

http://server-ip:8080/info.php

Nu krijg je de phpinfo pagina zoals hieronder.

phpinfo

Zoals te zien is, is de ’test-container’ met succes het PHP script geladen.

En als resultaat hebben we met succes een nieuw aangepast Docker image gemaakt en de nieuwe container op basis daarvan draaien zonder enige fout.