Contenedores de aplicación con Docker
Introducción
Docker es la plataforma de contenedores de aplicación más extendida. Permite empaquetar una aplicación y todas sus dependencias en una imagen portable que se ejecuta de forma idéntica en cualquier sistema con Docker instalado.
Instalación
Debian/Ubuntu
# Instalar desde el repositorio oficial de Docker
apt install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
> /etc/apt/sources.list.d/docker.list
apt update
apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Añadir el usuario al grupo docker para no necesitar sudo
usermod -aG docker $USER
RHEL / Rocky Linux
dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin
systemctl enable --now docker
Verificar instalación
docker version
docker info
docker run hello-world
Pasos recomendados tras la instalación
1. Ejecutar Docker sin sudo
Por defecto Docker requiere sudo. Para poder usarlo como usuario normal hay que añadirse al grupo docker:
sudo groupadd docker # crear el grupo si no existe
sudo usermod -aG docker $USER # añadir el usuario actual
# Activar sin cerrar sesión:
newgrp docker
# Verificar que funciona sin sudo:
docker run hello-world
El grupo docker da privilegios equivalentes a root sobre el daemon. No añadir usuarios no confiables
a este grupo.
2. Arranque automático con el sistema
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
# Verificar que están habilitados
systemctl is-enabled docker
systemctl is-enabled containerd
3. Configurar el driver de logging
Por defecto Docker usa el driver json-file sin límite de tamaño, lo que puede llenar el disco. Se recomienda
configurar rotación en /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
sudo systemctl reload docker
4. Configurar el almacenamiento de datos
Por defecto Docker almacena imágenes, contenedores y volúmenes en /var/lib/docker. Si el disco
raíz es pequeño, se puede cambiar en /etc/docker/daemon.json:
{
"data-root": "/mnt/disco-grande/docker"
}
sudo systemctl restart docker
docker info | grep "Docker Root Dir"
5. Limpiar recursos sin usar
Docker acumula imágenes, contenedores parados y volúmenes huérfanos. Conviene limpiar periódicamente:
docker system prune # elimina contenedores parados, redes sin uso e imágenes colgantes
docker system prune -a # también elimina imágenes sin contenedores asociados
docker system prune -a --volumes # incluye volúmenes huérfanos (¡cuidado con datos!)
docker system df # ver uso de espacio por Docker
Conceptos clave
- Imagen: plantilla de solo lectura con el sistema de ficheros y metadatos del contenedor
- Contenedor: instancia en ejecución de una imagen (con su capa de escritura)
- Dockerfile: fichero de instrucciones para construir una imagen
- Registry: repositorio de imágenes (Docker Hub, ghcr.io, registry privado)
- Volumen: almacenamiento persistente fuera del ciclo de vida del contenedor
- Red: red virtual que conecta contenedores entre sí o con el host
Comandos básicos
Imágenes
docker images # listar imágenes locales
docker pull nginx:latest # descargar imagen de Docker Hub
docker rmi nginx:latest # eliminar imagen
docker image prune # eliminar imágenes sin usar
docker image inspect nginx # info detallada de una imagen
Contenedores
docker run nginx # crear y arrancar contenedor (primer plano)
docker run -d nginx # en segundo plano (detached)
docker run -d -p 8080:80 nginx # mapear puerto host:contenedor
docker run -d --name mi-nginx nginx # con nombre personalizado
docker run -it ubuntu bash # interactivo con shell
docker ps # contenedores en ejecución
docker ps -a # todos (incluidos parados)
docker stop mi-nginx # parar contenedor
docker start mi-nginx # arrancar contenedor parado
docker restart mi-nginx # reiniciar
docker rm mi-nginx # eliminar contenedor parado
docker rm -f mi-nginx # forzar eliminación
docker container prune # eliminar todos los parados
docker logs mi-nginx # ver logs
docker logs -f mi-nginx # seguir logs en tiempo real
docker exec -it mi-nginx bash # abrir shell en contenedor en ejecución
docker inspect mi-nginx # info detallada del contenedor
docker stats # uso de recursos en tiempo real
Dockerfile
El Dockerfile define cómo se construye una imagen. Ejemplo para una app Node.js:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Instrucciones más usadas:
FROM: imagen baseWORKDIR: directorio de trabajo dentro del contenedorCOPY/ADD: copiar ficheros al contenedorRUN: ejecutar comandos durante la construcciónEXPOSE: documentar el puerto que usa la aplicaciónENV: variables de entornoCMD/ENTRYPOINT: comando al arrancar el contenedor
docker build -t mi-app:1.0 . # construir imagen
docker build -t mi-app:1.0 -f Dockerfile.prod . # Dockerfile alternativo
docker push mi-usuario/mi-app:1.0 # publicar en Docker Hub
Volúmenes y bind mounts
# Volumen gestionado por Docker (persistente entre contenedores)
docker volume create mis-datos
docker run -d -v mis-datos:/var/lib/mysql mysql
docker volume ls
docker volume inspect mis-datos
docker volume rm mis-datos
# Bind mount (directorio del host montado en el contenedor)
docker run -d -v /home/user/datos:/app/datos nginx
# Montar solo lectura
docker run -d -v /etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro nginx
Redes
docker network ls # listar redes
docker network create mi-red # crear red bridge
docker run -d --network mi-red --name app nginx
docker run -d --network mi-red --name db postgres
# Los contenedores en la misma red se resuelven por nombre
docker network inspect mi-red
docker network connect mi-red otro-contenedor
docker network disconnect mi-red contenedor
Docker Compose
Docker Compose permite definir y gestionar aplicaciones multi-contenedor mediante un fichero YAML
(compose.yaml).
# compose.yaml
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secreto
volumes:
- datos-db:/var/lib/postgresql/data
volumes:
datos-db:
docker compose up -d # arrancar en segundo plano
docker compose down # parar y eliminar contenedores
docker compose down -v # también eliminar volúmenes
docker compose logs -f # ver logs de todos los servicios
docker compose ps # estado de los servicios
docker compose exec web sh # shell en el contenedor web