Saltar a contenido

Archivo Dockerfile

Idea general

El archivo Dockerfile es el archivo de configuración que se necesita para crear y modificar las imágenes: agregar las rutinas del programa, instalar dependencias adicionales, etc.

Su uso es indispensable para cualquier proyecto que dependa de rutinas propias.

Sintaxis genérica

Supóngase un proyecto sencillo escrito en Python, cuya estructura de archivos es la siguiente:

Arbol de archivos - Proyecto
.
├── src
   └── rutina.py
└── requirements.txt

En este ejemplo las rutinas de Python se alojan en la carpeta src y se adjunta un archivo de requisitos para instalar los paquetes necesarios.

Se agrega el archivo de configuración al proyecto para crear la imagen:

Arbol de archivos - Proyecto (con Dockerfile)
.
├── src
   └── rutina.py
├── requirements.txt
└── Dockerfile

El archivo Dockerfile tiene una forma como esta:

Dockerfile - básico
# imagen de base - version fija
FROM python:alpine

# directorio de trabajo del contenedor (se crea automáticamente)
WORKDIR /code

# copia de archivo de dependencias al directorio de trabajo
COPY requirements.txt ./

# instalación de paquetes de python
RUN pip install --no-cache-dir -r requirements.txt

# actualización de PIP
RUN pip install --upgrade pip

# copia de rutinas al directorio de trabajo
COPY src/ ./

# comando, opciones y argumentos
CMD ["python", "rutina.py"]

Al ser construida la imagen su estructura interna toma esta forma:

Arbol de archivos - Imagen
/
|   # directorios estándar
├── run
├── root
├── etc
├── ...
|   # directorio de trabajo
└── code
    ├── requirements.txt
    └── rutina.py

Cláusulas básicas

El archivo Dockerfile tiene una serie de cláusulas básicas que se explican a continuación.

FROM

La cláusula FROM especifica qué imagen de base se utilizará para el proyecto. Permite indicar nombre y etiqueta de versión.

Uso:

Imagen de referencia
FROM  nombre_imagen:tag_version

Esta cláusula es obligatoria y se indica al comienzo.

WORKDIR

WORKDIR definer una ruta de trabajo para el programa dentro del contenedor. Si dicha ruta no existe en la imagen original entonces es creada automáticamente.

Uso:

Directorio de trabajo
WORKDIR ruta_interna_contenedor

COPY

Con COPY se copian los contenidos necesarios del proyecto al interior de la nueva imagen. El código fuente, los archivos de dependencias, assets (iconos, imagenes, etc.) se transfieren de esta manera.

Uso:

Copia de contenidos
COPY archivo_proyecto   ruta_destino/   
COPY carpeta_proyecto/  ruta_destino/

Esta cláusula se usa igual que el comando cp de Bash. Si la ruta de destino indicada es del tipo relativa entonces se toma por referencia el directorio de trabajo.

RUN

Este comando se usa típicamente para instalar paquetes adicionales del sistema operativo. Estos paquetes quedarán guardados dentro de la imagen final.

Por ejemplo, para instalar los paquetes de Python con PIP lo habitual es hacerlo mediante archivo TXT y deshabilitando la caché de PIP:

Paquetes - PIP
RUN pip install --no-cache-dir -r requirements.txt

la instalación de paquetes en la imagen con PIP se hace de manera global: crear un entorno virtual no trae ninguna ventaja porque el mismo contenedor hará las veces de entorno virtual.

Si se necesitan instalar paquetes faltantes del sistema operativo se llama a su gestor de paquetes:

Paquetes - Gestor APT
RUN apt install paquete_debian
Paquetes - Gestor APK
RUN apk add paquete_alpine

Nótese que no es necesario agregar la cláusula sudo para instalar paquetes dentro de las imágenes.

CMD

CMD define qué comando deberá ejecutar la imagen cuando sea puesto en marcha dentro de un contenedor. También permite definir argumentos posicionales y opciones preasignados.

La notación recomendada es la siguiente:

Comandos
CMD ["comando", "argumento_1", "argumento_1", "--opcion_1", ...]

En el caso de implementar rutinas de Python el comando habitual es python y el primer argumento será el nombre de la rutina principal:

Comandos en Python
CMD ["python", "rutina.py", "argumento_rutina", "--opcion_rutina"]

Los comandos y opciones definidos por CMD pueden ser sobreescritos externamente durante el despliegue del contenedor.

CMD siempre se especifica al final.

Construcción

La construcción de la nueva imagen se realiza siguiendo el orden indicado en el archivo Dockerfile.

El gestor de contenedores usado sólo repite los pasos de construcción donde detecta cambios: código fuente reemplazado, cambios en las dependencias y sus versiones, etc.

Copia de código fuente al final

El código fuente se copia cerca del final porque es lo que cambia con mayor frecuencia. De esta manera se minimiza el tiempo de construcción.

Hay varias maneras de construir las imágenes:

directa - comando build

El comando build construye la imagen y le asigna el nombre y versión especificados por la opción -t.

Uso básico:

Construir - build
cd ruta_dockerfile
podman build .  -t nuevo_nombre:version 

indirecta - comando compose

En este caso la construcción de la imagen se realiza indirectamente durante el despliegue con el comando compose, el cual requiere a su vez el archivo compose.yml

Esto se explica en capítulos posteriores.