Vista general de Dockerfile
Dockerfile
Todo comienza con un Dockerfile.
Docker compila imágenes leyendo las instrucciones de un Dockerfile. Un Dockerfile es un archivo de texto que contiene las instrucciones para compilar tu código fuente. La sintaxis de las instrucciones del Dockerfile está definida por la referencia de especificación en la referencia de Dockerfile.
Aquí tienes los tipos de instrucciones más comunes:
| Instrucción | Descripción |
|---|---|
FROM <imagen> | Define una base para tu imagen. |
RUN <comando> | Ejecuta cualquier comando en una nueva capa encima de la imagen actual y confirma el resultado. RUN también tiene una forma de shell para ejecutar comandos. |
WORKDIR <directorio> | Establece el directorio de trabajo para cualquier instrucción RUN, CMD, ENTRYPOINT, COPY y ADD que le sigan en el Dockerfile. |
COPY <origen> <destino> | Copia nuevos archivos o directorios desde <origen> y los añade al sistema de archivos del contenedor en la ruta <destino>. |
CMD <comando> | Te permite definir el programa predeterminado que se ejecuta una vez que inicias el contenedor basado en esta imagen. Cada Dockerfile solo tiene un CMD, y solo se respeta la última instancia de CMD cuando existen varias. |
Los Dockerfiles son entradas cruciales para las compilaciones de imágenes y pueden facilitar compilaciones de imágenes automatizadas y multicapa basadas en tus configuraciones únicas. Los Dockerfiles pueden comenzar siendo simples y crecer con tus necesidades para soportar escenarios más complejos.
Nombre de archivo
El nombre de archivo predeterminado para un Dockerfile es Dockerfile, sin extensión de
archivo. El uso del nombre predeterminado te permite ejecutar el comando docker build
sin tener que especificar banderas de comando adicionales.
Algunos proyectos pueden necesitar Dockerfiles distintos para propósitos específicos. Una
convención común es nombrarlos como <algo>.Dockerfile. Puedes especificar el
nombre del archivo Dockerfile utilizando la bandera --file para el comando docker build.
Consulta la
referencia de CLI de docker build
para obtener información sobre la bandera --file.
NoteRecomendamos usar el nombre predeterminado (
Dockerfile) para el Dockerfile principal de tu proyecto.
Imágenes de Docker
Las imágenes de Docker constan de capas. Cada capa es el resultado de una instrucción de compilación en el Dockerfile. Las capas se apilan secuencialmente y cada una es una diferencia (delta) que representa los cambios aplicados a la capa anterior.
Ejemplo
Así es como se ve un flujo de trabajo típico para compilar aplicaciones con Docker.
El siguiente código de ejemplo muestra una pequeña aplicación "Hello World" escrita en Python, que utiliza el framework Flask.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"Para distribuir y desplegar esta aplicación sin Docker Build, tendrías que asegurarte de que:
- Las dependencias de tiempo de ejecución requeridas estén instaladas en el servidor.
- El código Python se suba al sistema de archivos del servidor.
- El servidor inicie tu aplicación utilizando los parámetros necesarios.
El siguiente Dockerfile crea una imagen de contenedor, que tiene todas las dependencias instaladas y que inicia automáticamente tu aplicación.
# syntax=docker/dockerfile:1
FROM ubuntu:22.04
# install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip install flask==3.0.*
# install app
COPY hello.py /
# final configuration
ENV FLASK_APP=hello
EXPOSE 8000
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]Aquí tienes un desglose de lo que hace este Dockerfile:
- Sintaxis de Dockerfile
- Imagen base
- Configuración del entorno
- Comentarios
- Instalación de dependencias
- Copia de archivos
- Configuración de variables de entorno
- Puertos expuestos
- Inicio de la aplicación
Sintaxis de Dockerfile
La primera línea que se debe añadir a un Dockerfile es una
directiva del analizador # syntax.
Aunque es opcional, esta directiva le indica al constructor de Docker qué sintaxis utilizar
al analizar el Dockerfile, y permite que las versiones anteriores de Docker con BuildKit habilitado
utilicen un frontend de Dockerfile específico antes de
comenzar la compilación. Las
directivas del analizador
deben aparecer antes de cualquier otro comentario, espacio en blanco o instrucción de Dockerfile en
tu Dockerfile, y deben ser la primera línea en los Dockerfiles.
# syntax=docker/dockerfile:1TipRecomendamos utilizar
docker/dockerfile:1, que siempre apunta a la última versión de la sintaxis de la versión 1. BuildKit busca automáticamente actualizaciones de la sintaxis antes de compilar, asegurándose de que estás utilizando la versión más reciente.
Imagen base
La línea que sigue a la directiva de sintaxis define qué imagen base utilizar:
FROM ubuntu:22.04La
instrucción FROM establece tu imagen
base como la versión 22.04 de Ubuntu. Todas las instrucciones que siguen se ejecutan
en esta imagen base: un entorno Ubuntu. La notación ubuntu:22.04 sigue
el estándar nombre:etiqueta para nombrar imágenes de Docker. Cuando compilas imágenes,
utilizas esta notación para nombrar tus imágenes. Hay muchas imágenes públicas que puedes
aprovechar en tus proyectos importándolas en tus pasos de compilación utilizando la
instrucción FROM del Dockerfile.
Docker Hub contiene un gran conjunto de imágenes oficiales que puedes utilizar para este propósito.
Configuración del entorno
La siguiente línea ejecuta un comando de compilación dentro de la imagen base.
# install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pipEsta
instrucción RUN ejecuta una
shell en Ubuntu que actualiza el índice de paquetes APT e instala las herramientas de Python en
el contenedor.
Comentarios
Observa la línea # install app dependencies. Esto es un comentario. Los comentarios en los
Dockerfiles comienzan con el símbolo #. A medida que tu Dockerfile evoluciona, los comentarios pueden
ser fundamentales para documentar cómo funciona tu Dockerfile para futuros lectores y editores del
archivo, incluyéndote a ti mismo en el futuro.
NoteEs posible que hayas notado que los comentarios se denotan utilizando el mismo símbolo que la directiva de sintaxis en la primera línea del archivo. El símbolo solo se interpreta como una directiva si el patrón coincide con una directiva y aparece al principio del Dockerfile. De lo contrario, se trata como un comentario.
Instalación de dependencias
La segunda instrucción RUN instala la dependencia flask requerida por la
aplicación Python.
RUN pip install flask==3.0.*Un requisito previo para esta instrucción es que pip esté instalado en el contenedor de
compilación. El primer comando RUN instala pip, lo que garantiza que se pueda
usar el comando para instalar el framework web flask.
Copia de archivos
La siguiente instrucción utiliza la
instrucción COPY para copiar el
archivo hello.py desde el contexto de compilación local al directorio raíz de nuestra imagen.
COPY hello.py /Un contexto de compilación es el conjunto de archivos a los que puedes acceder
en las instrucciones de Dockerfile como COPY y ADD.
Después de la instrucción COPY, el archivo hello.py se añade al sistema de archivos
del contenedor de compilación.
Configuración de variables de entorno
Si tu aplicación utiliza variables de entorno, puedes establecer variables de entorno
en tu compilación de Docker utilizando la
instrucción ENV.
ENV FLASK_APP=helloEsto establece una variable de entorno de Linux que necesitaremos más adelante. Flask, el framework utilizado en este ejemplo, utiliza esta variable para iniciar la aplicación. Sin esto, flask no sabría dónde encontrar nuestra aplicación para poder ejecutarla.
Puertos expuestos
La
instrucción EXPOSE marca que
nuestra imagen final tiene un servicio escuchando en el puerto 8000.
EXPOSE 8000Esta instrucción no es obligatoria, pero es una buena práctica y ayuda a que las herramientas y los miembros del equipo entiendan lo que hace esta aplicación.
Inicio de la aplicación
Finalmente, la
instrucción CMD establece el
comando que se ejecuta cuando el usuario inicia un contenedor basado en esta imagen.
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]Este comando inicia el servidor de desarrollo de flask escuchando en todas las direcciones
en el puerto 8000. El ejemplo aquí utiliza la versión "exec form" de CMD.
También es posible utilizar "shell form":
CMD flask run --host 0.0.0.0 --port 8000Existen diferencias sutiles entre estas dos versiones,
por ejemplo, en cómo capturan señales como SIGTERM y SIGKILL.
Para obtener más información sobre estas diferencias, consulta
Shell and exec form.
Compilación
Para compilar una imagen de contenedor utilizando el ejemplo de Dockerfile de la
sección anterior, utilizas el comando docker build:
$ docker build -t test:latest .
La opción -t test:latest especifica el nombre y la etiqueta de la imagen.
El punto único (.) al final del comando establece el
contexto de compilación en el directorio actual. Esto significa que la
compilación espera encontrar el Dockerfile y el archivo hello.py en el directorio
desde donde se invoca el comando. Si esos archivos no están allí, la compilación falla.
Después de compilar la imagen, puedes ejecutar la aplicación como un contenedor con
docker run, especificando el nombre de la imagen:
$ docker run -p 127.0.0.1:8000:8000 test:latest
Esto publica el puerto 8000 del contenedor en http://localhost:8000 en el
host de Docker.
TipPara mejorar el análisis estático, la navegación de código y el escaneo de vulnerabilidades de tus Dockerfiles en Visual Studio Code, consulta la extensión Docker DX.