Compartir comentarios
Las respuestas se generan en base a la documentación.

Contenedorizar una aplicación Python

Requisitos previos

  • Has instalado la última versión de Docker Desktop.
  • Tienes un cliente de Git. Los ejemplos de esta sección utilizan un cliente de Git basado en línea de comandos, pero puedes usar cualquier cliente.

Descripción general

Esta sección te guía a través de la contenedorización y ejecución de una aplicación Python.

Obtener la aplicación de ejemplo

La aplicación de ejemplo utiliza el popular framework FastAPI.

Clona la aplicación de ejemplo para usarla con esta guía. Abre una terminal, ve al directorio en el que quieras trabajar y ejecuta el siguiente comando para clonar el repositorio:

$ git clone https://github.com/estebanx64/python-docker-example && cd python-docker-example

Inicializar los recursos de Docker

Ahora que tienes una aplicación, puedes crear los recursos de Docker necesarios para contenedorizarla. Puedes usar la función integrada Docker Init de Docker Desktop para ayudar a simplificar el proceso, o puedes crear los recursos manualmente.

Dentro del directorio python-docker-example, ejecuta el comando docker init. docker init proporciona cierta configuración predeterminada, pero tendrás que responder a algunas preguntas sobre tu aplicación. Por ejemplo, esta aplicación utiliza FastAPI para ejecutarse. Consulta el siguiente ejemplo para responder a las preguntas de docker init y utiliza las mismas respuestas para tus indicaciones.

Antes de editar tu Dockerfile, debes elegir una imagen base. Puedes usar la Imagen Oficial de Docker para Python o una Imagen Reforzada de Docker (DHI).

Las Imágenes Reforzadas de Docker (DHI, por sus siglas en inglés) son imágenes base mínimas, seguras y listas para producción mantenidas por Docker. Ayudan a reducir las vulnerabilidades y simplifican el cumplimiento. Para obtener más detalles, consulta Imágenes Reforzadas de Docker.

$ docker init
Welcome to the Docker Init CLI!

This utility will walk you through creating the following files with sensible defaults for your project:
  - .dockerignore
  - Dockerfile
  - compose.yaml
  - README.Docker.md

Let's get started!

? What application platform does your project use? Python
? What version of Python do you want to use? 3.12
? What port do you want your app to listen on? 8000
? What is the command to run your app? python3 -m uvicorn app:app --host=0.0.0.0 --port=8000

Crea un archivo llamado .gitignore con el siguiente contenido.

.gitignore
# Archivos compilados en bytes / optimizados / DLL
__pycache__/
*.py[cod]
*$py.class

# Extensiones C
*.so

# Distribución / empaquetado
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Informes de pruebas unitarias / cobertura
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# PEP 582; utilizado por ejemplo por github.com/David-OConnor/pyflow y github.com/pdm-project/pdm
__pypackages__/

# Entornos
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

Si no tienes instalado Docker Desktop o prefieres crear los recursos manualmente, puedes crear los siguientes archivos en el directorio de tu proyecto.

Crea un archivo llamado Dockerfile con el siguiente contenido.

Dockerfile
# syntax=docker/dockerfile:1

# Se proporcionan comentarios a lo largo de este archivo para ayudarte a empezar.
# Si necesitas más ayuda, visita la guía de referencia de Dockerfile en
# https://docs-docker.esdocu.com/go/dockerfile-reference/

# ¿Quieres ayudarnos a mejorar esta plantilla? Comparte tus comentarios aquí: https://forms.gle/ybq9Krt8jtBL3iCk7

# Este Dockerfile utiliza la Imagen Oficial de Docker para Python
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-slim

# Evita que Python escriba archivos pyc.
ENV PYTHONDONTWRITEBYTECODE=1

# Evita que Python almacene en búfer stdout y stderr para evitar situaciones en las que
# la aplicación se bloquee sin emitir ningún registro debido al almacenamiento en búfer.
ENV PYTHONUNBUFFERED=1

WORKDIR /app

# Crea un usuario no privilegiado bajo el cual se ejecutará la aplicación.
# Consulta https://docs-docker.esdocu.com/go/dockerfile-user-best-practices/
ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser

# Descarga las dependencias como un paso separado para aprovechar la caché de Docker.
# Aprovecha un montaje de caché en /root/.cache/pip para acelerar las compilaciones posteriores.
# Aprovecha un montaje de tipo bind en requirements.txt para evitar tener que copiarlos
# en esta capa.
RUN --mount=type=cache,target=/root/.cache/pip \
    --mount=type=bind,source=requirements.txt,target=requirements.txt \
    python -m pip install -r requirements.txt

# Cambia al usuario no privilegiado para ejecutar la aplicación.
USER appuser

# Copia el código fuente en el contenedor.
COPY . .

# Expone el puerto en el que escucha la aplicación.
EXPOSE 8000

# Ejecuta la aplicación.
CMD ["python3", "-m", "uvicorn", "app:app", "--host=0.0.0.0", "--port=8000"]

Crea un archivo llamado compose.yaml con el siguiente contenido.

compose.yaml
# Se proporcionan comentarios a lo largo de este archivo para ayudarte a empezar.
# Si necesitas más ayuda, visita la guía de referencia de Docker Compose en
# https://docs-docker.esdocu.com/go/compose-spec-reference/

# Aquí las instrucciones definen tu aplicación como un servicio llamado "server".
# Este servicio se construye a partir del Dockerfile en el directorio actual.
# Puedes agregar otros servicios de los que pueda depender tu aplicación aquí, como una
# base de datos o una caché. Para ver ejemplos, consulta el repositorio Awesome Compose:
# https://github.com/docker/awesome-compose
services:
  server:
    build:
      context: .
    ports:
      - 8000:8000

Crea un archivo llamado .dockerignore with the following contents.

.dockerignore
# Incluye aquí cualquier archivo o directorio que no quieras que se copie a tu
# contenedor (por ejemplo, artefactos de compilación local, archivos temporales, etc.).
#
# Para obtener más ayuda, consulta la guía de referencia del archivo .dockerignore en
# https://docs-docker.esdocu.com/go/build-context-dockerignore/

**/.DS_Store
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

Crea un archivo llamado .gitignore con el siguiente contenido.

.gitignore
# Archivos compilados en bytes / optimizados / DLL
__pycache__/
*.py[cod]
*$py.class

# Extensiones C
*.so

# Distribución / empaquetado
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Informes de pruebas unitarias / cobertura
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# PEP 582; utilizado por ejemplo por github.com/David-OConnor/pyflow y github.com/pdm-project/pdm
__pypackages__/

# Entornos
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

Las Imágenes Reforzadas de Docker (DHI) están disponibles para Python en el catálogo de Imágenes Reforzadas de Docker. Las Imágenes Reforzadas de Docker están disponibles gratuitamente para todos sin necesidad de suscripción. Puedes descargarlas y usarlas como cualquier otra imagen de Docker después de iniciar sesión en el registro de DHI. Para obtener más información, consulta la guía de inicio rápido de DHI.

  1. Inicia sesión en el registro de DHI:

    $ docker login dhi.io
    
  2. Descarga la DHI de Python (consulta el catálogo para ver las versiones disponibles):

    $ docker pull dhi.io/python:3.12.12-debian13-fips-dev
    

Crea un archivo llamado Dockerfile con el siguiente contenido.

Dockerfile
# syntax=docker/dockerfile:1

# Se proporcionan comentarios a lo largo de este archivo para ayudarte a empezar.
# Si necesitas más ayuda, visita la guía de referencia de Dockerfile en
# https://docs-docker.esdocu.com/go/dockerfile-reference/

# ¿Quieres ayudarnos a mejorar esta plantilla? Comparte tus comentarios aquí: https://forms.gle/ybq9Krt8jtBL3iCk7

# Este Dockerfile utiliza Imágenes Reforzadas de Docker (DHI) para una seguridad mejorada.
# Para obtener más información, consulta https://docs-docker.esdocu.com/dhi/
ARG PYTHON_VERSION=3.12.12-debian13-fips-dev
FROM dhi.io/python:${PYTHON_VERSION}

# Evita que Python escriba archivos pyc.
ENV PYTHONDONTWRITEBYTECODE=1

# Evita que Python almacene en búfer stdout y stderr para evitar situaciones en las que
# la aplicación se bloquee sin emitir ningún registro debido al almacenamiento en búfer.
ENV PYTHONUNBUFFERED=1

# Agrega dependencias para adduser
RUN apt update -y && apt install adduser -y

WORKDIR /app

# Crea un usuario no privilegiado bajo el cual se ejecutará la aplicación.
# Consulta https://docs-docker.esdocu.com/go/dockerfile-user-best-practices/
ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser

# Descarga las dependencias como un paso separado para aprovechar la caché de Docker.
# Aprovecha un montaje de caché en /root/.cache/pip para acelerar las compilaciones posteriores.
# Aprovecha un montaje de tipo bind en requirements.txt para evitar tener que copiarlos
# en esta capa.
RUN --mount=type=cache,target=/root/.cache/pip \
    --mount=type=bind,source=requirements.txt,target=requirements.txt \
    python -m pip install -r requirements.txt

# Cambia al usuario no privilegiado para ejecutar la aplicación.
USER appuser

# Copia el código fuente en el contenedor.
COPY . .

# Expone el puerto en el que escucha la aplicación.
EXPOSE 8000

# Ejecuta la aplicación.
CMD ["python3", "-m", "uvicorn", "app:app", "--host=0.0.0.0", "--port=8000"]

Crea un archivo llamado compose.yaml con el siguiente contenido.

compose.yaml
# Se proporcionan comentarios a lo largo de este archivo para ayudarte a empezar.
# Si necesitas más ayuda, visita la guía de referencia de Docker Compose en
# https://docs-docker.esdocu.com/go/compose-spec-reference/

# Aquí las instrucciones definen tu aplicación como un servicio llamado "server".
# Este servicio se construye a partir del Dockerfile en el directorio actual.
# Puedes agregar otros servicios de los que pueda depender tu aplicación aquí, como una
# base de datos o una caché. Para ver ejemplos, consulta el repositorio Awesome Compose:
# https://github.com/docker/awesome-compose
services:
  server:
    build:
      context: .
    ports:
      - 8000:8000

Crea un archivo llamado .dockerignore con el siguiente contenido.

.dockerignore
# Incluye aquí cualquier archivo o directorio que no quieras que se copie a tu
# contenedor (por ejemplo, artefactos de compilación local, archivos temporales, etc.).
#
# Para obtener más ayuda, consulta la guía de referencia del archivo .dockerignore en
# https://docs-docker.esdocu.com/go/build-context-dockerignore/

**/.DS_Store
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

Crea un archivo llamado .gitignore con el siguiente contenido.

.gitignore
# Archivos compilados en bytes / optimizados / DLL
__pycache__/
*.py[cod]
*$py.class

# Extensiones C
*.so

# Distribución / empaquetado
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Informes de pruebas unitarias / cobertura
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# PEP 582; utilizado por ejemplo por github.com/David-OConnor/pyflow y github.com/pdm-project/pdm
__pypackages__/

# Entornos
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

Ahora deberías tener el siguiente contenido en tu directorio python-docker-example.

├── python-docker-example/
│   ├── app.py
│   ├── requirements.txt
│   ├── .dockerignore
│   ├── .gitignore
│   ├── compose.yaml
│   ├── Dockerfile
│   └── README.md

Para obtener más información sobre estos archivos, consulta lo siguiente:

Ejecutar la aplicación

Dentro del directorio python-docker-example, ejecuta el siguiente comando en una terminal.

$ docker compose up --build

Abre un navegador y visualiza la aplicación en http://localhost:8000. Deberías ver una aplicación FastAPI sencilla.

En la terminal, presiona ctrl+c para detener la aplicación.

Ejecutar la aplicación en segundo plano

Puedes ejecutar la aplicación desacoplada de la terminal agregando la opción -d. Dentro del directorio python-docker-example, ejecuta el siguiente comando en una terminal.

$ docker compose up --build -d

Abre un navegador y visualiza la aplicación en http://localhost:8000.

Para ver los documentos de OpenAPI, puedes ir a http://localhost:8000/docs.

Deberías ver una aplicación FastAPI sencilla.

En la terminal, ejecuta el siguiente comando para detener la aplicación.

$ docker compose down

Para obtener más información sobre los comandos de Compose, consulta la referencia de la CLI de Compose.

Resumen

En esta sección, aprendiste cómo puedes contenedorizar y ejecutar tu aplicación Python usando Docker.

Información relacionada:

Pasos siguientes

En la siguiente sección, verás cómo configurar un entorno de desarrollo local utilizando contenedores de Docker.