Chuleta de Docker Compose para servidores reales
Consulta los comandos de Compose V2 para servidores: ciclo de vida, cambios, logs, shells, redes, volúmenes y limpieza segura, con el error exacto de rutas.
Los comandos de Compose que realmente se utilizan
Docker Compose incluye más de cuarenta subcomandos. El trabajo diario en un servidor utiliza aproximadamente una docena. Esta página los agrupa según la tarea que se realiza, explica en lenguaje claro el motivo de cada uno y enlaza con el análisis detallado cuando un comando tiene alguna particularidad importante.
Todo lo que aparece aquí utiliza Compose V2: docker compose con un espacio, no el script antiguo docker-compose. V2 es un complemento escrito en Go que se instala con Docker Engine. V1 ya no está disponible en los paquetes actuales, por lo que un docker-compose: command not found en una instalación nueva de Ubuntu en julio de 2026 es un comportamiento esperado, no un error. Compruébelo con docker compose version. Si no muestra nada, instale el paquete docker-compose-plugin.
Todos los comandos siguientes se ejecutan desde el directorio que contiene compose.yaml, porque Compose obtiene el nombre del proyecto de ese directorio y busca el archivo en relación con él. Si ejecuta el mismo comando un nivel por encima, Compose se detiene con no configuration file provided: not found. Si el formato del archivo todavía es nuevo para usted, empiece por un primer archivo de Compose en un VPS y vuelva aquí para consultar los comandos.
Ciclo de vida: los cuatro comandos que se escriben y el que elimina los contenedores
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d crea la red, crea los contenedores, los inicia y termina. Termina en cuanto los contenedores están creados. Por eso un script de despliegue que ejecuta después una comprobación curl suele fallar el primer intento. up -d --wait espera hasta que todos los servicios que declaran una comprobación de estado informan de que están saludables y termina con un código distinto de cero si alguno nunca alcanza ese estado. La opción sólo es tan fiable como la comprobación que utiliza. Por tanto, escriba una comprobación de estado que Compose pueda validar antes de usarla en la automatización.
stop detiene los contenedores y los conserva. Después, start inicia los mismos contenedores con la misma capa escribible. down detiene los contenedores y después elimina los contenedores y la red del proyecto. Todo lo que se haya escrito dentro del contenedor y fuera de un volumen se elimina con ellos. Este es el error de comprensión más costoso en Compose. La diferencia completa entre down y stop explica dónde se produce.
restart no es una recarga. Detiene e inicia el mismo contenedor con la configuración que ya tiene. Por tanto, una variable de entorno modificada, una nueva etiqueta de imagen o un mapeo de puertos editado no tienen ningún efecto. Para aplicar un cambio en el archivo, vuelva a ejecutar up -d. Compose compara cada servicio con su contenedor en ejecución y sólo recrea los contenedores cuya configuración haya cambiado.
Aplicar un cambio: recrear, descargar o volver a compilar
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webup -d no hace nada si no ha cambiado nada, lo que permite ejecutarlo repetidamente de forma segura. --force-recreate ignora esa comparación y reemplaza todos los contenedores aunque la configuración sea idéntica, por lo que es la forma más rápida de eliminar un estado extraño dentro de los contenedores.
Actualizar una imagen requiere dos comandos porque realizan tareas diferentes. pull descarga la imagen actual para cada etiqueta indicada en el archivo. Después, up -d detecta que el ID de imagen del servicio ya no coincide con el de su contenedor en ejecución y lo vuelve a crear. Si omite la descarga, up -d mantiene en ejecución el latest del mes pasado sin mostrar ningún error. El riesgo contrario aparece en una pila con varios servicios: descargar latest para todos los servicios a la vez puede romper una aplicación que funcionaba diez segundos antes. Por eso un espacio de trabajo AFFiNE autohospedado fija cada una de sus cuatro etiquetas de imagen.
build se aplica a los servicios que declaran una sección build: en lugar de un image:. up -d --build compila e inicia en un solo paso, que es el ciclo normal mientras cambia el código. Use --no-cache sólo cuando una capa almacenada en caché esté claramente obsoleta, porque vuelve a compilar todas las capas desde cero.
Ver lo que está en ejecución
docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose lsps sólo muestra los contenedores en ejecución. Un servicio que ha fallado durante el arranque no aparece ahí hasta que se añade -a. Por eso, que falte un contenedor en ps mientras ps -a lo muestra como Exited (1) es el patrón normal de un fallo de arranque. Lea el código de salida y, después, los registros.
logs -f sigue todos los servicios a la vez y antepone a cada línea el nombre del servicio. Esta es la vista adecuada cuando los servicios se comunican entre sí y el orden de los eventos es importante. Especifique un servicio para limitar la salida. --tail=100 es importante en un contenedor que lleva un mes en ejecución, porque la salida predeterminada muestra todo el historial y llena el terminal. --since 15m responde a la pregunta habitual: qué ocurrió durante el reinicio que acaba de realizar.
top muestra los procesos dentro de cada contenedor. Esto permite distinguir entre «el contenedor está en ejecución» y «el proceso que contiene está en ejecución». ls sale del directorio actual y muestra todos los proyectos de Compose del host con su estado. Así puede localizar la pila que inició hace tres meses.
Obtener un shell dentro de un servicio
docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web shexec ejecuta un comando dentro de un contenedor que ya está en ejecución. run inicia un contenedor nuevo a partir de la misma definición de servicio. Es lo que necesita cuando el servicio no permanece activo el tiempo suficiente para ejecutar un comando con exec. Combine siempre run con --rm. Sin esta opción, cada ejecución deja un contenedor detenido, y estos se acumulan hasta que docker compose ps -a deja de ser legible.
Pruebe sh antes que bash. Las imágenes basadas en Alpine no incluyen bash, y el error aparece como exec: "bash": executable file not found in $PATH. Añadir --no-deps a run omite las dependencias del servicio. Así, una comprobación rápida de la configuración no inicia toda la base de datos.
run --rm web env es la forma más rápida de ver el entorno que recibió realmente un servicio después de combinar cada archivo .env, bloque environment: y variable del shell. Cuando un valor es incorrecto, el orden de combinación suele ser la causa. cómo Compose resuelve los archivos de entorno y los secretos explica qué origen tiene prioridad.
Redes, puertos y resolución de nombres
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksCompose coloca todos los servicios en una red del proyecto, y cada nombre de servicio es un nombre DNS dentro de ella. Ejecutar getent hosts db dentro de web muestra la IP del contenedor cuando la resolución funciona y no muestra nada cuando falla. Por eso permite comprobar en dos segundos si «estos contenedores pueden verse entre sí». Si el nombre se resuelve pero la conexión se rechaza, el proceso dentro de db está enlazado a 127.0.0.1 en lugar de 0.0.0.0. Por tanto, nunca acepta paquetes de otro contenedor. El resto de este modelo se explica en cómo funcionan las redes de Compose y el DNS de los servicios.
port web 80 muestra la dirección del host y el puerto en el que está publicado un puerto del contenedor. Esto evita tener que deducirlos cuando la asignación procede de una variable. Publicar un puerto también crea una regla de firewall que Docker gestiona por su cuenta. Esa regla se evalúa antes que las suyas. Por tanto, un servicio que consideraba privado puede quedar expuesto a Internet. Este caso se explica en por qué los puertos publicados de Docker omiten ufw. Mantener esos puertos sin publicar y colocar delante de los servicios un único proxy con autenticación en la red del proyecto es una arquitectura más segura. Eso es lo que ofrece ejecutar Authentik como capa de inicio de sesión único.
Volúmenes y datos
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes muestra los volúmenes con nombre que declara el proyecto, uno por línea. Esa es la lista que debe incluir en la copia de seguridad. Cuando los volúmenes contienen datos irreemplazables, el comando exacto de copia de seguridad es tan importante como la lista. Por eso, la comparación entre PhotoPrism e Immich especifica los comandos de volcado y copia que necesita cada servidor de fotos. cp copia un archivo hacia o desde un contenedor sin abrir un shell. Usa la forma service:path en el lado que corresponda al contenedor.
down -v elimina esos volúmenes con nombre junto con los contenedores. Es el comando adecuado para desmontar una pila de pruebas y el incorrecto para cualquier pila que contenga datos importantes, porque no solicita confirmación y no permite deshacer la operación. Los bind mounts sobreviven, porque residen en el sistema de archivos del host. Esta diferencia en el alcance del impacto es una de las razones para elegir deliberadamente entre bind mounts y volúmenes con nombre.
Limpieza que libera espacio en disco sin perder datos
docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune--remove-orphans elimina los contenedores que pertenecen al proyecto pero ya no aparecen en el archivo. Esto es exactamente lo que ocurre después de cambiar el nombre de un servicio. Sin esta opción, esos contenedores siguen ejecutándose y quedan invisibles para docker compose ps.
docker system df muestra qué está ocupando el disco antes de eliminar nada. Desglosa las imágenes, los contenedores, los volúmenes locales y la caché de compilación, e indica cuánto se puede recuperar en cada caso. image prune -a elimina todas las imágenes a las que no apunta ninguna etiqueta. En un servidor que ha descargado varias versiones de una imagen grande, esta suele ser la mayor recuperación de espacio. builder prune borra la caché de compilación, que crece silenciosamente en cualquier servidor que genere sus propias imágenes.
Ninguno de esos comandos afecta a un volumen con nombre. Sólo docker volume prune y docker compose down -v lo hacen.
Comprobar el archivo antes de que cause problemas
docker compose config --quiet
docker compose config --services
docker compose --dry-run up -dconfig --quiet valida el archivo y no imprime nada si la validación es correcta, por lo que debe usarse en un paso previo al despliegue o en un hook de Git. config sin opciones imprime el archivo completamente combinado e interpolado. Así puede confirmar que una variable se resolvió y que un archivo de override se aplicó como esperaba. Una variable no definida aparece allí con un valor vacío, junto a la advertencia The "X" variable is not set. Defaulting to a blank string.
--dry-run es una opción global, no una opción del subcomando, por lo que debe colocarse antes de up. Imprime todas las acciones que Compose realizaría y no cambia nada. Son treinta segundos bien invertidos antes de ejecutar down en un stack importante.
Trabajo con archivos, perfiles y proyectos
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -dVarios indicadores -f se combinan en orden. Los archivos posteriores sobrescriben las claves de los archivos anteriores. Esta es la forma estándar de mantener un archivo base con una pequeña sobreescritura para producción. Sin embargo, las reglas son diferentes para las listas y los mapas. Consulte cómo combina Compose varios archivos antes de investigar un resultado inesperado.
--profile inicia los servicios etiquetados con ese perfil junto con los servicios sin etiqueta. Esto mantiene las herramientas de depuración fuera de un up normal. -p establece el nombre del proyecto. Así, dos copias de una misma pila pueden ejecutarse en paralelo con redes y nombres de volúmenes independientes. Para recuperar la pila después de un reinicio no tiene que escribir ningún comando. Una unidad se encarga de hacerlo. Se describe en iniciar pilas de Compose durante el arranque.
FAQ
¿Qué sustituyó docker-compose con un guion?
Compose V2, que se ejecuta como docker compose, con un espacio. Es un complemento incluido con Docker Engine, y las versiones actuales de los paquetes ya no instalan la herramienta V1 escrita en Python. Si la forma con espacio no muestra ninguna salida, instale el paquete docker-compose-plugin correspondiente a su distribución. Actualice los scripts antiguos para usar la forma con espacio en lugar de añadir un alias, porque V2 tiene flags que V1 nunca tuvo.
¿Por qué docker compose restart no aplica mi cambio de configuración?
restart detiene e inicia el contenedor existente con la configuración con la que se creó, y nunca vuelve a leer compose.yaml. Cualquier cambio en las variables de entorno, los puertos, los volúmenes o la etiqueta de la imagen requiere docker compose up -d. Este comando compara cada servicio con su contenedor en ejecución y recrea los que sean diferentes. Añada --force-recreate cuando quiera que la sustitución se produzca aunque no haya cambiado nada en el archivo.
¿Cómo actualizo un servicio a una imagen más reciente?
Ejecute docker compose pull y después docker compose up -d. La operación pull descarga la imagen actual para cada etiqueta del archivo, y up -d recrea cualquier servicio cuyo ID de imagen ya no coincida con el de su contenedor. Ejecutar up -d por sí solo reutiliza la imagen que ya está en el disco. Por eso una pila fijada en latest puede seguir usando una compilación de hace meses sin mostrar ningún error.
¿Qué comandos de limpieza son seguros en un servidor activo?
docker system df, docker image prune -a y docker builder prune eliminan únicamente imágenes y caché. Los servicios en ejecución siguen funcionando y los volúmenes con nombre no se modifican. La combinación peligrosa es docker compose down -v y docker volume prune, porque elimina los volúmenes con nombre sin pedir confirmación. Ejecute primero docker compose config --volumes para saber qué elementos están en riesgo.
¿Puedo ejecutar un comando sin iniciar toda la pila?
Sí. docker compose run --rm --no-deps web sh inicia un solo contenedor a partir de la definición del servicio web, omite sus dependencias y elimina el contenedor cuando sale. Use exec cuando el contenedor ya esté en ejecución, porque exec se conecta al proceso activo y muestra el estado real del servicio.