Cómo escribir un Dockerfile para principiantes

Cómo escribir un Dockerfile para principiantes

Antes de profundizar en qué es un Dockerfile, realicemos un pequeño experimento. ¿Recuerdas la imagen de Python que descargamos en la sección anterior? Primero, ingresemos al contenedor usando el comando docker run -it. Recuerda qué hace el parámetro -it: asigna una pseudo-TTY al contenedor, permitiendo que el usuario interactúe con él. Una vez dentro del contenedor, listemos todos los archivos en el directorio actual:

[root@novita ~]# docker run -it python:3.7 /bin/bash
root@692f87774bf7:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@692f87774bf7:/# 

A continuación, crearemos un archivo llamado hello.py y luego listaremos todos los archivos nuevamente:

root@692f87774bf7:/# touch hello.py
root@692f87774bf7:/# ls
bin  boot  dev  etc  hello.py  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

Puedes ver que hello.py se ha creado. Ahora, salgamos del contenedor y reingresemos al modo interactivo del contenedor usando el mismo comando docker run -it python:3.7 /bin/bash, y luego listemos todos los archivos:

root@692f87774bf7:/# exit
exit
[root@novita ~]# docker run -it python:3.7 /bin/bash
root@65c767655e8a:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@65c767655e8a:/#

Seguramente ya habrás notado el problema. Curiosamente, el archivo que creamos antes ha desaparecido. Esto se debe a que las acciones realizadas dentro del contenedor no modifican la imagen. El contenedor simplemente agrega una capa de escritura sobre la imagen, como un papel de calco sobre una plantilla de caligrafía: no importa lo que escribas en el papel de calco, no afecta la capa inferior. Esta función es similar a una instantánea de máquina virtual.

Pero aquí está el problema: si las acciones dentro del contenedor no modifican la imagen, ¿cómo podemos lograr un despliegue rápido sin repetir ciertas operaciones antes de cada despliegue de código? Eso sería bastante ineficiente. Supongamos que eres el líder técnico de una plataforma de redes sociales y de repente ocurre un evento viral que requiere escalar rápidamente a cientos de servidores en la nube para manejar el tráfico masivo de usuarios. Tu equipo ha elegido Docker para el despliegue de la aplicación. Si desplegaras usando el método anterior, los usuarios podrían decepcionarse. Para cuando tu servicio se recupere, ellos podrían haberse ido a otra plataforma.

Aquí es donde entra el Dockerfile. Según la introducción oficial de Docker:

Docker puede construir imágenes automáticamente leyendo las instrucciones de un Dockerfile. Un Dockerfile es un documento de texto que contiene todos los comandos que un usuario podría ejecutar en la línea de comandos para ensamblar una imagen. Usando docker build, los usuarios pueden crear una construcción automatizada que ejecuta varias instrucciones de línea de comandos en sucesión.

En términos más simples, un Dockerfile es un documento de texto que contiene todos los comandos necesarios para construir una imagen desde la línea de comandos. Es como un manual de instrucciones para armar un conjunto de piezas hasta obtener la imagen deseada.

Exploremos cómo construir un Dockerfile a partir de un escenario práctico, usando una imagen de Python como ejemplo. En mi máquina local (fuera del contenedor), hay un script de Python llamado Optimal_Hotel_Matching.py. Es un programa de web scraping. Intentemos ejecutarlo dentro del contenedor:

Como era de esperar, aparece un error porque la librería HTTP requests, que es un módulo de terceros, no está instalada en la imagen de Python. Este es un escenario típico en el que necesitamos configurar un entorno de dependencias. Intentemos resolverlo usando un Dockerfile.

Antes de escribir nuestro primer Dockerfile, familiaricémonos con algunas instrucciones comunes del Dockerfile:

  • FROM: Especifica la imagen base para la construcción.
  • MAINTAINER: Describe al creador de la imagen con su nombre y correo electrónico.
  • RUN: Uno de los comandos más importantes en un Dockerfile. Ejecuta comandos en el contenedor y confirma los resultados.
  • CMD: Especifica el comando que se ejecutará cuando se inicie el contenedor.
  • COPY: Copia archivos del host al sistema de archivos del contenedor.
  • WORKDIR: Establece el directorio de trabajo para cualquier comando RUN, CMD o ENTRYPOINT que le siga en el Dockerfile.

Ahora, escribamos nuestro primer Dockerfile para satisfacer nuestras necesidades: instalar la librería requests y ejecutar el script. Aquí hay una posible solución:

FROM python:3.7                             # Especifica la imagen base como python:3.7
MAINTAINER ultra "tech@novita.ai"     # Nombre y correo del creador de la imagen
RUN pip install requests                  # Instala la librería requests
WORKDIR /dockerfileTest                   # Establece el directorio de trabajo
COPY . .                                  # Copia el contenido del directorio actual dentro del contenedor
CMD ["python", "Optimal_Hotel_Matching.py"]  # Comando para ejecutar el script

Guarda el contenido anterior en un archivo llamado Dockerfile en tu directorio de proyecto. Ahora, construyamos la imagen usando el comando docker build, etiquetándola para identificarla fácilmente:

[root@novita dockerfileTest]# docker build --tag python:requests .
Sending build context to Docker daemon  5.12 kB
...

Después de que la construcción termine, usa el comando docker images para verificar:

[root@novita dockerfileTest]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
python                  requests            04f20acdc288        2 hours ago         926 MB
...

Puedes ver que se ha generado localmente una nueva imagen de Python etiquetada como requests. Intenta ejecutar esta imagen para ver si el error No module named 'requests' persiste y si el programa se ejecuta como se espera.

[root@novita dockerfileTest]# docker run python:requests
Computing distance between 116.368816,39.866464  and  116.438946,39.921624
Computing distance between 116.370910,39.869603  and  116.438946,39.921624
...

¡Éxito! El contenedor ejecutó el código y terminó.

¿Es esto todo? En este artículo, he compartido una aplicación simple de los Dockerfiles. En los entornos de producción empresarial reales, los Dockerfiles tienden a ser más complejos.

Novita AI es la plataforma integral en la nube que potencia tus ambiciones de IA. Con APIs integradas sin problemas, computación serverless y aceleración por GPU, proporcionamos las herramientas rentables que necesitas para construir y escalar rápidamente tu negocio impulsado por IA. Elimina los dolores de cabeza de infraestructura y comienza gratis: Novita AI hace realidad tus sueños de IA.

Lectura recomendada:

  1. Guía definitiva para desarrollar la herramienta de mejora de escala ESRGAN 4x
  2. Domina Stable Diffusion LoRA: Estrategias para el éxito