Cómo crear imágenes Docker con un Dockerfile en Ubuntu 20.04 LTS

Docker es una virtualización a nivel de sistema operativo destinada principalmente a desarrolladores y administradores de sistemas. Docker facilita la creación y el despliegue de aplicaciones en un entorno aislado.

Un Dockerfile es un script que contiene colecciones de comandos e instrucciones que se ejecutarán automáticamente en secuencia en el entorno Docker para construir una nueva imagen Docker.

En este tutorial, te mostraremos cómo crear tu propia imagen Docker con un Dockerfile. Explicaremos los detalles relacionados con el Dockerfile para que puedas construir tu propia imagen Docker.

Requisitos previos

Para esta guía, utilizaremos el Ubuntu 20.04 con 1 GB de RAM, 25 GB de espacio libre en disco y 2 CPUs. Además, utilizaremos Ubuntu 20.04 como imagen base para construir la imagen Docker personalizada.

Introducción al comando Dockerfile

Un Dockerfile es un script que contiene todos los comandos para construir una imagen Docker. El Dockerfile contiene todas las instrucciones que se utilizarán para crear la imagen Docker con el comando ‘docker build’.

Antes de crear tu primer Dockerfile, debes familiarizarte con las instrucciones del Dockerfile. A continuación, algunas instrucciones del Dockerfile que debes conocer.

DESDE

Establece la imagen base para la nueva imagen que quieres crear. La instrucción FROM inicializará la nueva etapa de construcción y debe estar situada en la parte superior del Dockerfile.

ETIQUETA

Con esta instrucción puedes añadir información adicional sobre tu imagen Docker, como la versión, la descripción, el mantenedor, etc. La instrucción LABEL es un par clave-valor que te permite añadir varias etiquetas y valores de varias líneas.

EJECUTAR

Esta instrucción se utiliza para ejecutar un comando durante el proceso de construcción de la imagen Docker. Puedes instalar paquetes adicionales necesarios para tus imágenes Docker.

AÑADIR

La instrucción ADD se utiliza para copiar archivos, directorios o archivos remotos desde la URL a tus imágenes Docker, desde el ‘src’ a la ruta absoluta ‘dest’. Además, puedes configurar la propiedad por defecto de tu archivo.

ENV

La instrucción ENV se utiliza para definir una variable de entorno que se puede utilizar durante la etapa de construcción y también se puede sustituir en línea en muchos.

CMD

La instrucción CMD se utiliza para definir el comando por defecto a ejecutar cuando se ejecuta el contenedor. El Dockerfile sólo debe contener una instrucción CMD, y si hay varias CMD, se ejecutará la última instrucción CMD.

EXPOSE

Esta instrucción se utiliza para exponer el puerto del contenedor en los puertos de red específicos en tiempo de ejecución. El protocolo expuesto por defecto es TCP, pero puedes especificar si es TCP o UDP.

ARG

La instrucción ARG se utiliza para definir una variable que el usuario puede pasar en tiempo de construcción. Puedes utilizar esta instrucción en el ‘comando de construcción’ de Docker durante el tiempo de construcción utilizando la opción ‘–build-arg variable=valor’ y puede pasarse a través del Dockerfile. Además, puedes utilizar varios ARG en el Dockerfile.

ENTRYPOINT

La instrucción ENTRYPOINT se utiliza para definir el primer comando y el predeterminado que se ejecutará cuando el contenedor se esté ejecutando. Define el comando para iniciar tu aplicación con la instrucción ENTRYPOINT.

WORKDIR

La instrucción WORKDIR se utiliza para definir el directorio de trabajo por defecto de tu imagen Docker. Las instrucciones RUN, CMD, ENTRYPOINT y ADD siguen a la instrucción WORKDIR. Puedes añadir varias instrucciones WORKDIR en tu Dockerfile, y si no existe, se creará automáticamente.

USER

La instrucción USER se utiliza para definir el usuario o gid por defecto al ejecutar la imagen. Las instrucciones RUN, CMD y ENTRYPOINT siguen a la instrucción USER en el Dockerfile.

VOLUMEN

La instrucción VOLUME ad utiliza para habilitar el acceso/enlace del directorio entre el contenedor y la máquina anfitriona.

Ahora, vamos a empezar a crear el primer Dockerfile.

Paso 1 – Instalar Docker en Ubuntu 20.04

Antes de crear un Dockerfile, instalaremos el Docker en nuestro sistema Ubuntu 20.04, que está disponible por defecto en el repositorio FocalFossa de Ubuntu.

Actualiza toda la lista de paquetes en el repositorio de Ubuntu e instala Docker utilizando el comando apt que aparece a continuación.

sudo apt update
sudo apt install docker.io

Una vez completada la instalación, inicia el servicio Docker y añádelo al arranque del sistema.

systemctl start docker
systemctl enable docker

Ahora comprueba el servicio Docker utilizando el siguiente comando.

systemctl status docker

El servicio Docker está funcionando en Ubuntu 20.04.

Iniciar el servicio Docker

A continuación, ejecuta el siguiente comando Docker para asegurarte de que la instalación es correcta.

docker run hello-world

A continuación se muestra el resultado que obtendrás.

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/

Como se puede ver, obtienes el mensaje Hello World de Docker, y la instalación de Docker en Ubuntu 20.04 se ha completado con éxito.

Paso 2 – Crear Dockerfile y otras configuraciones

En este paso, te mostraremos cómo construir una imagen Docker personalizada para tu aplicación utilizando el Dockerfile. Crearemos una nueva imagen Docker personalizada basada en la imagen de Ubuntu 20.04, para los servicios PHP-FPM y Nginx, y luego ejecutaremos el nuevo contenedor con un simple script phpinfo.

Primero, crea un nuevo directorio de proyecto y crea un Dockerfile vacío.

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

Ahora edita el script ‘Dockerfile’ usando tu propio editor (para este ejemplo estamos usando vim).

vim Dockerfile

En la parte superior de la línea, añade la imagen base de Ubuntu 20.04 utilizando la instrucción FROM como se indica a continuación.

#Download base image ubuntu 20.04
FROM ubuntu:20.04

Ahora añade información detallada sobre la imagen personalizada utilizando la instrucción LABEL.

# 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."

Para la instalación de los paquetes apt, omitiremos cualquier paso interactivo posterior a la instalación utilizando la variable de entorno ‘DEBIAN_FRONTEND=noninteractive’.

# Disable Prompt During Packages Installation
ARG DEBIAN_FRONTEND=noninteractive

A continuación, ejecuta el comando ‘apt update’ antes de instalar cualquier paquete.

# Update Ubuntu Software repository
RUN apt update

Ahora instala los paquetes Nginx, PHP-FPM y supervisor. Una vez completada la instalación, elimina todos los paquetes de la caché para reducir el tamaño de la imagen personalizada.

# 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 una nueva variable de entorno que se pueda pasar a la imagen personalizada.

#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

Ahora copia la configuración por defecto de Nginx en la variable ‘nginx_vhost’, sustituye la configuración de PHP ‘cgi.fix_pathinfo=1’ por ‘cgi.fix_pathinfo=0’ en el archivo de configuración php.ini, y añade la opción ‘daemon off’ a la variable por defecto ‘nginx_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}

Copia la configuración personalizada de supervisord en la variable ‘supervisor_conf’.

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

Crea un nuevo directorio para el archivo sock de PHP-FPM, cambia la propiedad del directorio raíz de la web ‘/var/www/html’ y del directorio de PHP-FPM ‘/run/php’ al usuario por defecto ‘www-data’.

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

Define el volumen de la imagen personalizada para que podamos montar todos esos directorios en la máquina anfitriona.

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

Ahora añade el script ‘start.sh’ y define el comando contenedor por defecto utilizando la instrucción CMD como se indica a continuación.

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

Y por último, abre los puertos HTTP y HTTPS por defecto en el contenedor utilizando la instrucción EXPOSE.

# Expose Port for the Application 
EXPOSE 80 443

Guarda y cierra.

A continuación se muestra el script Dockerfile completo que acabamos de crear.

# 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

A continuación, crearemos una nueva configuración adicional para Nginx, supervisord y el script start.sh.

La configuración «por defecto» del virtualhost de Nginx contendrá la sección para el PHP-FPM. En efecto, puedes ejecutar el script PHP utilizando la imagen personalizada sin ningún cambio.

Crea una nueva configuración «por defecto» del virtualhost de Nginx con tu editor.

vim default

Pega en ella la siguiente configuración.

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;
    }
}

Guarda y cierra.

A continuación, crearemos la configuración ‘supervisrod.conf’ que contiene el programa Nginx y PHP-FPM que se ejecutará automáticamente.

Crea el archivo ‘supervisrod.conf’ utilizando tu editor.

vim supervisord.conf

Pega en él la siguiente configuración.

[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

Guarda y cierra.

Ahora crea el script ‘start.sh’ usando t=tu editor, contendrá el comando supervisord para arrancar.

vim start.sh

Pega en él la siguiente configuración.

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

Guarda y cierra.

Haz que el script ‘start.sh’ sea ejecutable.

chmod +x start.sh

Como resultado, se ha creado toda la configuración para nuestra imagen Docker personalizada, a continuación están todas las configuraciones que hemos creado.

tree .

Ahora estamos listos para crear una nueva imagen personalizada basada en estas configuraciones.

Comprobar el estado del servicio Docker

Paso 3 – Construir la nueva imagen personalizada y ejecutar el nuevo contenedor

Para crear la imagen personalizada Docker, ve al directorio del proyecto ‘nginx-image’ y ejecuta el comando ‘docker build’ como se indica a continuación.

docker build -t nginx-image .

El comando descargará la imagen base de Ubuntu 20.04 y creará una nueva imagen personalizada con el nombre ‘nginx-image’.

Una vez completado todo el proceso, comprueba la lista de imágenes Docker disponibles en tu sistema utilizando el siguiente comando.

docker image ls

A continuación se muestra el resultado que obtendrás.

Comprueba las imágenes Docker

Como puedes ver, se ha creado la nueva imagen Docker personalizada ‘nginx-image’.

A continuación, ejecutaremos el nuevo contenedor Docker basado en la imagen ‘nginx-image’.

En tu máquina local, crea un nuevo directorio llamado ‘webroot’ que se utilizará para almacenar todos los archivos web.

mkdir -p /webroot

Ahora crea un nuevo contenedor llamado test-container utilizando el comando docker run que aparece a continuación.

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

Nota:

  • –name test-container nginx-image = Creamos un nuevo contenedor con el nombre ‘test-container’, basado en la imagen docker ‘nginx-image’.
  • -p 8080:80 = El contenedor test-container se ejecuta en el puerto 8080 de la máquina anfitriona.
  • -v /webroot:/var/www/html = el directorio /webroot en la máquina anfitriona reescribe el directorio /var/www/html en el contenedor.

Después de esto, comprueba todos los contenedores que se están ejecutando en tu sistema utilizando el siguiente comando.

docker ps

A continuación se muestra el resultado que obtendrás.

Comprobar el contenedor en funcionamiento

Como resultado, el nuevo contenedor llamado ‘test-container’ basado en la ‘nginx-image’ y que expone el puerto 8080 está en marcha.

Paso 4 – Prueba

Para asegurarnos de que el contenedor funciona correctamente, crearemos un nuevo archivo index.html y phpinfo en el directorio raíz ‘/webroot’ de la máquina anfitriona. Porque el directorio ‘/webroot’ está montado en el directorio del contenedor ‘/var/www/html’.

Crea el archivo index.html en el directorio ‘/webroot’ con el siguiente comando.

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

Ahora prueba a acceder a tu contenedor con el comando curl en el puerto 8080.

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

Como resultado, obtendrás la página index.html por defecto que acabamos de crear.

crear la página index.html

A continuación, crea un nuevo archivo PHP ‘info.php’ en el directorio ‘/webroot’ para asegurarte de que el servicio PHP-FPM se está ejecutando.

Crea el archivo ‘info.php’ con el siguiente comando.

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

A continuación, abre tu navegador web y escribe la dirección IP de tu servidor con el puerto ‘8080’ seguido de la ruta del archivo ‘info.php’.

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

Ahora obtendrás la página phpinfo como la siguiente.

phpinfo

Como se puede ver, el ‘contenedor-prueba’ ha cargado con éxito el script PHP.

Y como resultado, hemos creado con éxito una nueva imagen Docker personalizada y hemos ejecutado el nuevo contenedor basado en ella sin ningún error.

También te podría gustar...