Índice:
- Sección A. Estructurar un proyecto: apartado I, apartado II, apartado III, apartado IV, apartado V, apartado VI, apartado VII, apartado VIII.
En este apartado crearemos lo necesario para trabajar con la virtualización de entornos.
Crear una nueva rama
Empezamos con la creación de la rama release/000-virtualization
:
git checkout -b 'release/000-virtualization'
Ahora actualizamos el archivo .gitignore
añadiendo:
.env.production
Docker
Empezaremos añadiendo el archivo .dockerignore
:
_temp_/
.git
.gitignore
.env*
.vscode/
.venv/
.pytest*
tests/
Dockerfile
compose.yml
compose.override.yml
Ahora prepararemos los entornos para Linux y Windows por separado.
Docker en el entorno Linux
Creamos el archivo Dockerfile:
# Dockerfile
FROM python:3.12-slim AS base
# Configuración de entorno
ARG APP_PATH=/opt/la_fragua
ENV APP_PATH=${APP_PATH}
ARG APP_ENV=production
ENV APP_ENV=${APP_ENV}
ARG APP_PORT=8080
ENV APP_PORT=${APP_PORT}
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
POETRY_VIRTUALENVS_CREATE=false \
PATH="/root/.local/bin:$PATH" \
DISPLAY=:99 \
QT_QPA_PLATFORM=offscreen
# Crear directorio de la aplicación
WORKDIR ${APP_PATH}
# Instalar dependencias del sistema necesarias para nicegui (qt, chrome, etc.)
RUN apt-get update && apt-get install -y \
git curl build-essential \
libglib2.0-0 libnss3 libx11-6 libxcomposite1 \
libxdamage1 libxrandr2 libxkbcommon0 libxshmfence1 \
libasound2 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
libdrm2 libxext6 libgbm1 libxfixes3 libxrender1 \
xvfb x11vnc fluxbox wmctrl \
&& rm -rf /var/lib/apt/lists/*
# ---- desarrollo ----
FROM base AS dev
COPY requirements.txt .
COPY requirements-dev.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt -r requirements-dev.txt
CMD ["python3", "-m", "app.main"]
# ---- producción ----
FROM base AS production
COPY requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt
COPY . ${APP_FOLDER}
EXPOSE ${APP_PORT}
RUN echo '#!/bin/bash\nXvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &\npython3 -m app.main' > /opt/start.sh && \
chmod +x /opt/start.sh
CMD ["/opt/start.sh"]
Una vez que tenemos el archivo Dockerfile
vamos a preparar los archivos 'compose' para automatizar la creación y ejecución de los entornos.
Creamos el archivo compose.yml:
# compose.yml para producción
services:
la_fragua:
image: "${DOCKER_LOGIN}/${APP_NAME}-linux:latest"
build:
context: .
dockerfile: "Dockerfile"
target: production
env_file:
- .env.production
ports:
- "${APP_PORT}:8080"
environment:
- APP_ENV=container
- APP_PATH=/opt/la_fragua
restart: always
Creamos el archivo compose.override.yml:
# compose.override.yml para dev
services:
la_fragua:
image: "${APP_NAME}-linux:dev"
build:
context: .
dockerfile: "Dockerfile"
target: dev
env_file:
- .env
ports:
- "${APP_PORT}:8080"
environment:
- APP_ENV=container
- APP_PATH=/opt/la_fragua
volumes:
- .:/opt/la_fragua
stdin_open: true
tty: true
Docker en el entorno Windows
Añadimos al archivo .dockerignore
el siguiente contenido:
Dockerfile.windows
compose.windows.yml
compose.windows.override.yml
Creamos el archivo Dockerfile.windows:
# Dockerfile.windows
FROM mcr.microsoft.com/windows/servercore:ltsc2022 AS base
# Shell Powershell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
# Instalar Python
RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.12.0/python-3.12.0-amd64.exe -OutFile python-installer.exe; \
Start-Process python-installer.exe -Wait -ArgumentList '/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'DefaultAllUsersTargetDir=C:\Python312'; \
Remove-Item python-installer.exe -Force
# Actualizar pip
RUN python -m pip install --upgrade pip --disable-pip-version-check
# Configuración de entorno
ARG APP_PATH="C:/la_fragua"
ENV APP_PATH=${APP_PATH}
ARG APP_ENV=production
ENV APP_ENV=${APP_ENV}
ARG APP_PORT=8080
ENV APP_PORT=${APP_PORT}
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_VIRTUALIZATION=container \
QT_QPA_PLATFORM=minimal
# Crear directorio de la aplicación
WORKDIR ${APP_PATH}
# ---------- Dev stage ----------
FROM base AS dev
COPY requirements.txt .
COPY requirements-dev.txt .
RUN pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt
CMD ["python", "-m", "app.main"]
# ---------- Production stage ----------
FROM base AS production
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . ${APP_FOLDER}
EXPOSE ${APP_PORT}
CMD ["python", "-m", "app.main"]
Creamos el archivo compose.windows.yml
# compose.windows.yml para producción
services:
la_fragua:
image: "${DOCKER_LOGIN}/${APP_NAME}-windows:latest"
build:
context: .
dockerfile: "Dockerfile.windows"
target: production
env_file:
- .env.production
ports:
- "${APP_PORT}:8080"
environment:
- APP_ENV=container
- APP_PATH="C:/la_fragua"
restart: always
Creamos el archivo compose.windows.override.yml
# compose.windows.override.yml para dev
services:
la_fragua:
image: "${APP_NAME}-windows:dev"
build:
context: .
dockerfile: "Dockerfile.windows"
target: dev
env_file:
- .env
ports:
- "${APP_PORT}:8080"
environment:
- APP_ENV=container
- APP_PATH="C:/la_fragua"
volumes:
- .:C:/la_fragua
stdin_open: true
tty: true
Ya tenemos preparados los entornos docker de Linux y Windows.
Hemos cometido un par de errores en los Dockerfile para obligarnos a realizar una corrección. En el siguiente artículo trabajaremos sobre ello.
Apuntes
En los archivos Dockerfile
habrás visto que utilizamos FROM python:3.12-slim AS base
al inicio, y posteriormente FROM base AS dev
y FROM base AS production
. Esto, unido al target
de los archivos compose
nos define qué parte del Dockerfile está generándose. Con esta dinámica hemos conseguido no repetir información en innecesariamente. En el siguiente artículo continuamos trabajando sobre los entornos.
En los archivos compose
verás que en producción tenemos la variable DOCKER_LOGIN
pero en desarrollo no lo está. Esto tiene una razón: la imagen docker que se genere para producción querremos poder llevarla al hub
de docker, pero la imagen de desarrollo no debemos llevarla nunca al hub
.
Enlaces
Repositorio del proyecto:
Enlaces de interés:
- Multi-stage builds: https://docs.docker.com/build/building/multi-stage/
- Merge Compose files: https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/
Siguiente artículo:
Top comments (0)