SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-10-14

Docker Compose commands wey you need for server

Learn Docker Compose V2 commands for lifecycle, changes, logs, shells, networks, volumes, and safe cleanup, plus why docker-compose fails on fresh Ubuntu.

Compose commands wey you go really use

Docker Compose get more than forty subcommands. Daily server work dey use about twelve. This page group dem according to the work wey you dey do, give one clear reason for each one, and point you to the detailed guide when command get hidden problem.

Everything here dey use Compose V2: docker compose with a space, no be the old docker-compose script. V2 na Go plugin wey dey install together with Docker Engine, and V1 don comot from current packages. So, if you see docker-compose: command not found for fresh Ubuntu box as of July 2026, na expected result, no be error. Check am with docker compose version. If e print nothing, install the docker-compose-plugin package.

Every command below dey run from the directory wey hold your compose.yaml, because Compose dey take project name from that directory and dey find the file relative to am. If you run the same command one level up, Compose go stop with no configuration file provided: not found. If file format itself still new to you, start with your first Compose file for VPS, then come back here for the commands.

Lifecycle: commands wey you dey type four times, and the one wey dey remove containers

docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose down

up -d go create the network, create the containers, start dem, then return. E go return as soon as e don create the containers. Na why deploy script wey run curl probe after am often fail for the first try. up -d --wait go wait until every service wey declare healthcheck report say e healthy, and e go exit with non-zero status if any one no reach that state. The flag only dey work as well as the check behind am, so write healthcheck wey Compose fit trust before you depend on am for automation.

stop go stop the containers but keep dem, so start go bring back the same containers with the same writable layer. down go stop dem, then remove the containers and the project network. Anything wey you write inside the container and outside a volume go disappear with dem. Na this be the most costly misunderstanding for Compose, and the complete difference between down and stop explain where e fit cause problem.

restart no be reload. E go stop and start the same container with the configuration wey e already get, so changed environment variable, new image tag, or edited port mapping no go get any effect. To apply file change, run up -d again. Compose go compare each service with the container wey dey run, then recreate only the ones wey configuration don change.

How to apply change: recreate, pull, or rebuild

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 dey do anything if nothing change, na why e safe to run am anytime. --force-recreate go ignore that comparison and replace every container even if the configuration still be the same, so na the fastest way to clear any funny state wey dey inside container.

To update image, you need two commands because dem dey do different things. pull go download the current image for every tag wey dey inside the file. up -d go come see say the image ID for the service no match the one wey dey run, so e go recreate the container. If you skip the pull, up -d go just keep the old latest wey you get since last month dey run without any error. The wahala dey show for multi-service stack, where to pull latest for every service at the same time fit break app wey dey work fine ten seconds ago, na why a self-hosted AFFiNE workspace dey pin each of im four image tags. Pinning also make upgrade be like deliberate edit of the tag, follow by the same pull and recreate. For stack wey dey migrate database as e dey boot, you must get dump for hand before you run any of the commands, na the routine a self-hosted Chatwoot support desk dey follow for every version bump.

build dey apply to services wey declare build: section instead of image:. up -d --build go build and start everything for one step, na the normal loop when you dey change code. Use --no-cache only when you see say cached layer don spoil, because e go rebuild every layer from scratch. Some projects dey provide both routes from one cloned repo, and the two loops come be alternative update paths: a self-hosted openGym workout tracker dey update with git pull, docker compose pull and docker compose up -d against im prebuilt images, and e dey use git pull follow by docker compose up -d --build only when you build am from source.

Wetin dey run

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 dey list only containers wey dey run. Service wey crash during startup no go show there until you add -a, so if container no dey ps but ps -a show am as Exited (1), na the normal pattern for startup failure. Read the exit code, then read the logs.

logs -f dey follow every service at once and put service name for front of each line. Na this view you need when services dey communicate with each other and event order matter. Put service name to narrow the result. --tail=100 matter for container wey don dey up for one month, because the default go print the complete history and fill the terminal with too much output. --since 15m answer the question wey you normally get: wetin happen during the restart wey you just do.

top dey list the processes inside each container. This one help separate "the container dey run" from "the process inside am dey run". ls comot from the current directory and list every Compose project for the host with its status, so you fit find the stack wey you start three months ago.

Get shell inside service

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 dey run command inside container wey don already dey up. run dey start new container from the same service definition. Na this one you need when service no stay up long enough make you exec inside am. Always use run together with --rm, because if you no use am, every invocation go leave stopped container behind. Dem go pile up until docker compose ps -a no readable again.

Try sh before bash. Alpine-based images no get bash, and the error message go show exec: "bash": executable file not found in $PATH. If you add --no-deps to run, e go skip the service dependencies. This stops quick config check from starting your whole database.

run --rm web env na the fastest way to see the environment wey service really receive, after e don merge every .env file, environment: block, and shell variable. When value no correct, na usually the merge order cause am. how Compose dey resolve env files and secrets explain which source go win.

Networks, ports, and name resolution

docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networks

Compose dey put every service for one project network, and each service name na DNS name for inside. If you run getent hosts db inside web, e go print the container IP if resolution dey work, and e no go print anything if e no work. So, e dey answer "these containers fit see each other?" sharp-sharp. If the name resolve but connection still fail, e mean say the process inside db dey bound to 127.0.0.1 instead of 0.0.0.0, so e no go fit accept packet from another container. The same boundary explain why container wey start outside the project, whether by docker run or as e own stack, no fit resolve name like jellyfin at all. Na this one you suppose check first if one Halcyon front end for your Jellyfin library no fit reach the server wey e point to. The rest of that model dey inside how Compose networks and service DNS work.

port web 80 dey print the host address and port wey container port dey published on. This one dey save you from guessing when the mapping come from variable. If you publish port, e go write firewall rule wey Docker dey manage by e-self, and that rule dey stay front of your own rules. So, service wey you think say dey private fit dey open to internet. We cover that case for why published Docker ports bypass ufw. E safer make you no publish those ports, but instead, put one authenticating proxy for the project network wey go stay front of the services. Na this one running Authentik as a single sign-on layer dey give you.

Volumes and data

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

config --volumes dey print the named volumes wey the project declare, one for each line. Na that list you need back up. When the volumes hold something wey you no fit replace, the exact backup command matter as much as the list. Na why the PhotoPrism and Immich comparison dey show the dump and copy commands wey each photo server need. cp dey copy file enter or comot from container without opening shell, using the service:path form for any side wey container dey.

down -v dey remove those named volumes together with the containers. Na the correct command to tear down test stack, but e wrong for anything wey hold data wey you care about, because e no dey ask for confirmation and you no fit undo am. Bind mounts survive am because dem dey live for host filesystem. This difference for blast radius na one reason to choose carefully between bind mounts and named volumes.

Waka wey you go take free disk space without loss of data

docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune

--remove-orphans dey delete containers wey belong to the project but no dey inside the file again, na wetin dey happen if you rename service. If you no use am, dem containers go continue to dey run, but docker compose ps no go fit see dem.

docker system df dey show you where your disk space dey go before you delete anything, e dey split images, containers, local volumes and build cache with the amount of space wey you fit recover for each one. image prune -a dey remove every image wey no container dey use, whether e get tag or e no get. For server wey don pull plenty versions of one big image, this one usually dey free the most space. builder prune dey clear the build cache, wey dey grow small-small for any server wey dey build im own images.

None of those commands dey touch named volume. Na only docker volume prune --all and docker compose down -v fit do that one. Ordinary docker volume prune dey remove anonymous volumes only.

Check the file before e cause problem

docker compose config --quiet
docker compose config --services
docker compose --dry-run up -d

config --quiet dey validate and print nothing when e succeed, so e good for pre-deploy step or git hook. Plain config dey print the fully merged and interpolated file. Na so you fit confirm say variable resolve and override file layer the way you expect. If variable no set, e go show as empty value, together with warning The "X" variable is not set. Defaulting to a blank string.

--dry-run na global flag, no be subcommand flag, so e go come before up. E dey print every action Compose go take and e no change anything. Those thirty seconds worth am before you run down for stack wey matter.

Working across files, profiles, and projects

docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -d

Multiple -f flags dey merge in order, and later files dey override earlier ones key by key. Na the standard way to keep one base file with small production override, but the rules dey different for lists and maps, so read how Compose merges multiple files before you debug unexpected result.

--profile dey start services wey get that profile together with the ones wey no get profile, so debug tooling no go enter normal up. -p dey set the project name, so two copies of one stack fit run side by side with separate networks and separate volume names. To bring the stack back after reboot no be command wey you type yourself; na unit wey dey run one for you, as starting Compose stacks on boot describe.

FAQ

Wetin replace docker-compose wey get hyphen?

Compose V2, wey dem dey call as docker compose with space. E be plugin wey dem bundle inside Docker Engine, and current packages no dey install the V1 Python tool again. If the space form no show anything, install the docker-compose-plugin package for your distribution. Update old scripts make dem use the space form instead of alias, because V2 get flags wey V1 no get.

Why docker compose restart no dey see my config change?

restart dey stop and start the container wey dey already exist with the configuration wey dem take create am, e no dey re-read compose.yaml. Any change wey you do for environment variables, ports, volumes or image tag need docker compose up -d, wey go compare each service with the container wey dey run and recreate the ones wey different. Add --force-recreate if you want make the replacement happen even if nothing change for the file.

How I go update service go new image?

Run docker compose pull, then docker compose up -d. The pull go fetch the current image for each tag wey dey the file, and up -d go recreate any service wey e image ID no match the container again. If you run up -d by itself, e go just use the image wey dey disk already, na why stack wey dem pin to latest fit stay months without update and e no go show error.

Which cleanup commands safe for live server?

docker system df, docker image prune -a and docker builder prune dey remove images and cache only, so services wey dey run go continue to work and dem no go touch named volumes. The two wey dangerous na docker compose down -v, wey dey delete project named volumes without ask you, and docker volume prune --all, wey dey delete every named volume wey no container dey use after one y/N prompt, or nothing at all if you use -f. Run docker compose config --volumes first so you go know wetin fit loss.

I fit run one command without start the whole stack?

Yes. docker compose run --rm --no-deps web sh dey start one single container from the web service definition, e go skip dependencies, and e go remove the container when you exit. Use exec instead if the container dey already run, because exec go join the live process and show you the state wey the service dey currently.

Dis article help you?