Docker Run to Compose Converter
Turn a docker run command into a docker-compose.yml — ports, volumes, environment and limits mapped for you.
services:
web:
image: "nginx:1.27-alpine"
container_name: web
ports:
- "8080:80"
- "8443:443"
environment:
TZ: Asia/Seoul
volumes:
- "./site:/usr/share/nginx/html:ro"
- "nginx-cache:/var/cache/nginx"
restart: unless-stopped
volumes:
nginx-cache:
- -d is not a file setting. Start the stack with docker compose up -d instead.
How to use
- Paste a docker run command — line continuations, quoted arguments and --flag=value forms all parse.
- Change the service name if you want something other than the container name or the image name.
- Copy the YAML into docker-compose.yml, then read the notes for anything that could not be expressed as a file setting.
About this tool
ShowHide
Paste the docker run command from a project's README and get the equivalent docker-compose.yml back. Ports, bind mounts and named volumes, environment variables, labels, capabilities, devices, resource limits and the rest are mapped onto their Compose keys, and the two pieces people forget are handled for you: a named volume gets its own top-level volumes entry, and a network you passed with --network is declared external, because Compose did not create it. The output has no version key, which the Compose Specification dropped years ago and current Docker warns about. Two flags deliberately produce nothing: -d describes how you start the stack rather than what it is, and --rm has no equivalent at all, so both are called out as notes instead of being silently invented. Anything the parser does not recognise is listed rather than dropped quietly, so you can see exactly what still needs a hand.
Frequently asked questions
Why is there no version: line at the top?
Because it has been obsolete since the Compose Specification merged the v2 and v3 formats. Docker Compose v2 ignores the key entirely and prints a warning telling you to remove it, so emitting one would only add a line you have to delete. The absence of a version is what a current file looks like; if you are pasting into an old file that still has one, drop that line at the same time.
Why is my network marked external: true?
Because --network refers to a network that already exists. Compose otherwise creates a network of its own for the project and attaches services to it automatically, so simply naming one would tell Compose to make a second network with that name rather than join the one you meant. Marking it external says the network is managed outside this file and Compose should attach to it as-is. If you would rather let Compose manage it, delete the networks block entirely — the default network it creates already lets your services reach each other by service name.
What happens to -d and --rm?
Neither becomes a file setting, and both are reported as notes rather than quietly dropped. -d is not a property of the container at all — it describes how you launched it, and the Compose equivalent is to run docker compose up -d. --rm has no counterpart: Compose deliberately keeps a stopped container so you can read its logs and restart it, which is the opposite of what --rm asks for. The nearest behaviour is docker compose run --rm for a one-off container that cleans up after itself.
Why are the ports and some values in quotes?
Because YAML would otherwise read them as something else. An unquoted 22:22 is a sexagesimal number in YAML 1.1, which several tools still parse, and it would arrive as 1342 rather than a port mapping. The same trap catches environment values: yes and no become booleans, 1.10 becomes the float 1.1 and loses its trailing zero, and a value containing a colon breaks the mapping. Anything that could be misread is quoted, and anything safe is left bare so the file stays readable.
Which flags are not handled?
The ones with no clean single-key mapping — --gpus, --sysctl, --ulimit, --health-cmd and its siblings, --mount in its long comma-separated form, --link, and anything newer than this page. They are listed under the notes with their names, so nothing disappears without telling you. Health checks and ulimits do exist in Compose but take a nested block rather than a scalar, so they are worth adding by hand rather than guessing at from a flag.
Related tools
Base64 to Hex Converter (and back)
Convert a Base64 string to hexadecimal bytes and hex back to Base64, with URL-safe support, in your browser.
Developer
cURL to fetch / axios Converter
Paste a cURL command — get ready-to-use JS fetch or axios code with headers, body, method, and basic auth handled.
Developer
HTML → JSX Converter
Paste an HTML snippet and get React-ready JSX — class becomes className, onclick becomes onClick, and void tags self-close.
Developer
JSON to Go Struct Converter
Turn a JSON object into a typed Go struct with json tags, instantly in your browser.
Developer
JSON to Python Dataclass Converter
Turn a JSON object into Python @dataclass definitions with type hints, in your browser.
Developer
JSON to Rust Struct Converter (serde)
Turn a JSON object into Rust structs with serde derives and type-mapped fields, in your browser.
Developer