Docker y Compose: la base para alojar tus servicios
Básico
Los pasos marcados en azul cambian según tu sistema.
Casi todo lo que merece la pena alojar en casa o en tu servidor (un gestor de contraseñas, una nube de fotos, un lector de noticias, un panel que vigila tus webs) se distribuye hoy como una imagen de Docker. Es la forma más cómoda de tenerlo: cada aplicación viaja con todo lo que necesita, vive aislada del resto y se actualiza o se borra sin dejar restos por el sistema.
En este tutorial instalarás Docker desde su repositorio oficial, entenderás sus cuatro piezas básicas y levantarás tu primer servicio con Compose, el archivo que describe cómo se monta cada aplicación. También verás la trampa más habitual: los puertos que Docker abre por su cuenta, aunque el cortafuegos diga que no.
Lo que necesitas
- Un servidor con un usuario con
sudoy el cortafuegos activo. Si partes de cero, sigue antes los primeros pasos de un servidor Linux. - Al menos 1 GB de memoria. Docker en sí gasta poco; lo que pesa son las aplicaciones que metas.
Paso 1: quitar versiones antiguas
Las distribuciones traen sus propios paquetes de Docker, pero suelen ir varias versiones por detrás y no siempre incluyen Compose. Usarás el repositorio de Docker, así que primero quita lo que pueda chocar con él. Si no tenías nada instalado, el comando simplemente avisará de que no hay nada que quitar.
Ubuntu
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt remove $pkg; done
Debian
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt remove $pkg; done
AlmaLinux / Rocky
sudo dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runc
Fedora
sudo dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
Paso 2: instalar Docker
Ubuntu
Descarga la clave con la que Docker firma sus paquetes y añade su repositorio. El nombre de tu versión de Ubuntu (como noble o resolute) se rellena solo:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Instala Docker con sus complementos, entre ellos Compose:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
En Ubuntu, el servicio arranca solo nada más instalarse.
Debian
Descarga la clave con la que Docker firma sus paquetes y añade su repositorio. El nombre de tu versión de Debian (como bookworm o trixie) se rellena solo:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Instala Docker con sus complementos, entre ellos Compose:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
En Debian, el servicio arranca solo nada más instalarse.
AlmaLinux / Rocky
Añade el repositorio de Docker, instala sus paquetes y arranca el servicio:
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
Si te pregunta si aceptas la clave GPG, comprueba que la huella es 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35 antes de decir que sí.
Fedora
Añade el repositorio de Docker, instala sus paquetes y arranca el servicio:
sudo dnf config-manager addrepo --from-repofile https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
Si te pregunta si aceptas la clave GPG, comprueba que la huella es 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35 antes de decir que sí.
Comprueba que todo funciona con el contenedor de prueba:
sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
Docker ha descargado una imagen diminuta, ha creado un contenedor a partir de ella, ha mostrado ese mensaje y lo ha parado. Todo en un par de segundos.
Paso 3: usar Docker sin sudo, sabiendo lo que implica
Escribir sudo delante de cada orden cansa. Para evitarlo, añade tu usuario al grupo docker y vuelve a entrar en el servidor para que el cambio surta efecto:
sudo usermod -aG docker $USER
Antes de hacerlo, entiende lo que significa: estar en el grupo docker equivale a ser administrador. Quien puede lanzar contenedores puede montar dentro de uno todo el disco del servidor y hacer con él lo que quiera. En un servidor que solo usas tú no cambia nada; en uno compartido, no metas a nadie en ese grupo a la ligera.
Paso 4: las cuatro piezas
Con estas cuatro ideas entenderás cualquier receta de autoalojamiento:
- Imagen: la aplicación empaquetada, con su sistema mínimo y sus dependencias. Es de solo lectura y se descarga de un registro como Docker Hub. Su nombre lleva una etiqueta de versión, como
louislam/uptime-kuma:2. - Contenedor: una imagen en marcha. Se puede parar, borrar y volver a crear en segundos. Lo que se escribe dentro se pierde al borrarlo, salvo que lo guardes en un volumen.
- Volumen: la carpeta donde viven los datos que importan, fuera del contenedor. Aquí usarás la forma más clara: una carpeta normal del servidor que el contenedor ve como suya.
- Puerto publicado: la puerta por la que se llega a la aplicación desde fuera del contenedor.
Paso 5: tu primer servicio con Compose
Compose describe en un archivo, compose.yaml, qué imagen usar, dónde guardar los datos y qué puertos abrir. Así cada servicio se monta igual siempre, y el archivo te sirve de documentación.
Como ejemplo, montarás Uptime Kuma, un panel que vigila tus webs y servicios y te avisa si alguno se cae. Dale una carpeta propia; es buena costumbre tener una por servicio:
mkdir -p ~/servicios/uptime-kuma
cd ~/servicios/uptime-kuma
nano compose.yaml
~/servicios/uptime-kuma/compose.yaml
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: unless-stopped
volumes:
- ./datos:/app/data
ports:
- "127.0.0.1:3001:3001"
Línea a línea:
image: la imagen y su versión. La etiqueta2sigue las actualizaciones de la versión 2 sin saltar por sorpresa a una 3.restart: unless-stopped: si el servidor se reinicia o la aplicación se cae, Docker la vuelve a levantar, salvo que la hayas parado tú.volumes: la carpetadatos, junto alcompose.yaml, será la carpeta/app/datadel contenedor. Ahí quedan la configuración y el historial de Uptime Kuma.ports: el puerto 3001 del contenedor se publica en el 3001 del servidor, pero solo para el propio servidor (127.0.0.1). Enseguida verás por qué.
Levántalo:
docker compose up -d
La primera vez descargará la imagen. El -d lo deja funcionando en segundo plano. Comprueba que está en marcha y mira lo que cuenta:
docker compose ps
docker compose logs -f
Sal de los registros con Ctrl+C; el servicio sigue funcionando.
La trampa del cortafuegos
Si en ports hubieras escrito solo "3001:3001", Uptime Kuma quedaría abierto a todo internet aunque UFW o firewalld lo prohíban. Docker escribe sus propias reglas en el cortafuegos del núcleo, y lo hace por delante de las tuyas. Es la sorpresa más común de quien empieza, y la causa de muchas bases de datos expuestas sin querer.
La regla de oro: publica los puertos en 127.0.0.1 y deja que entren solo por una puerta que controles. Tienes dos:
- Un túnel SSH, para paneles que solo usas tú. Desde tu ordenador,
ssh -L 3001:127.0.0.1:3001 usuario@tu-servidory abrehttp://localhost:3001. Lo tienes explicado en SSH a fondo. - Nginx como puerta de entrada, para lo que tenga que verse desde fuera, con su dominio y su HTTPS. Es el proxy inverso de tu servidor web con Nginx, con un añadido: Uptime Kuma, como muchas aplicaciones modernas, usa websockets para actualizar la pantalla en directo, y Nginx necesita tres líneas más para dejarlos pasar. En AlmaLinux, Rocky y Fedora, el archivo va en
/etc/nginx/conf.d/estado.ejemplo.org.conf, y SELinux pide antessudo setsebool -P httpd_can_network_connect 1:
/etc/nginx/sites-available/estado.ejemplo.org
server {
listen 80;
listen [::]:80;
server_name estado.ejemplo.org;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
Después, cífralo con Let’s Encrypt. La primera vez que entres, Uptime Kuma te pedirá crear la cuenta de administración: hazlo enseguida, antes de que lo haga otro.
Paso 6: el día a día
Todas estas órdenes se lanzan desde la carpeta del servicio, donde está su compose.yaml:
- Actualizar:
docker compose pulldescarga la imagen nueva ydocker compose up -drecrea el contenedor con ella. Los datos siguen en./datos. - Parar y quitar:
docker compose downpara el servicio y borra el contenedor, pero no la carpeta de datos.docker compose up -dlo vuelve a levantar tal como estaba. - Reiniciar:
docker compose restart.
Y estas, desde cualquier sitio:
docker ps: los contenedores en marcha.docker stats: cuánta memoria y CPU gasta cada uno, en directo.docker system df: cuánto disco ocupan imágenes, contenedores y volúmenes.docker image prune: borra las imágenes viejas que ya no usa ningún contenedor. Tras unas cuantas actualizaciones, libera bastante espacio.
Lo único que de verdad tienes que proteger es la carpeta ~/servicios: dentro están la receta (compose.yaml) y los datos de cada aplicación. Con eso puedes rehacerlo todo en otro servidor en minutos. Inclúyela en tus copias de seguridad con restic.
Siguiente paso
Ya tienes la base. El siguiente servicio que vale la pena alojar es el que guarda todas las demás llaves: tu gestor de contraseñas con Vaultwarden.
