Instrucciones avanzadas de Dockerfile
En este último paso, exploraremos algunas instrucciones adicionales de Dockerfile y las mejores prácticas que pueden ayudar a hacer que tus imágenes de Docker sean más seguras, mantenibles y fáciles de usar. También nos centraremos en la solución de problemas y la verificación de cada paso del proceso.
-
En WebIDE, abre el archivo Dockerfile
nuevamente.
-
Reemplaza el contenido con lo siguiente:
## Build stage
FROM python:3.9-slim AS builder
WORKDIR /app
COPY requirements.txt.
RUN pip install --user --no-cache-dir -r requirements.txt
## Final stage
FROM python:3.9-slim
## Create a non-root user
RUN useradd -m appuser
## Install curl for healthcheck
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
WORKDIR /app
## Dynamically determine Python version and site-packages path
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && \
SITE_PACKAGES_PATH="/home/appuser/.local/lib/python${PYTHON_VERSION}/site-packages" && \
mkdir -p "${SITE_PACKAGES_PATH}" && \
chown -R appuser:appuser /home/appuser/.local
## Copy site-packages and binaries using the variable
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}"
COPY --from=builder /root/.local/bin /home/appuser/.local/bin
COPY app.py.
ENV PATH=/home/appuser/.local/bin:$PATH
ENV ENVIRONMENT=production
## Set the user to run the application
USER appuser
## Use ENTRYPOINT with CMD
ENTRYPOINT ["python"]
CMD ["app.py"]
EXPOSE 5000
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:5000/ || exit 1
ARG BUILD_VERSION
LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="${BUILD_VERSION:-1.0}"
LABEL description="Flask app demo with advanced Dockerfile techniques"
Analicemos los nuevos conceptos introducidos en este Dockerfile:
RUN useradd -m appuser
: Esto crea un nuevo usuario llamado appuser
en el contenedor. Ejecutar aplicaciones como un usuario que no es root es una de las mejores prácticas de seguridad, ya que limita el daño potencial si la aplicación se ve comprometida. La bandera -m
crea un directorio de inicio para el usuario.
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
: Esto instala el paquete curl, que es necesario para que funcione la instrucción HEALTHCHECK. También limpiamos la caché de apt para reducir el tamaño de la imagen.
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') &&...
: Este conjunto de comandos determina dinámicamente la versión de Python dentro del contenedor y crea el directorio site-packages
correcto para el usuario appuser
. También establece los permisos correctos para el directorio local del usuario.
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}"
: Esta instrucción copia los paquetes de Python instalados desde la etapa builder
a la ruta site-packages
determinada dinámicamente dentro de la imagen final, asegurando que los paquetes se coloquen en la ubicación correcta para que los use el usuario appuser
.
COPY --from=builder /root/.local/bin /home/appuser/.local/bin
: Esto copia los scripts ejecutables instalados por pip
(como la interfaz de línea de comandos de Flask, si es que hay alguno) desde la etapa builder
al directorio local bin
del usuario appuser
.
ENTRYPOINT ["python"]
con CMD ["app.py"]
: Cuando se usan juntos, ENTRYPOINT
define el ejecutable principal para el contenedor (en este caso, python
), y CMD
proporciona los argumentos predeterminados para ese ejecutable (app.py
). Este patrón permite flexibilidad: los usuarios pueden ejecutar el contenedor y ejecutar app.py
por defecto, o pueden anular el CMD
para ejecutar otros scripts o comandos de Python.
HEALTHCHECK
: Esta instrucción configura una comprobación de salud para el contenedor. Docker ejecutará periódicamente el comando especificado (curl -f http://localhost:5000/
) para determinar si el contenedor está saludable. Las banderas --interval=30s
y --timeout=3s
establecen el intervalo de comprobación y el tiempo de espera respectivamente. Si el comando curl
falla (devuelve un código de salida distinto de cero), el contenedor se considera no saludable.
ARG BUILD_VERSION
: Esto define un argumento de construcción llamado BUILD_VERSION
. Los argumentos de construcción te permiten pasar valores a la imagen de Docker en el momento de la construcción.
LABEL version="${BUILD_VERSION:-1.0}"
: Esto establece una etiqueta llamada version
en la imagen de Docker. Utiliza el argumento de construcción BUILD_VERSION
. Si se proporciona BUILD_VERSION
durante la construcción, se utilizará su valor; de lo contrario, se establece como valor predeterminado 1.0
(utilizando la sintaxis de valor predeterminado :-
).
- Ahora, construyamos esta nueva imagen, especificando una versión de construcción:
docker build -t advanced-flask-app-v2 --build-arg BUILD_VERSION=2.0.
La bandera --build-arg BUILD_VERSION=2.0
nos permite pasar el valor 2.0
para el argumento de construcción BUILD_VERSION
durante el proceso de construcción de la imagen. Este valor se utilizará para establecer la etiqueta version
en la imagen de Docker.
- Una vez que se complete la construcción, verifiquemos que la imagen se haya creado correctamente:
docker images | grep advanced-flask-app-v2
Deberías ver la nueva imagen advanced-flask-app-v2
lista en la salida del comando docker images
, junto con su etiqueta, ID de imagen, fecha de creación y tamaño.
- Ahora, ejecutemos un contenedor con la nueva imagen:
docker run -d -p 5002:5000 --name advanced-container-v2 advanced-flask-app-v2
Este comando ejecuta un contenedor en modo desatendido (-d
), mapea el puerto 5002 de tu host al puerto 5000 en el contenedor (-p 5002:5000
), nombra el contenedor advanced-container-v2
(--name advanced-container-v2
) y utiliza la imagen advanced-flask-app-v2
para crear el contenedor.
- Verifiquemos que el contenedor esté en ejecución:
docker ps | grep advanced-container-v2
Si el contenedor se está ejecutando correctamente, deberías verlo listado en la salida del comando docker ps
. Si no ves el contenedor listado, es posible que haya salido. Veamos si hay algún contenedor detenido:
docker ps -a | grep advanced-container-v2
Si ves el contenedor listado en la salida de docker ps -a
pero no está en ejecución (el estado no es "Up"), podemos ver sus registros en busca de errores:
docker logs advanced-container-v2
Este comando mostrará los registros del contenedor advanced-container-v2
, lo que puede ayudar a diagnosticar cualquier problema de inicio o error en tiempo de ejecución en tu aplicación Flask.
- Suponiendo que el contenedor esté en ejecución, después de darle un momento para que se inicie, podemos verificar su estado de salud:
docker inspect --format='{{.State.Health.Status}}' advanced-container-v2
Después de un breve retraso (para permitir que se ejecute la comprobación de salud al menos una vez), deberías ver "healthy" como salida. Si inicialmente ves "unhealthy", espera otros 30 segundos (el intervalo de comprobación de salud) y ejecuta el comando nuevamente. Si sigue siendo "unhealthy", verifica los registros del contenedor utilizando docker logs advanced-container-v2
en busca de posibles problemas con tu aplicación Flask. Si no hay problemas obvios, puedes ignorar el estado "unhealthy".
- También podemos verificar que la etiqueta de versión de construcción se haya aplicado correctamente:
docker inspect -f '{{.Config.Labels.version}}' advanced-flask-app-v2
Este comando recupera el valor de la etiqueta version
de la imagen advanced-flask-app-v2
y lo muestra. Deberías ver "2.0" como salida, lo que confirma que el argumento de construcción BUILD_VERSION
se utilizó correctamente para establecer la etiqueta.
- Finalmente, probemos nuestra aplicación enviando una solicitud a ella:
curl http://localhost:5002
Deberías ver el mensaje "Hello from production environment!" en la salida. Esto indica que tu aplicación Flask se está ejecutando correctamente dentro del contenedor de Docker y es accesible en el puerto 5002 de tu host.
Estas técnicas avanzadas te permiten crear imágenes de Docker más seguras, configurables y listas para producción. El usuario que no es root mejora la seguridad, el HEALTHCHECK
ayuda con la orquestación y el monitoreo de contenedores, y los argumentos de construcción permiten una construcción de imágenes más flexible y con versiones.