8.5 Contenedores con Docker
Los contenedores han cambiado cómo se despliegan los servicios: en lugar de instalar software directamente en el servidor, lo empaquetas junto con todas sus dependencias en una imagen reproducible. Como sysadmin ya no basta con saber gestionar servicios con systemd — necesitas saber gestionar contenedores Docker que corren junto a ellos.
1. Qué es Docker y cómo se relaciona con el kernel
Sección titulada “1. Qué es Docker y cómo se relaciona con el kernel"Docker no es un hipervisor: los contenedores comparten el kernel del host. Docker usa dos características del kernel Linux para aislarlos:
- Namespaces: cada contenedor tiene su propio árbol de procesos, interfaces de red, usuarios y sistema de ficheros.
- Cgroups: limitan la CPU, memoria y I/O que puede usar cada contenedor.
Host Linux (kernel compartido)├── Proceso: nginx (contenedor 1 — namespace propio)├── Proceso: postgres (contenedor 2 — namespace propio)└── Proceso: sshd (servicio del host — sin contenedor)2. Instalación
Sección titulada “2. Instalación"# Método oficial (repositorio Docker)sudo apt updatesudo apt install ca-certificates curlsudo install -m 0755 -d /etc/apt/keyringssudo curl -fsSL https://download.docker.com/linux/debian/gpg \ -o /etc/apt/keyrings/docker.ascecho "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ | sudo tee /etc/apt/sources.list.d/docker.listsudo apt updatesudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Verificar instalaciónsudo docker run hello-world
# Permitir al usuario actual usar Docker sin sudo (requiere cerrar sesión)sudo usermod -aG docker $USER3. Imágenes y contenedores
Sección titulada “3. Imágenes y contenedores"La relación imagen → contenedor es la misma que clase → instancia en programación.
# Buscar imágenes en Docker Hubdocker search nginx
# Descargar una imagendocker pull nginx:latestdocker pull nginx:1.26-alpine # versión específica
# Listar imágenes descargadasdocker images
# Ver información de una imagendocker inspect nginx:latest
# Eliminar una imagendocker rmi nginx:latest4. Ciclo de vida de un contenedor
Sección titulada “4. Ciclo de vida de un contenedor"# Ejecutar un contenedor (descarga la imagen si no está local)docker run nginx
# Modo detached (en segundo plano) con nombre y puerto mapeadodocker run -d --name mi-nginx -p 8080:80 nginx# -d = background# --name = nombre identificativo# -p host:contenedor = mapeo de puertos
# Listar contenedores en ejecucióndocker ps
# Listar todos (incluidos parados)docker ps -a
# Ver logs del contenedordocker logs mi-nginxdocker logs -f mi-nginx # Follow (en tiempo real)
# Ejecutar un comando dentro del contenedordocker exec -it mi-nginx bash# -i = interactivo, -t = terminal
# Detener / iniciar / reiniciardocker stop mi-nginxdocker start mi-nginxdocker restart mi-nginx
# Eliminar un contenedor (debe estar parado)docker rm mi-nginx
# Parar y eliminar en un solo pasodocker rm -f mi-nginx5. Volúmenes — persistencia de datos
Sección titulada “5. Volúmenes — persistencia de datos"Por defecto, los datos dentro de un contenedor se pierden cuando se elimina. Los volúmenes persisten los datos fuera del contenedor.
# Montar un directorio del host dentro del contenedordocker run -d \ --name nginx-web \ -p 80:80 \ -v /var/www/html:/usr/share/nginx/html:ro \ nginx# /var/www/html = ruta en el HOST# /usr/share/nginx/html = ruta en el CONTENEDOR# :ro = solo lectura (opcional)# Crear un volumen nombradodocker volume create datos-postgres
# Usar el volumen en un contenedordocker run -d \ --name postgres-db \ -e POSTGRES_PASSWORD=secreto \ -v datos-postgres:/var/lib/postgresql/data \ postgres:16
# Listar volúmenesdocker volume ls
# Inspeccionar dónde está el volumen en el hostdocker volume inspect datos-postgres
# Eliminar un volumen (debe estar sin uso)docker volume rm datos-postgres6. Redes Docker
Sección titulada “6. Redes Docker"# Ver redes disponiblesdocker network ls# bridge (por defecto — contenedores aislados pero pueden comunicarse por IP)# host (el contenedor usa la red del host directamente)# none (sin red)
# Crear una red personalizada (los contenedores se comunican por nombre)docker network create mi-red
# Iniciar contenedores en la misma reddocker run -d --name app --network mi-red mi-app:latestdocker run -d --name db --network mi-red postgres:16
# Dentro de "app", puede conectarse a "db" por nombre:# psql -h db -U postgres7. Docker Compose — varios contenedores coordinados
Sección titulada “7. Docker Compose — varios contenedores coordinados"docker compose define y levanta aplicaciones multi-contenedor con un fichero YAML.
# Verificar instalación (viene con docker-compose-plugin)docker compose versionEjemplo de compose.yaml para una pila web+base de datos:
services: web: image: nginx:alpine ports: - "80:80" volumes: - ./html:/usr/share/nginx/html:ro depends_on: - db
db: image: mariadb:11 environment: MARIADB_ROOT_PASSWORD: rootpass MARIADB_DATABASE: miapp MARIADB_USER: appuser MARIADB_PASSWORD: apppass volumes: - datos-db:/var/lib/mysql
volumes: datos-db:# Levantar todos los servicios (en background)docker compose up -d
# Ver estadodocker compose ps
# Ver logs de todos los serviciosdocker compose logs -f
# Parar sin eliminar contenedoresdocker compose stop
# Parar y eliminar contenedores, redes y volúmenes anónimosdocker compose down
# Eliminar también los volúmenes nombradosdocker compose down -v8. Integrar Docker con systemd
Sección titulada “8. Integrar Docker con systemd"Para que un contenedor arranque automáticamente con el servidor sin depender del daemon Docker directamente:
# Crear un unit de systemd que use docker composesudo nano /etc/systemd/system/mi-app.service[Unit]Description=Mi aplicación DockerAfter=docker.serviceRequires=docker.service
[Service]WorkingDirectory=/opt/mi-appExecStart=/usr/bin/docker compose upExecStop=/usr/bin/docker compose downRestart=alwaysRestartSec=10
[Install]WantedBy=multi-user.targetsudo systemctl daemon-reloadsudo systemctl enable mi-appsudo systemctl start mi-app9. Mantenimiento y limpieza
Sección titulada “9. Mantenimiento y limpieza"# Ver cuánto espacio ocupa Dockerdocker system df
# Eliminar todo lo que no está en uso (imágenes, contenedores parados, redes, caché)docker system prune
# Eliminar también volúmenes sin uso (¡cuidado con datos!)docker system prune --volumes
# Eliminar solo imágenes sin tag (dangling images)docker image prune
# Actualizar una imagen y recrear el contenedordocker pull nginx:latestdocker compose up -d --pull always