Skip to content

Docker Compose commands cheat sheet ​

A reference for the docker compose commands you use on a server, grouped by task. Each table lists the command and what it does, followed by the details that cause trouble in practice. Everything here is for Compose v2 and later (the docker compose plugin). If you still type docker-compose, see Docker Compose on Ubuntu for the switch. If Docker is not installed yet, start with install Docker on Ubuntu.

How Compose finds your project ​

Most commands work on "the current project" without naming it. Compose works it out like this:

  • The file. Without -f, Compose looks for compose.yaml (or compose.yml, docker-compose.yaml, docker-compose.yml) in the current folder, then in parent folders. If compose.override.yaml sits next to it, that file is merged on top automatically.
  • The project name. Taken from -p, then the COMPOSE_PROJECT_NAME variable, then a top level name: in the file, and finally the folder name. It prefixes all containers, networks and volumes, so /opt/blog/compose.yaml creates blog-web-1, blog_default and so on.
  • Variables. Values for ${VAR} in the file come from your shell and from .env in the project folder.

Practical rule: cd into the project folder before you run anything. Most "my containers are gone" moments are commands run from the wrong folder, which Compose treats as a different, empty project.

Start and stop ​

CommandWhat it does
docker compose up -dCreate and start all services in the background
docker compose up -d appStart only app (and what it depends on)
docker compose up -d --waitStart, then wait until services are running or healthy
docker compose stopStop containers, keep them
docker compose startStart containers that were stopped
docker compose restart appStop and start app with its existing configuration
docker compose downStop and remove containers and the project network
docker compose pause / unpauseFreeze and resume processes without stopping them
docker compose killStop immediately with SIGKILL, no graceful shutdown

Gotchas:

  • restart does not apply changes. After editing compose.yaml or .env, run docker compose up -d. It recreates only the containers whose configuration or image changed and leaves the rest running.
  • up without -d attaches your terminal to the logs, and Ctrl+C stops the whole project. On a server you almost always want -d.
  • stop vs down. stop keeps the containers and is quick to undo with start. down removes them. Data in named volumes survives both.
  • Slow shutdown. Containers get 10 seconds to exit before they are killed. Databases sometimes need more: docker compose stop -t 60 or stop_grace_period: in the file.

Status and logs ​

CommandWhat it does
docker compose psRunning containers of this project, with status and ports
docker compose ps -aInclude stopped and exited containers
docker compose lsAll running Compose projects on the server
docker compose ls -aAll projects, including stopped ones
docker compose logs -fFollow the logs of all services
docker compose logs -f --tail 100 appLast 100 lines of app, then follow
docker compose logs --since 30mOnly the last 30 minutes
docker compose logs -tAdd timestamps to each line
docker compose topProcesses running inside each container
docker compose statsLive CPU and memory usage per container
docker compose port app 8080Which host address a container port is published on

Gotchas:

  • logs without --tail prints everything since the container was created. On a container that has run for months this floods the terminal. Make --tail 100 a habit.
  • docker compose ls is the fastest way to find where a project lives: the CONFIG FILES column shows the path of its compose.yaml.

Run commands inside containers ​

CommandWhat it does
docker compose exec app shShell in the running app container
docker compose exec -u root app shSame, as root
docker compose exec db psql -U postgresRun a tool inside a service
docker compose exec -T db pg_dump -U postgres mydb > dump.sqlPipe output to a file on the host
docker compose run --rm app shStart a new one off container from the app service
docker compose run --rm --no-deps app ./migrateOne off task without starting dependencies
docker compose cp app:/app/config.yml ./config.ymlCopy a file from a container to the host
docker compose cp ./config.yml app:/app/config.ymlCopy a file from the host into a container

Gotchas:

  • exec vs run. exec enters a container that is already running. run creates a fresh container from the service definition, which is useful for migrations and maintenance scripts, or when the service is stopped.
  • Always add --rm to run. Without it, every run leaves a stopped container behind.
  • run does not publish ports from the service definition. Add --service-ports if you need them.
  • Use -T when piping in or out (> dump.sql, < dump.sql), and in cron jobs. Without it, the allocated TTY can add carriage returns to the output or fail when there is no terminal.
  • bash may not exist. Many images are based on Alpine or are minimal. Try sh if bash is not found.

Images and builds ​

CommandWhat it does
docker compose pullDownload newer versions of all images
docker compose pull appOnly for one service
docker compose imagesImages used by the project's containers
docker compose buildBuild services that have a build: section
docker compose build --no-cacheBuild from scratch, ignoring the layer cache
docker compose build --pullFetch a newer base image before building
docker compose up -d --buildRebuild, then start
docker compose up -d --force-recreateRecreate containers even if nothing changed
docker compose up -d --no-deps appRecreate app without touching its dependencies
docker compose up -d --pull alwaysPull images on every up

The standard update routine for a project built from published images:

bash
docker compose pull
docker compose up -d
docker image prune -f

Gotchas:

  • pull alone changes nothing for running containers. They keep the old image until up -d recreates them.
  • up does not rebuild an image that already exists. After changing a Dockerfile or source code, use up -d --build.
  • --force-recreate helps when a container needs a clean start, for example after changing log settings in daemon.json. It does not pull or rebuild anything.

Check the configuration ​

CommandWhat it does
docker compose configPrint the final configuration with variables filled in and files merged
docker compose config --quietOnly validate, print nothing on success
docker compose config --servicesList service names
docker compose config --volumesList named volumes
docker compose config --imagesList images the project uses
docker compose config --environmentShow the variables used for substitution
docker compose --dry-run up -dShow what up would do without doing it

Gotchas:

  • config prints secrets. Passwords from .env appear in plain text in its output. Do not paste it into chats or tickets unedited.
  • Run config --quiet before every up after editing YAML. Indentation errors show up with a line number instead of a half started project.

Several files and projects ​

CommandWhat it does
docker compose -f compose.yaml -f compose.prod.yaml up -dMerge files, later ones override earlier ones
docker compose -f /opt/blog/compose.yaml psWork on a project from any folder
docker compose -p staging up -dRun a second copy of the project under another name
docker compose --env-file .env.prod up -dUse another variables file
docker compose --project-directory /opt/blog psSet the base folder for relative paths

Gotchas:

  • Repeat the same -f and -p flags on every command. If you started with -p staging, a plain docker compose down targets a different project and does not stop staging.
  • Setting them once. COMPOSE_FILE, COMPOSE_PROJECT_NAME and COMPOSE_PROFILES can go into the project's .env file, so the short commands keep working. Separate several files in COMPOSE_FILE with : on Linux.
  • Relative paths in all files are resolved from the folder of the first file, not of the file they appear in.

Profiles ​

Profiles mark optional services that do not start by default, for example an admin tool or a one off backup job:

yaml
services:
  db:
    image: postgres:18
  adminer:
    image: adminer
    profiles: [tools]
    ports:
      - "127.0.0.1:8081:8080"
CommandWhat it does
docker compose up -dStarts only services without a profile (db)
docker compose --profile tools up -dAlso starts services in the tools profile
COMPOSE_PROFILES=tools docker compose up -dSame, with an environment variable
docker compose --profile "*" up -dEnable every profile
docker compose up -d adminerNaming a service starts it even if its profile is off
docker compose --profile tools downRemove profiled services together with the rest

Gotcha: a plain docker compose down ignores services in inactive profiles. Their containers keep running. Pass the same --profile to down that you used for up.

Watch mode (development) ​

watch rebuilds or updates containers automatically when files on disk change. It works only for services with a build: section and a develop.watch block:

yaml
services:
  web:
    build: .
    develop:
      watch:
        - action: sync
          path: ./src
          target: /app/src
        - action: rebuild
          path: package.json
CommandWhat it does
docker compose watchStart watching, show sync and rebuild events
docker compose up --watchStart the project with watching and normal logs

The actions are sync (copy changed files into the container), rebuild (build a new image and replace the container) and sync+restart (copy, then restart). Watch mode is meant for development. On a production server, deploy deliberately with pull or build and up -d.

Clean up, and the dangerous flags ​

CommandWhat it doesData loss?
docker compose downRemove containers and project networksNo, volumes stay
docker compose down --remove-orphansAlso remove containers of services deleted from the fileNo
docker compose up -d --remove-orphansSame cleanup while startingNo
docker compose rmRemove stopped service containersNo
docker compose down --rmi allAlso remove the project's imagesNo, but they must be pulled again
docker compose down -vAlso remove named and anonymous volumesYes
docker compose up -d -VRecreate anonymous volumes instead of reusing themYes, for anonymous volumes

docker compose down -v deletes your data

-v removes the named volumes declared in the file. For a database that means the whole database, with no undo. It is useful when you deliberately want to start over in development. On a server, use plain down, and have a backup before you ever type -v.

Gotchas:

  • Orphans. When you rename or delete a service in the file, its old container keeps running and Compose warns about orphan containers. --remove-orphans removes them.
  • External volumes and networks (marked external: true) are never removed by down, not even with -v.
  • Server wide cleanup is done with plain Docker commands, not Compose: docker image prune for unused images, docker system df to see what takes space. Be careful with docker volume prune --all: it deletes every volume no container uses at that moment, including the data of projects that are currently down. Without --all, current Docker versions only remove unused anonymous volumes.

Coming from docker-compose v1 ​

Old commandNew command
docker-compose up -ddocker compose up -d
docker-compose logs -f webdocker compose logs -f web
docker-compose exec web shdocker compose exec web sh
docker-compose -f prod.yml up -ddocker compose -f prod.yml up -d

Subcommands and most flags kept their names. The visible differences are container names with hyphens (project-web-1 instead of project_web_1) and the version: line at the top of files, which is now ignored.