Skip to content
ZeroServer.tools

Docker Run to Docker Compose Converter

Convert any single-line 'docker run' CLI command into a clean, formatted docker-compose.yml file.

Presets:
services:
  webserver:
    image: nginx:latest
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /data:/app/data
    environment:
      - NODE_ENV=production
      - PORT=3000

Service Name

webserver

Exposed Ports

2

Volume Mounts

1

Environment Variables

2

How docker run to docker-compose conversion works

Paste a docker run command and get a ready-to-use docker-compose.yml file. The converter parses all common flags: -p (ports), -v (volumes), -e (environment variables), --name (container_name), --network, and --restart. The -d flag is intentionally omitted — compose always runs detached. The service name defaults to the image name. Use this to migrate one-liner scripts to a reproducible Compose workflow.

Built and maintained by Meet Shah · Last updated

What this tool is used for

  • Turning a long docker run command into a checked-in compose file.
  • Capturing an ad-hoc container's flags before you forget them.
  • Converting a README's run command into something reproducible.
  • Producing a starting compose file you then extend with more services.
  • Seeing which run flags have no compose equivalent.

Frequently Asked Questions

Why convert a docker run command at all?
Because the command is ephemeral and a Compose file is a record. A long `docker run` lives in someone's shell history; the same thing in `docker-compose.yml` is reviewable, diffable, and can be started by anyone with `docker compose up` without reconstructing twelve flags correctly.
How are -p and -v flags translated?
Into the `ports` and `volumes` lists, preserving the `host:container` order. That order is the one people reverse most often — `-p 8080:80` means port 8080 on the host maps to 80 in the container, and swapping it produces a container that starts fine and serves nothing.
What is the difference between a named volume and a bind mount?
`-v pgdata:/var/lib/postgresql/data` is a named volume Docker manages; `-v /data:/app/data` bind-mounts a host path. Both become `volumes` entries, but a named volume additionally needs a top-level `volumes:` declaration, which is the step most hand-written conversions forget.
Do I still need the version key?
No. The Compose Specification dropped it, and current versions of `docker compose` warn that it is obsolete. It remains available here because plenty of CI systems still run older Compose v1, which does require it.
How is the command parsed?
With a real POSIX argument splitter rather than a split on spaces — it handles quoting, escapes, line continuations and adjacent concatenation. That matters because a command with `-e MESSAGE="hello world"` in it becomes two tokens under a naive split and one environment variable under a correct one.

Common errors and gotchas

  • Losing the network the container was on, which compose creates differently by default.
  • Converting a bind mount's host path literally, which then only works on your machine.
  • Assuming restart behaviour carries over, which run and compose express differently.
  • Leaving secrets in environment values that are now committed to a file.
  • Expecting the container name to be preserved, when compose derives its own.

Related Developer Utilities tools

Private & free — this tool runs entirely in your browser.

IndieKitShip your Next.js startup in days.affiliate