Comprensión de las Instrucciones y Capas de Dockerfile
Comencemos creando un Dockerfile que utilice varias instrucciones. Construiremos una imagen para una aplicación web Python usando Flask y, en el proceso, exploraremos cómo cada instrucción contribuye a las capas de nuestra imagen de Docker.
- Primero, vamos a crear un nuevo directorio para nuestro proyecto. En la terminal del WebIDE, ejecuta:
mkdir -p ~/project/advanced-dockerfile && cd ~/project/advanced-dockerfile
Este comando crea una nueva carpeta llamada advanced-dockerfile dentro de la carpeta project y luego se sitúa dentro de ella.
-
Ahora, creemos nuestro archivo de aplicación. En el explorador de archivos del WebIDE (normalmente a la izquierda), haz clic derecho en la carpeta advanced-dockerfile y selecciona "New File". Nombra este archivo como app.py.
-
Abre app.py y añade el siguiente código Python:
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def hello():
return f"Hello from {os.environ.get('ENVIRONMENT', 'unknown')} environment!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Esta es una aplicación Flask sencilla que responde con un mensaje de saludo, incluyendo el entorno en el que se está ejecutando.
- A continuación, necesitamos crear un archivo
requirements.txt para especificar nuestras dependencias de Python. Crea un nuevo archivo llamado requirements.txt en el mismo directorio y añade el siguiente contenido:
Flask==2.0.1
Werkzeug==2.0.1
Aquí estamos especificando versiones exactas tanto para Flask como para Werkzeug para asegurar la compatibilidad.
- Ahora, vamos a crear nuestro Dockerfile. Crea un nuevo archivo llamado
Dockerfile (con 'D' mayúscula) en el mismo directorio y añade el siguiente contenido:
## Use an official Python runtime as the base image
FROM python:3.9-slim
## Set the working directory in the container
WORKDIR /app
## Set an environment variable
ENV ENVIRONMENT=production
## Copy the requirements file into the container
COPY requirements.txt .
## Install the required packages
RUN pip install --no-cache-dir -r requirements.txt
## Copy the application code into the container
COPY app.py .
## Specify the command to run when the container starts
CMD ["python", "app.py"]
## Expose the port the app runs on
EXPOSE 5000
## Add labels for metadata
LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="1.0"
LABEL description="Flask app demo for advanced Dockerfile techniques"
Ahora, analicemos estas instrucciones y comprendamos cómo contribuyen a las capas de nuestra imagen:
FROM python:3.9-slim: Esta es siempre la primera instrucción. Especifica la imagen base sobre la que construimos. Esto crea la primera capa de nuestra imagen, que incluye el entorno de ejecución de Python.
WORKDIR /app: Establece el directorio de trabajo para las instrucciones posteriores. No crea una capa nueva, pero afecta el comportamiento de las siguientes instrucciones.
ENV ENVIRONMENT=production: Define una variable de entorno. Las variables de entorno no crean capas nuevas, sino que se almacenan en los metadatos de la imagen.
COPY requirements.txt .: Copia el archivo de requisitos desde nuestro host hacia la imagen. Esto crea una nueva capa que contiene solo este archivo.
RUN pip install --no-cache-dir -r requirements.txt: Ejecuta un comando en el contenedor durante el proceso de construcción. Instala nuestras dependencias de Python. Esto crea una nueva capa que contiene todos los paquetes instalados.
COPY app.py .: Copia el código de nuestra aplicación en la imagen, creando otra capa.
CMD ["python", "app.py"]: Especifica el comando que se ejecutará cuando el contenedor se inicie. No crea una capa, sino que define el comando por defecto.
EXPOSE 5000: En realidad, es solo una forma de documentación. Indica a Docker que el contenedor escuchará en este puerto en tiempo de ejecución, pero no publica el puerto realmente. No crea una capa.
LABEL ...: Añaden metadatos a la imagen. Al igual que las instrucciones ENV, no crean capas nuevas, sino que se guardan en los metadatos.
Cada instrucción RUN, COPY y ADD en un Dockerfile crea una nueva capa. Las capas son un concepto fundamental en Docker que permite el almacenamiento y la transferencia eficiente de imágenes. Cuando realizas cambios en tu Dockerfile y vuelves a construir la imagen, Docker reutilizará las capas en caché que no hayan cambiado, acelerando el proceso de construcción.
- Ahora que entendemos qué hace nuestro Dockerfile, construyamos la imagen. En la terminal, ejecuta:
docker build -t advanced-flask-app .
Este comando construye una nueva imagen de Docker con la etiqueta advanced-flask-app. El . al final le indica a Docker que busque el Dockerfile en el directorio actual.
Verás una salida que muestra cada paso del proceso. Observa cómo cada paso corresponde a una instrucción en nuestro Dockerfile y cómo Docker menciona "Using cache" para los pasos que no han cambiado si ejecutas el comando de construcción varias veces.
- Una vez finalizada la construcción, podemos ejecutar un contenedor basado en nuestra nueva imagen:
docker run -d -p 5000:5000 --name flask-container advanced-flask-app
Este comando hace lo siguiente:
-d ejecuta el contenedor en modo desatendido (en segundo plano).
-p 5000:5000 mapea el puerto 5000 de tu host al puerto 5000 del contenedor.
--name flask-container asigna un nombre a nuestro nuevo contenedor.
advanced-flask-app es la imagen que usamos para crear el contenedor.
Puedes verificar que el contenedor está funcionando consultando la lista de contenedores activos:
docker ps
- Para probar si nuestra aplicación funciona correctamente, podemos usar el comando
curl:
curl http://localhost:5000
Deberías ver el mensaje "Hello from production environment!"
Si tienes problemas con curl, también puedes abrir una nueva pestaña en el navegador y visitar http://localhost:5000. Deberías ver el mismo mensaje.
Si encuentras algún problema, puedes revisar los registros (logs) del contenedor usando:
docker logs flask-container
Esto te mostrará cualquier mensaje de error o salida de tu aplicación Flask.