Los contenedores son efímeros
Todo lo que escribes dentro de un contenedor se guarda en una capa de solo-escritura asociada a ese contenedor concreto. Si lo eliminas, esos datos se pierden. Para aplicaciones reales necesitas que la base de datos, los archivos subidos por usuarios y las configuraciones sobrevivan a ciclos de docker rm. Ahí entran los volúmenes.
Bind mounts vs named volumes
Docker ofrece dos formas principales de persistir datos fuera del contenedor:
- Bind mount: montas una carpeta del host directamente dentro del contenedor. Útil en desarrollo, cuando quieres editar el código y ver los cambios al vuelo.
- Named volume: Docker gestiona una zona de almacenamiento en
/var/lib/docker/volumes/. Recomendado en producción porque es más portable y eficiente.
Ejemplos prácticos
Bind mount de la carpeta de tu proyecto:
docker run -d -p 80:80 \
-v $(pwd)/html:/usr/share/nginx/html \
--name web nginx
Named volume para persistir MySQL:
docker volume create mysql_data
docker run -d --name db \
-e MYSQL_ROOT_PASSWORD=secret \
-v mysql_data:/var/lib/mysql \
mysql:8
Inspeccionar volúmenes:
docker volume ls
docker volume inspect mysql_data
docker volume rm mysql_data # solo si ningún contenedor lo usa
Redes en Docker
Cuando levantas un contenedor con la configuración por defecto, Docker lo conecta a una red bridge llamada bridge. Dentro de esa red los contenedores pueden comunicarse entre sí, pero para tener resolución DNS por nombre necesitas crear una red propia.
Tipos de red
- bridge: red virtual aislada en el host. Es la más común y la que usas para grupos de contenedores que deben hablar entre ellos.
- host: el contenedor usa directamente la pila de red del host, sin aislamiento. Ofrece máximo rendimiento pero pierde portabilidad.
- none: contenedor sin red alguna. Útil para procesos batch que no requieren conectividad.
- overlay: conecta contenedores en diferentes hosts (modo swarm).
Crear una red y conectar servicios
docker network create miapp-net
docker run -d --name db --network miapp-net \
-e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name api --network miapp-net \
-e DB_HOST=db -p 3000:3000 miapp:1.0
Fíjate en el detalle clave: la API se conecta usando DB_HOST=db. Dentro de la red personalizada, Docker resuelve db al contenedor correcto gracias a su DNS interno. No necesitas IPs ni editar /etc/hosts.
Buenas prácticas
- Nunca guardes datos importantes solo dentro del sistema de archivos del contenedor.
- Haz copias de seguridad de tus volúmenes con regularidad (puedes montar el volumen en un contenedor de
tarpara comprimirlo). - Crea una red por stack de aplicación: separa servicios que no deben hablar entre sí.
- Expón al host solo los puertos estrictamente necesarios (por ejemplo, el 80/443 del proxy, no los puertos internos de la base de datos).
Volúmenes y redes son los cimientos invisibles que transforman un experimento con contenedores sueltos en una infraestructura confiable.