How to convert docker run commands to Docker Compose
On this page 5 sections
Short answer: each docker run flag has a matching key in compose.: -p becomes ports, -e becomes environment, -v becomes volumes, --restart becomes restart, and the image and any trailing arguments become image and command. Convert flag by flag, declare named volumes at the bottom, then check the file with docker compose config. DevSnip Pro's docker run → Compose tool does the conversion in VS Code, for one command or several at once.
READMEs usually show how to start a service with one long docker run command. That's fine once. When a project needs a database and a cache every day, a Compose file is easier to read, commit and share: docker compose up -d starts everything, and docker compose down stops it.
The flag-to-key mapping
| `docker run` | `compose.yaml` | Notes |
|---|---|---|
IMAGE (last argument before the command) | image: | |
| arguments after the image | command: | |
--name db | container_name: db | The service key is what other services use as a hostname |
-p 5432:5432 | ports: | Quote it: "5432:5432" |
-e KEY=value | environment: | Or env_file: for an . file |
-v pgdata:/ | volumes: | Named volumes are also declared at the top level |
-v . | volumes: | Bind mount; relative to the Compose file |
--restart unless-stopped | restart: unless-stopped | |
--network mynet | networks: | Declare the network at the top level too |
--health-cmd, --health-interval | healthcheck: | test, interval, timeout, retries |
-d | (none) | Use docker compose up -d |
--rm, -it | (none) | Interactive options for one-off runs |
A worked example
Here are two commands you might find in a project's setup notes: PostgreSQL with a named volume and a health check, and Redis with persistence turned on.
docker run -d --name db -p 5432:5432 \
-e POSTGRES_PASSWORD=secret -e POSTGRES_DB=app \
-v pgdata:/var/lib/postgresql/data \
--restart unless-stopped \
--health-cmd "pg_isready -U postgres" --health-interval 10s \
postgres:16-alpine
docker run -d --name cache -p 6379:6379 redis:7-alpine redis-server --appendonly yesConverted, they become one file with two services:
services:
db:
image: postgres:16-alpine
container_name: db
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=app
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test:
- CMD-SHELL
- pg_isready -U postgres
interval: 10s
cache:
image: redis:7-alpine
container_name: cache
ports:
- "6379:6379"
command:
- redis-server
- --appendonly
- yes
volumes:
pgdata:Three details are easy to get wrong by hand:
- Port mappings are quoted. YAML can read some unquoted
xx:yyvalues as numbers in base 60. Quoting every port mapping avoids the problem. - Named volumes need a top-level
volumes:entry. Without it, Compose refuses to start. A bind mount (a path such as.) doesn't need one./ data - A health check written as
--health-cmd "…"runs in a shell, so it becomesCMD-SHELLin Compose.
Move secrets out of the file
The example keeps POSTGRES_PASSWORD=secret inline, which is fine for a throwaway local database but not for a file you commit. Put the values in an . file next to compose., add . to ., and reference them:
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=appCompose reads . from the project directory automatically when it substitutes ${…} values. Commit an . with placeholder values so others know what to set. DevSnip Pro's .env Checker & Generator compares the two and generates . for you.
Check it, then start it
docker compose config
docker compose up -d
docker compose psdocker compose config validates the file and prints it fully resolved, with variables substituted, so mistakes show up before anything starts. Inside the Compose network, services reach each other by service name: an app container connects to postgres:/, not localhost:5432. From your own machine, the published ports still work on localhost.
Do it in VS Code
- Copy the
docker runcommands from the README. You can convert several at once, one after another. - Run DevSnip Pro: docker run → Compose, or search for "compose" in the DevSnip Pro tools sidebar with Ctrl/Cmd+K.
- Paste the commands, or take them from the active editor. The
compose.updates as you type, with a count of services and warnings, such as inline secrets.yaml - Save it as
compose.in your project, then runyaml docker compose config.
The tool handles ports, environment variables, volumes, networks, restart policies, health checks, resource limits and GPUs. For a new service rather than an existing command, the Docker Compose Generator & Validator and Dockerfile Generator & Linter in the same section start from your stack instead.