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.

IndieKit — Ship your Next.js startup in days.affiliate