Guía completa para desplegar Nginx con Docker: montaje de configuración, HTTPS y proxy inverso

Por séptima vez pulsas docker restart nginx, refrescas el navegador y sigue apareciendo el error 502. Cambiaste nginx.conf, pero la configuración del contenedor no se aplica.
Los problemas de configuración al desplegar Nginx con Docker los ha pisado casi todo el mundo que trabaja con contenedores. Montaje de archivos de configuración, certificados HTTPS, comunicación entre contenedores: operaciones que parecen simples, pero esconden trampas en los detalles. Este artículo cubre desde la forma correcta de montar la configuración hasta la renovación automática de certificados HTTPS y la configuración de red del proxy inverso, con un esquema de despliegue completo y usable.
Aprenderás:
- Por qué la configuración no se aplica tras editarla y 5 formas correctas de montarla
- La ruta completa de configuración HTTPS, desde certificados autofirmados hasta Let’s Encrypt
- Trucos de configuración de red al hacer proxy inverso a otros contenedores Docker
- Endurecimiento de seguridad y ajuste de rendimiento en producción
Configuración básica de Docker Nginx y montaje de archivos
¿Por qué montar la configuración?
Quizá te preguntes: ¿no basta empaquetar la configuración de Nginx en la imagen? Sí, pero…
Cada cambio de configuración implica reconstruir la imagen, subirla al registro, volver a descargarla y reiniciar el contenedor. El proceso completo puede llevar más de diez minutos. Y ni hablemos de gestión de versiones de configuración o cambio entre entornos. Si a las dos de la madrugada hay un incidente en producción y quieres revertir la configuración rápido, ¿esperar a que termine el build? Mejor no pensarlo.
Montar la configuración resuelve ese dolor: modificas el archivo en el host y el contenedor lo refleja al instante. Pruebas, rollback y trabajo en equipo resultan mucho más sencillos.
Estructura de directorios clave del contenedor Nginx
Primero, ubica dónde vive todo dentro del contenedor:
/etc/nginx/
├── nginx.conf # Configuración principal
├── conf.d/ # Directorio de subconfiguraciones, un sitio por archivo
│ └── default.conf # Configuración del sitio por defecto
/usr/share/nginx/html # Raíz de archivos estáticos
/var/log/nginx/ # Directorio de logs
├── access.log
└── error.log
Punto clave: en nginx.conf hay una línea include /etc/nginx/conf.d/*.conf;. Eso significa que la configuración principal carga automáticamente todos los .conf de conf.d. Si solo montas nginx.conf y olvidas conf.d, acabas de encontrar la primera trampa.
Montaje correcto: paso a paso
No arranques el contenedor todavía. Un poco de preparación te ahorrará muchos dolores de cabeza.
Paso 1: copiar la configuración por defecto del contenedor como plantilla
¿Por qué? La configuración oficial por defecto está probada; partir de ella es más fiable que escribir desde cero.
# Arranca un contenedor temporal
docker run --name nginx-temp -d nginx
# Copia la configuración por defecto
docker cp nginx-temp:/etc/nginx/nginx.conf ./nginx/nginx.conf
docker cp nginx-temp:/etc/nginx/conf.d ./nginx/conf.d
# Elimínalo cuando termines
docker stop nginx-temp && docker rm nginx-temp
Paso 2: crear la estructura de directorios estándar en el host
Mi costumbre es guardar todo lo relacionado con Docker bajo /opt; puedes ajustarlo a tu gusto:
mkdir -p /opt/nginx/{conf,conf.d,html,logs,ssl}
Esta estructura cubre configuración, archivos estáticos, logs y certificados SSL de un solo golpe.
Paso 3: arrancar el contenedor y montar todos los directorios
Aquí está lo importante. Fíjate en cada mapeo de rutas tras el parámetro -v:
docker run -d --name my-nginx \
-p 80:80 -p 443:443 \
-v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /opt/nginx/conf.d:/etc/nginx/conf.d \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/logs:/var/log/nginx \
-v /opt/nginx/ssl:/etc/nginx/ssl \
nginx
Puntos clave:
-p 80:80 -p 443:443: expone HTTP y HTTPS (lo necesitarás para HTTPS más adelante)- Tras
nginx.confva:ro(montaje de solo lectura), para evitar que procesos dentro del contenedor modifiquen la configuración conf.dse monta como directorio completo, no como archivo suelto (esto es crucial; verás por qué abajo)
Cuatro trampas que quizá te esperan
Trampa 1: editar con vim y que el contenedor no se sincronice
Fue la primera que me pilló. Editaba nginx.conf en el host, reiniciaba el contenedor y no pasaba nada.
Causa: vim puede cambiar el inode del archivo al editar. Docker monta por inode; si el inode cambia, el contenedor sigue viendo el archivo antiguo.
Dos soluciones:
- Opción A: usar nano (no cambia el inode)
- Opción B: montar el directorio completo en lugar de un solo archivo
Yo uso siempre la opción B. Con montaje de directorio, da igual cómo cambie el inode; además puedes añadir o quitar archivos de configuración con flexibilidad.
Trampa 2: ruta incorrecta en include
Entra al contenedor y revisa tu nginx.conf:
docker exec -it my-nginx bash
cat /etc/nginx/nginx.conf | grep include
Asegúrate de que exista esta línea:
include /etc/nginx/conf.d/*.conf;
Si la cambias a /opt/nginx/conf.d/*.conf (ruta del host), está mal. Dentro del contenedor solo valen rutas del contenedor.
Trampa 3: olvidar montar conf.d
Montar solo nginx.conf no basta. Si añades un sitio nuevo en conf.d del host, el contenedor no lo verá.
Compruébalo así:
docker exec my-nginx ls /etc/nginx/conf.d
Deberías ver todos los archivos de /opt/nginx/conf.d en el host.
Trampa 4: permisos que impiden a Nginx leer la configuración
En Linux pasa a menudo. Permisos demasiado restrictivos y el proceso Nginx (usuario nginx) no puede leer.
Solución:
chmod 644 /opt/nginx/conf/nginx.conf
chmod 644 /opt/nginx/conf.d/*.conf
Tras cambiar la configuración, acostúmbrate a probar la sintaxis:
docker exec my-nginx nginx -t
Si ves syntax is ok, puedes respirar tranquilo.
Montaje de archivo único vs directorio: ¿cuál elegir?
Es una pregunta frecuente. Mi recomendación:
nginx.conf principal: puede ir montado como archivo único + solo lectura (:ro), porque casi no cambia
Directorio conf.d: hay que montarlo como directorio, para añadir sitios con flexibilidad
html, logs: montaje de directorio, sin más
Regla general: si gestionas varios archivos con flexibilidad, monta el directorio; si quieres control de versiones sobre un archivo central, montaje de archivo único con protección de solo lectura.
Configuración HTTPS y renovación automática con Let’s Encrypt
Certificado autofirmado: validación rápida en desarrollo
En producción hace falta un certificado válido, pero en desarrollo y pruebas un autofirmado basta. Unos comandos y listo:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /opt/nginx/ssl/nginx.key \
-out /opt/nginx/ssl/nginx.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Dev/CN=localhost"
Genera dos archivos:
nginx.key: clave privada, no la compartasnginx.crt: certificado
Luego crea ssl.conf en /opt/nginx/conf.d/:
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
Puntos clave:
- Las rutas de
ssl_certificateson del contenedor (/etc/nginx/ssl), no del host (/opt/nginx/ssl) ssl_protocolssolo TLS 1.2 y 1.3; protocolos antiguos tienen vulnerabilidades- Al arrancar el contenedor no olvides
-p 443:443, o HTTPS no estará expuesto
Recarga en caliente:
docker exec my-nginx nginx -s reload
Visita https://localhost; el navegador avisará de que el certificado no es de confianza. Es normal en autofirmados: continúa y ya.
Let’s Encrypt: certificados gratuitos en producción
Let’s Encrypt es una maravilla: gratis, automatizable y confiable globalmente. El único “pero” es que caduca a los 90 días, pero con renovación automática no es problema.
Recomiendo docker-compose + contenedor certbot; es más fiable que hacerlo a mano.
Primero el docker-compose.yml completo:
version: '3'
services:
nginx:
image: nginx:latest
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/html:/usr/share/nginx/html
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
networks:
- web
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
- web
networks:
web:
driver: bridge
Puntos clave:
1. Montaje compartido de certificados y archivos de validación
./certbot/confmontado en ambos contenedores: certbot genera, nginx lee./certbot/wwwpara la validación HTTP de Let’s Encrypt (método webroot)
2. Nginx hace reload cada 6 horas
La línea parece compleja, pero solo lanza un bucle en segundo plano que recarga la configuración cada 6 horas para que los certificados renovados surtan efecto al instante.
3. Certbot comprueba la renovación cada 12 horas
Let’s Encrypt recomienda comprobar una vez al día; aquí 12 horas da más margen.
Pasos para solicitar el certificado por primera vez
En /opt/nginx/conf.d/ crea primero una configuración temporal temp.conf para la validación HTTP:
server {
listen 80;
server_name your-domain.com; # Cambia por tu dominio
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
Arranca los servicios:
docker-compose up -d
Solicita el certificado (sustituye your-domain.com y [email protected]):
docker-compose run --rm certbot certonly --webroot \
-w /var/www/certbot \
-d your-domain.com \
--email [email protected] \
--agree-tos \
--no-eff-email
Si todo va bien verás “Congratulations!”. Los certificados estarán en ./certbot/conf/live/your-domain.com/.
Ya puedes crear la configuración HTTPS definitiva. Modifica temp.conf a:
server {
listen 80;
server_name your-domain.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Optimización SSL
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# HSTS (forzar HTTPS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
Recarga la configuración:
docker-compose exec nginx nginx -s reload
Verificar la renovación automática
Los certificados de Let’s Encrypt duran 90 días, pero certbot renueva automáticamente cuando quedan 30. Puedes probarlo manualmente:
docker-compose run --rm certbot renew --dry-run
Si ves “The dry run was successful”, está bien.
También puedes revisar los logs de certbot:
docker-compose logs certbot
Extras de seguridad en HTTPS
Si quieres endurecer más la configuración SSL, añade esto:
# OCSP Stapling (comprobación en línea del estado del certificado)
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/your-domain.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Prohibir iframe (anti clickjacking)
add_header X-Frame-Options DENY;
# Anti XSS
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
Después prueba tu SSL en SSL Labs. Conseguir A+ no es difícil.
Proxy inverso y comunicación entre contenedores Docker
Lo que hay que saber de la red de contenedores
Al usar Nginx como proxy de otros contenedores Docker, lo que más duele suele ser la red. Quizá probaste la IP del contenedor directamente y, tras un reinicio, cambió y toca reconfigurar.
Docker tiene varios modos de red; los más usados son:
- bridge: modo por defecto; los contenedores se hablan por un puente virtual
- host: el contenedor usa la pila de red del host; mejor rendimiento, peor aislamiento
Para proxy inverso con Nginx, recomiendo encarecidamente una red bridge personalizada. ¿Por qué?
- Los contenedores se hablan por nombre de servicio, sin depender de IPs que cambian
- Aislamiento: los contenedores de un proyecto forman un entorno de red propio
- Resolución DNS automática con el service discovery integrado de Docker
Crear una red personalizada y ejecutar contenedores
Primero crea la red:
docker network create my-app-network
Arranca tu backend (supongamos una API Node.js):
docker run -d \
--name backend-api \
--network my-app-network \
-e NODE_ENV=production \
my-backend:latest
Arranca Nginx en la misma red:
docker run -d \
--name my-nginx \
--network my-app-network \
-p 80:80 -p 443:443 \
-v /opt/nginx/conf.d:/etc/nginx/conf.d \
nginx
Clave: en la misma red, en la configuración de Nginx puedes usar directamente el nombre backend-api para llegar al backend.
Configuración práctica de proxy inverso en Nginx
Crea api-proxy.conf en /opt/nginx/conf.d/:
upstream backend {
server backend-api:3000; # nombre-contenedor:puerto
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
# Proxy de la API
location /api/ {
proxy_pass http://backend/;
# Pasar información real del cliente
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;
# Soporte WebSocket (si hace falta)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Archivos estáticos servidos directamente por Nginx
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
Detalles fáciles de pasar por alto:
1. upstream y el manejo de rutas en proxy_pass
Fíjate en la barra final de proxy_pass http://backend/;. Con ella, /api/users se reenvía como http://backend/users (sin el prefijo /api).
Si escribes proxy_pass http://backend; (sin barra), se reenvía como http://backend/api/users (ruta completa).
2. Importancia del header X-Forwarded-For
Si el backend necesita la IP real del cliente, depende de este header. Sin él, solo verá la IP del contenedor Nginx.
3. Pool keepalive
keepalive 32 en upstream reutiliza conexiones TCP y reduce el coste del handshake. Muy útil con alta concurrencia.
Simplificar varios contenedores con docker-compose
Crear la red y arrancar contenedor a contenedor cansa. Con docker-compose, de un golpe:
version: '3.8'
services:
backend:
image: my-backend:latest
container_name: backend-api
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://db:5432/mydb
networks:
- app-network
depends_on:
- db
nginx:
image: nginx:latest
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/html:/usr/share/nginx/html
- ./nginx/logs:/var/log/nginx
networks:
- app-network
depends_on:
- backend
db:
image: postgres:14
container_name: postgres-db
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
db-data:
Un comando levanta todo el stack:
docker-compose up -d
Docker automáticamente:
- Crea la red
app-network - Arranca contenedores según
depends_on - Configura resolución DNS entre contenedores
En la configuración de Nginx puedes usar backend y db como hostnames. Muy cómodo.
Rutina de diagnóstico de problemas de proxy
Problema 1: 502 Bad Gateway
El error más común. Causas habituales:
- El backend no está arrancado o se cayó
- Nginx y el backend no están en la misma red
- El backend escucha en un puerto distinto
Pasos de diagnóstico:
# Comprobar si el backend corre
docker ps | grep backend
# Revisar la red
docker network inspect my-app-network
# Entrar al contenedor Nginx y probar conectividad
docker exec -it my-nginx sh
ping backend-api
curl http://backend-api:3000/health
Si ping falla, hay un problema de red. Si curl hace timeout, el backend no escucha bien.
Problema 2: timeout de peticiones
El timeout por defecto de proxy es 60 segundos. Si tu API tarda más (subida grande, cálculo pesado), sube los timeouts:
location /api/long-running/ {
proxy_pass http://backend/;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
Problema 3: cuerpo de POST perdido
A veces un POST llega al backend como GET o sin cuerpo. Revisa:
location /api/ {
proxy_pass http://backend/;
proxy_request_buffering off; # Desactivar buffering de petición
client_max_body_size 100M; # Permitir subidas grandes
}
Balanceo de carga con varios backends
Si tienes varias instancias del backend, Nginx puede repartir la carga:
upstream backend_cluster {
least_conn; # Algoritmo de menor número de conexiones
server backend-1:3000 weight=3; # Peso 3
server backend-2:3000 weight=1; # Peso 1
server backend-3:3000 backup; # Servidor de respaldo
keepalive 32;
}
server {
listen 80;
location /api/ {
proxy_pass http://backend_cluster/;
# ... resto de ajustes proxy
}
}
Algoritmos de balanceo:
round-robin(por defecto): reparto circularleast_conn: prioriza el nodo con menos conexionesip_hash: la misma IP de cliente va siempre al mismo servidor
Si un backend cae, Nginx desvía el tráfico a los nodos sanos.
Mejores prácticas y optimización de rendimiento en producción
Gestión de configuración: no subas a producción a lo bruto
Dejar la configuración suelta en el servidor es cosa de desarrollo. En producción conviene más orden.
Gestionar la configuración con Git
Yo uso un repositorio aparte para toda la configuración de Nginx, con carpetas por entorno. Ventajas claras:
- Historial de versiones visible; rollback con
git checkout - Colaboración en equipo con PR review de cambios
- Integración CI/CD para despliegue automatizado
Plantillas de configuración
La configuración de distintos entornos se parece mucho. Plantillas + sustitución de variables ahorran trabajo. En el despliegue, envsubst basta.
Gestión de logs: no esperes a que el disco se llene
Nginx escribe logs rápido; en sitios con mucho tráfico varios GB al día no es raro. Sin control, un disco lleno tumba el contenedor.
Rotación de logs
Configura logrotate en el host: rotación diaria, retención 14 días, compresión de logs antiguos. Tras rotar hay que pedir a Nginx que reabra los archivos (nginx -s reopen), o seguirá escribiendo en el archivo viejo.
Logs centralizados
Con varios servidores, envía logs a una plataforma central (ELK, Loki, servicios cloud). Drivers de logs de Docker o Promtail lo simplifican.
Recarga elegante: que el usuario no lo note
Tras cambiar la configuración, no hagas docker restart a la ligera. Reiniciar corta todas las conexiones y pierdes peticiones en curso.
La forma correcta:
# Probar sintaxis primero
docker exec my-nginx nginx -t
# Si está bien, reload
docker exec my-nginx nginx -s reload
reload es recarga elegante: nuevos workers cargan la configuración nueva, los viejos terminan las peticiones actuales y salen. Transición sin cortes visibles para el usuario.
Lista de endurecimiento de seguridad
Antes de producción, revisa estos puntos:
1. Ocultar la versión de Nginx
Por defecto las páginas de error muestran la versión. Un atacante puede explotar vulnerabilidades conocidas. En el bloque http añade server_tokens off;.
2. Limitación de tasa anti DDoS
Protección simple y efectiva:
http {
# Limitar frecuencia de peticiones por IP
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# Limitar conexiones concurrentes
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_conn conn_limit 10;
proxy_pass http://backend/;
}
}
3. Montaje de configuración en solo lectura
Añade :ro a la configuración principal para evitar cambios accidentales dentro del contenedor.
4. Principio de mínimo privilegio
Asegúrate de que nginx.conf tenga user nginx;. No lo cambies a root; el riesgo es enorme.
Ajuste de rendimiento: exprimir Nginx
Optimización de procesos worker
worker_processes auto; # Ajuste automático al número de núcleos CPU
worker_cpu_affinity auto; # Afinidad de CPU
auto es cómodo: Nginx detecta los núcleos solo.
Optimización de conexiones
events {
worker_connections 2048; # Máximo de conexiones por worker
use epoll; # En Linux epoll rinde mejor
}
Concurrencia teórica máxima: worker_processes * worker_connections. En la práctica también cuenta el límite de descriptores (ulimit -n).
Compresión gzip
Comprimir texto puede reducir el tráfico un 60-80 %:
http {
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6; # Nivel 1-9; 6 equilibra rendimiento y ratio
gzip_types
text/plain
text/css
text/xml
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
gzip_min_length 1000; # Archivos menores de 1 KB no compensa comprimir
}
Caché de recursos estáticos
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d; # Caché del navegador 30 días
add_header Cache-Control "public, immutable";
}
Soporte HTTP/2
HTTP/2 mejora mucho el rendimiento; activarlo es sencillo:
server {
listen 443 ssl http2; # Añade http2
# ... resto de configuración
}
Requisito: HTTPS; HTTP/2 va sobre TLS.
Monitorización y health checks
No olvides la monitorización. Prometheus + Grafana con nginx-prometheus-exporter exportando métricas funciona bien. Activa stub_status en Nginx, limita el acceso a la red interna de Docker, deja que Prometheus scrapee y Grafana muestre el panel.
Conclusión
En resumen, cuatro pilares:
Montaje de configuración: directorios mejor que archivos sueltos, configuración principal en solo lectura, no olvides conf.d y ssl. Evita la trampa del inode con vim.
HTTPS: autofirmado en desarrollo para validar rápido; Let’s Encrypt + Certbot automatizado en producción. docker-compose simplifica la renovación.
Proxy inverso: red bridge personalizada y comunicación por nombre de contenedor. upstream con keepalive mejora rendimiento y fiabilidad.
Práctica en producción: versiona la configuración con Git, rota logs, reload elegante en lugar de restart, y no te saltes las medidas de seguridad.
Docker Nginx parece simple, pero los detalles importan. Si lo dominas, montarás una arquitectura web estable de desarrollo a producción.
Si este artículo te evitó alguna trampa o resolvió un problema antiguo, ya valió la pena. Pruébalo; si te atascas, comenta y lo vemos.
Un último consejo: guarda las plantillas de configuración de este artículo y reutilízalas. No reinventes la rueda; el tiempo que ahorres lo puedes invertir en otras cosas.
Flujo completo para desplegar Nginx con Docker
Montaje de configuración, HTTPS y proxy inverso en la práctica, solucionando problemas habituales como configuración que no se aplica y comunicación entre contenedores
⏱️ Estimated time: 1 hr
- 1
Step 1: Montaje de configuración: 5 formas correctas
5 formas correctas de montar la configuración:
• Montar el archivo de configuración: -v ./nginx.conf:/etc/nginx/nginx.conf
• Montar el directorio de configuración: -v ./conf.d:/etc/nginx/conf.d
• Usar volúmenes (Volume)
• Configurar con docker-compose
• Usar ConfigMap (entorno K8s)
Problemas habituales:
• La configuración no se aplica tras editarla: cambias nginx.conf y el contenedor sigue con la configuración antigua
• Hay que montar correctamente los archivos con el parámetro -v
• Asegúrate de que el formato del archivo sea correcto
Mejores prácticas:
• Montar directorios es mejor que montar un solo archivo
• Proteger la configuración principal en solo lectura
• No olvides los directorios conf.d y ssl
• Evita la trampa del inode con vim - 2
Step 2: Configuración HTTPS y renovación automática con Let's Encrypt
Configuración HTTPS:
• Usar certificados gratuitos de Let's Encrypt
• Configurar renovación automática: certbot renew
• Montar el directorio de certificados: -v ./certs:/etc/nginx/certs
• Configurar las rutas de los certificados SSL
• Soportar HTTP/2 y TLS 1.3
Configuración de Let's Encrypt:
• Obtener certificados con certbot: certbot certonly --standalone
• Probar renovación automática: certbot renew --dry-run
• Montar certificados en el contenedor: -v ./letsencrypt:/etc/letsencrypt
• Configurar nginx.conf para usar los certificados - 3
Step 3: Proxy inverso y mejores prácticas para producción
Configuración de proxy inverso:
• Configurar upstream apuntando al contenedor backend
• Usar nombre de contenedor o servicio: proxy_pass http://backend:8080
• Configurar health checks
• Gestionar problemas de CORS
• Configurar balanceo de carga
Mejores prácticas para producción:
• Gestionar múltiples contenedores con docker-compose
• Configurar health checks
• Establecer límites de recursos
• Configurar rotación de logs
• Gestionar la configuración con variables de entorno
• Actualizar imágenes con regularidad
Docker Nginx parece sencillo, pero tiene muchos detalles. Si dominas todo esto, podrás montar una arquitectura web estable y fiable de desarrollo a producción.
FAQ
¿Por qué la configuración de Docker Nginx no se aplica tras editarla?
5 formas correctas de montar la configuración:
1) Montar el archivo: -v ./nginx.conf:/etc/nginx/nginx.conf
2) Montar el directorio: -v ./conf.d:/etc/nginx/conf.d
3) Usar volúmenes (Volume)
4) Configurar con docker-compose
5) Usar ConfigMap (entorno K8s)
Mejores prácticas:
• Montar directorios es mejor que montar un solo archivo
• Proteger la configuración principal en solo lectura
• No olvides los directorios conf.d y ssl
• Evita la trampa del inode con vim
¿Cómo configurar HTTPS en Docker Nginx?
• Usar certificados gratuitos de Let's Encrypt
• Configurar renovación automática: certbot renew
• Montar el directorio de certificados: -v ./certs:/etc/nginx/certs
• Configurar las rutas de los certificados SSL
• Soportar HTTP/2 y TLS 1.3
Configuración de Let's Encrypt:
• Obtener certificados con certbot: certbot certonly --standalone
• Probar renovación automática: certbot renew --dry-run
• Montar certificados en el contenedor: -v ./letsencrypt:/etc/letsencrypt
• Configurar nginx.conf para usar los certificados
¿Cómo configurar el proxy inverso en Docker Nginx?
• Configurar upstream apuntando al contenedor backend
• Usar nombre de contenedor o servicio: proxy_pass http://backend:8080
• Configurar health checks
• Gestionar problemas de CORS
• Configurar balanceo de carga
Comunicación entre contenedores:
• Crear una red personalizada con docker-compose
• Asegurarse de que los contenedores estén en la misma red
• Acceder con el nombre del servicio o del contenedor
• Configurar upstream apuntando al servicio backend
¿Cuáles son las mejores prácticas de Docker Nginx en producción?
• Gestionar múltiples contenedores con docker-compose
• Configurar health checks
• Establecer límites de recursos
• Configurar rotación de logs
• Gestionar la configuración con variables de entorno
• Actualizar imágenes con regularidad
Docker Nginx parece sencillo, pero tiene muchos detalles. Si dominas todo esto, podrás montar una arquitectura web estable y fiable de desarrollo a producción.
Consejo: guarda las plantillas de configuración de este artículo y reutilízalas la próxima vez, sin reinventar la rueda.
15 min de lectura · Publicado el: 18 dic 2025 · Actualizado el: 21 ago 2026
Guía práctica de Docker
Si llegaste desde búsqueda, lo más rápido es ir al artículo anterior o siguiente de esta misma serie.
Anterior
Guía completa de despliegue de MySQL con Docker: persistencia de datos y replicación maestro-esclavo
Desde la persistencia de datos en Docker MySQL hasta la configuración de replicación maestro-esclavo: soluciona pérdida de datos al reiniciar contenedores, montaje de archivos de configuración, fallos de conexión y más, con un plan de despliegue listo para producción.
Parte 27 de 38
Siguiente
Escaneo y corrección de seguridad de imágenes Docker: tutorial práctico con Trivy e integración CI/CD
El 76% de las imágenes en Docker Hub tienen vulnerabilidades de seguridad. Esta guía explica el uso práctico de Trivy, métodos sistemáticos de corrección y la integración automatizada en CI/CD, con ejemplos de comandos completos para construir aplicaciones contenedorizadas seguras.
Parte 29 de 38



Comentarios
Inicia sesión con GitHub para dejar un comentario