How to convert docker run commands to Docker Compose

By Sayaib SarkarUpdated 4 min read

On this page 5 sections

Short answer: each docker run flag has a matching key in compose.yaml: -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 imagecommand:
--name dbcontainer_name: dbThe service key is what other services use as a hostname
-p 5432:5432ports:Quote it: "5432:5432"
-e KEY=valueenvironment:Or env_file: for an .env file
-v pgdata:/var/lib/...volumes:Named volumes are also declared at the top level
-v ./data:/datavolumes:Bind mount; relative to the Compose file
--restart unless-stoppedrestart: unless-stopped
--network mynetnetworks:Declare the network at the top level too
--health-cmd, --health-intervalhealthcheck: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.

BASH
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 yes

Converted, they become one file with two services:

YAML
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:yy values 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 ./data) doesn't need one.
  • A health check written as --health-cmd "…" runs in a shell, so it becomes CMD-SHELL in 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 .env file next to compose.yaml, add .env to .gitignore, and reference them:

YAML
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=app

Compose reads .env from the project directory automatically when it substitutes ${…} values. Commit an .env.example with placeholder values so others know what to set. DevSnip Pro's .env Checker & Generator compares the two and generates .env.example for you.

Check it, then start it

BASH
docker compose config
docker compose up -d
docker compose ps

docker 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://db:5432, not localhost:5432. From your own machine, the published ports still work on localhost.

Do it in VS Code

  1. Copy the docker run commands from the README. You can convert several at once, one after another.
  2. Run DevSnip Pro: docker run → Compose, or search for "compose" in the DevSnip Pro tools sidebar with Ctrl/Cmd+K.
  3. Paste the commands, or take them from the active editor. The compose.yaml updates as you type, with a count of services and warnings, such as inline secrets.
  4. Save it as compose.yaml in your project, then run 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.

Try it in your own editor

Free, no account, runs locally. Requires VS Code 1.93+ on Windows, macOS or Linux.

code --install-extension sayaib.hue-console