Dockerfile para Django
# Dockerfile
FROM python:3.12-slim AS base
# Variables de entorno
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
# Instalar dependencias del sistema
RUN apt-get update && apt-get install -y \
libpq-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Instalar dependencias Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copiar código fuente
COPY . .
# Crear usuario sin privilegios
RUN addgroup --system django && adduser --system --ingroup django django
RUN chown -R django:django /app
USER django
# Recopilar archivos estáticos en build time
RUN python manage.py collectstatic --noinput
EXPOSE 8000
# Usar gunicorn en producción
CMD ["gunicorn", "mi_proyecto.wsgi:application", \
"--bind", "0.0.0.0:8000", \
"--workers", "3", \
"--timeout", "30"]

docker-compose para desarrollo
# docker-compose.yml
version: '3.9'
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: ${DB_NAME:-mi_app}
POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
web:
build: .
command: >
sh -c "python manage.py migrate &&
python manage.py collectstatic --noinput &&
gunicorn mi_proyecto.wsgi:application --bind 0.0.0.0:8000"
volumes:
- .:/app
- static_volume:/app/staticfiles
- media_volume:/app/media
ports:
- "8000:8000"
env_file:
- .env
environment:
- DJANGO_SETTINGS_MODULE=mi_proyecto.settings.produccion
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- static_volume:/app/staticfiles:ro
- media_volume:/app/media:ro
ports:
- "80:80"
depends_on:
- web
volumes:
postgres_data:
redis_data:
static_volume:
media_volume:
Archivo .env
# .env (NO incluir en el repositorio)
SECRET_KEY=tu_clave_secreta_muy_larga_y_aleatoria
DEBUG=False
ALLOWED_HOSTS=localhost,127.0.0.1,mi-dominio.com
# Base de datos
DB_ENGINE=django.db.backends.postgresql
DB_NAME=mi_app
DB_USER=postgres
DB_PASSWORD=contraseña_segura
DB_HOST=db
DB_PORT=5432
# Redis
REDIS_URL=redis://redis:6379/1
# Email
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=noreply@mi-app.com
EMAIL_HOST_PASSWORD=app_password
Comandos Docker útiles
# Construir y arrancar todos los servicios
docker-compose up --build -d
# Ver logs en tiempo real
docker-compose logs -f web
# Ejecutar comandos en el contenedor
docker-compose exec web python manage.py createsuperuser
docker-compose exec web python manage.py shell
docker-compose exec web python manage.py migrate
# Parar y eliminar contenedores (mantiene volúmenes)
docker-compose down
# Parar y eliminar TODO incluyendo volúmenes (¡elimina la base de datos!)
docker-compose down -v
# Reconstruir solo el servicio web
docker-compose up -d --build web
docker-compose.override.yml para desarrollo
# docker-compose.override.yml (sobreescribe docker-compose.yml en desarrollo)
version: '3.9'
services:
web:
command: python manage.py runserver 0.0.0.0:8000
environment:
- DJANGO_SETTINGS_MODULE=mi_proyecto.settings.desarrollo
- DEBUG=True
volumes:
- .:/app # Recarga automática con cambios
Nginx para Docker
# nginx.conf
upstream django {
server web:8000;
}
server {
listen 80;
client_max_body_size 20M;
location /static/ {
alias /app/staticfiles/;
expires 30d;
}
location /media/ {
alias /app/media/;
expires 7d;
}
location / {
proxy_pass http://django;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Docker garantiza que la aplicación se ejecuta en el mismo entorno en desarrollo y producción, eliminando el problema "en mi máquina funciona" y facilitando los despliegues reproducibles.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Escribir un Dockerfile optimizado para una aplicación Django. Configurar docker-compose con Django, PostgreSQL y Redis. Gestionar variables de entorno y secretos en contenedores. Ejecutar collectstatic y migraciones en el proceso de build y arranque. Configurar volúmenes para persistencia de datos y archivos media.