SSD Nodes Learn 8GB de RAM — $66/año
Guías Matt ConnorPor Matt Connor · Actualizado 2026-08-02

Docker Compose: comandos esenciales para servidores

Guía práctica de Compose V2 para servidores: ciclo de vida, cambios, logs, shells, redes, volúmenes y limpieza segura, con errores y diferencias clave.

Los comandos de Compose que realmente se usan

Docker Compose incluye más de cuarenta subcomandos. El trabajo diario en un servidor usa aproximadamente una docena. Esta página los agrupa según la tarea que realiza, explica brevemente el motivo de cada uno y enlaza a la explicación detallada cuando un comando oculta algún problema.

Todo lo descrito aquí usa Compose V2: docker compose con un espacio, no el script antiguo docker-compose. V2 es un plugin escrito en Go que se instala con Docker Engine, y V1 ya no está disponible en los paquetes actuales. Por eso, recibir docker-compose: command not found en un sistema Ubuntu recién instalado en julio de 2026 es lo esperado y no indica un fallo. 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 aún 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 down

up -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 en el primer intento. up -d --wait espera hasta que todos los servicios que declaran un healthcheck informan de que están healthy y termina con un código distinto de cero si alguno nunca llega a ese estado. La eficacia de la opción depende de la comprobación que haya detrás. Por eso, escribe un healthcheck en el que Compose pueda confiar antes de usarla en la automatización.

stop detiene los contenedores y los conserva. De este modo, start vuelve a iniciar los mismos contenedores con la misma capa escribible. down los detiene 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 malentendido más costoso en Compose. La diferencia completa entre down y stop explica dónde tiene consecuencias.

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 etiqueta de imagen nueva o un mapeo de puertos editado no tienen ningún efecto. Para aplicar un cambio en el archivo, vuelve a ejecutar up -d. Compose compara cada servicio con su contenedor en ejecución y recrea solo los contenedores cuya configuración haya cambiado.

Aplicar un cambio: recrear, descargar o reconstruir

docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build web

up -d no hace nada por sí solo cuando no hay cambios, lo que permite ejecutarlo repetidamente de forma segura. --force-recreate omite esa comparación y reemplaza todos los contenedores incluso cuando la configuración es idéntica, por lo que es la forma más rápida de eliminar estados anómalos 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 recrea. Si omite la descarga, up -d mantiene en ejecución el latest del mes pasado sin producir ningún error.

build se aplica a los servicios que declaran una sección build: en lugar de una sección image:. up -d --build compila e inicia en un solo paso, que es el ciclo normal mientras cambia el código. Use --no-cache solo cuando una capa almacenada en caché esté claramente obsoleta, porque reconstruye todas las capas desde cero.

Ver los servicios 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 ls

ps solo muestra los contenedores en ejecución. Un servicio que falló durante el inicio no aparece allí hasta que se añade -a, por lo que un contenedor ausente de ps mientras ps -a lo muestra como Exited (1) es el comportamiento normal de un fallo de inicio. Lea el código de salida y, después, los logs.

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. Indique un servicio para limitar la salida. --tail=100 es importante en un contenedor que lleva un mes en ejecución, porque la opción 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 dentro del contenedor está en ejecución». ls sale del directorio actual y muestra todos los proyectos de Compose del host junto con su estado, para que pueda encontrar 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 sh

exec ejecuta un comando dentro de un contenedor que ya está activo. run inicia un contenedor nuevo a partir de la misma definición de servicio. Esto es necesario cuando el servicio no permanece activo el tiempo suficiente para usar exec. Combine siempre run con --rm. De lo contrario, cada ejecución deja un contenedor detenido, y estos se acumulan hasta que docker compose ps -a resulta ilegible.

Pruebe sh antes que bash. Las imágenes basadas en Alpine no incluyen bash, y el error muestra 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 todos los archivos .env, los bloques environment: y las variables del shell. Si un valor es incorrecto, normalmente se debe al orden de combinación. cómo Compose resuelve los archivos env 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 --networks

Compose coloca todos los servicios en una red del proyecto, y cada nombre de servicio es un nombre DNS en 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 responde en dos segundos a la pregunta «¿estos contenedores pueden comunicarse 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 los que se publica el puerto de un contenedor. Esto evita tener que adivinar cuando la asignación proviene de una variable. Publicar un puerto también crea una regla de firewall que Docker administra directamente. Esa regla se evalúa antes que las tuyas. Por tanto, un servicio que considerabas privado puede quedar expuesto a Internet. Este caso se explica en por qué los puertos de Docker publicados evitan ufw.

Volúmenes y datos

docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -v

config --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. cp copia un archivo hacia o desde un contenedor sin abrir un shell, mediante el formato service:path en el lado donde se encuentra el contenedor.

down -v elimina esos volúmenes con nombre junto con los contenedores. Es el comando adecuado para desmontar una pila de prueba y el incorrecto para cualquier elemento que contenga datos importantes, porque no solicita confirmación y no permite deshacer la operación. Los montajes vinculados sobreviven, porque residen en el sistema de archivos del host. Esta diferencia en el alcance del impacto es uno de los motivos para elegir deliberadamente entre montajes vinculados 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 que 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 docker compose ps no los muestra.

docker system df muestra cómo se distribuye el espacio en disco antes de eliminar nada. Separa las imágenes, los contenedores, los volúmenes locales y la caché de compilación, e indica cuánto espacio se puede recuperar en cada categoría. 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, normalmente esta acción libera más espacio. builder prune borra la caché de compilación, que crece silenciosamente en cualquier servidor que compile sus propias imágenes.

Ninguno de estos comandos modifica un volumen con nombre. Solo 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 -d

config --quiet valida y no muestra 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 muestra el archivo completamente combinado e interpolado. Así puede confirmar que una variable se resolvió y que un archivo de sobrescritura se aplicó como esperaba. Una variable no definida aparece como un valor vacío, junto con la advertencia The "X" variable is not set. Defaulting to a blank string.

--dry-run es una opción global, no una opción de subcomando, por lo que debe colocarse antes de up. Muestra todas las acciones que Compose realizaría y no modifica nada. Esos treinta segundos resultan útiles antes de ejecutar down en una pila importante.

Trabajo con varios 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 -d

Varias opciones -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 modificación para producción. Sin embargo, las reglas son diferentes para las listas y los mapas. Consulte cómo Compose combina 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 volumen independientes. Para recuperar la pila después de un reinicio, no debe escribir ningún comando. Debe usar una unidad que lo ejecute automáticamente, como se describe en iniciar pilas de Compose durante el arranque.

FAQ

¿Qué reemplazó docker-compose por un guion?

Compose V2, invocado como docker compose con un espacio. Es un complemento incluido con Docker Engine, y la herramienta Python V1 ya no se instala con los paquetes actuales. Si la forma con espacio no muestra nada, instale el paquete docker-compose-plugin correspondiente a su distribución. Actualice los scripts antiguos para usar la forma con espacio en lugar de agregar un alias, porque V2 tiene opciones que V1 no tenía.

¿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, que compara cada servicio con su contenedor en ejecución y vuelve a crear los que son diferentes. Agregue --force-recreate cuando quiera que el reemplazo se realice 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 extracción obtiene la imagen actual para cada etiqueta del archivo, y up -d vuelve a crear cualquier servicio cuya ID de imagen ya no coincida con la 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 en producción?

docker system df, docker image prune -a y docker builder prune eliminan únicamente imágenes y caché, por lo que los servicios en ejecución siguen funcionando y los volúmenes con nombre no se modifican. La pareja peligrosa es docker compose down -v y docker volume prune, que 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 de 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.