elefcode
← All guides

Tools · 5 min read

Docker Compose vs docker run

A docker run command starts out simple and grows. Add a port, a volume, three environment variables and a restart policy, and you end up with a wall of flags living in your shell history or pasted in a README.

Docker Compose solves that by moving the same configuration into a file. This guide explains the difference and when to switch.

Try it yourself with the related tool.

Convert a docker run command →

Advertisement

Imperative vs declarative

docker run is imperative — you describe the container each time you start it, and the configuration exists only in that command. Compose is declarative: the configuration lives in docker-compose.yml, and docker compose up brings reality in line with the file.

That shift is what makes the setup reviewable, version-controllable, and reproducible on someone else's machine.

How the flags translate

Most flags map one to one: -p becomes ports, -v becomes volumes, -e becomes environment, --name becomes container_name, --restart becomes restart, and -w / -u become working_dir / user. Once you see the pattern, reading a Compose file is easy.

Where Compose really wins

Multiple services. The moment your app needs a database, a cache, or a worker alongside it, docker run means juggling several commands and a manually created network. Compose starts everything with one command, puts the services on a shared network automatically, and lets them reach each other by service name.

What does not carry over

Some flags describe how a container is *run* rather than how it is *configured* — -d and --rm are behaviours, not config. Use docker compose up -d for detached mode. Named networks created outside Compose appear as external: true, meaning Compose expects them to already exist.

Related guides