Compose ↔ docker run
WebEverything runs locally in your browser — nothing is uploaded
Both directions work: paste a compose `services:` section to get `docker run` commands, or paste a `docker run` command to get a compose snippet. The kind of input is detected automatically. ⚠️ But the two formats are not equally expressive, so the conversion cannot be complete. That is the single most important thing to know before using this: · `depends_on`, `deploy` (replicas, resource limits), `profiles`, `extends` — compose has them, and `docker run` has nothing corresponding. Replicas especially: `docker run` starts exactly one container, and “three replicas” does not exist as a concept in a single command. · `${VAR}` interpolation, the merge order of `env_file` and `.env`, and the base directory for relative paths (the compose file’s directory versus the current directory) — the meaning shifts after conversion, while the result looks entirely reasonable. So the approach here is: convert what maps one-to-one, and list what does not, with the reason. Silently dropping a `deploy` block would suggest that the command is equivalent to the original service when it is not. ⚠️ The other easy trap is argument position in `docker run`: a token starting with `-` after the image is not a docker option, it is an argument to the command inside the container (the `-g` in `docker run nginx -g "daemon off;"` belongs to nginx). Splitting by position means the command survives intact. Everything runs in your browser. Need to plan Docker’s address pools and subnets (the `default-address-pools` / `bip` in `daemon.json`)? That is a separate tool: “Docker Subnet Planner”.
Features
- Both directions detected automatically: a compose services section ↔ a complete docker run command
- image, container_name, ports, volumes, environment, env_file, command, entrypoint, restart, network_mode, working_dir, user, hostname
- Switches: privileged, read_only, tty, stdin_open
- A healthcheck test array becomes --health-cmd, along with interval, timeout and retries
- Short and long port forms (target / published / protocol); non-tcp gets its suffix
- Long volume form (source / target / read_only) becomes `-v src:dst:ro`
- ⚠️ depends_on, deploy, profiles and extends are listed individually, with the reason there is no counterpart
- ⚠️ build, multiple networks, named volumes and empty `KEY=` values are flagged as places where the meaning shifts
- ⚠️ Unrecognised docker options are reported honestly rather than folded into the result
- ⚠️ Trailing line continuations are handled — commands copied from `docker ps` or the docs all carry them
- ⚠️ Arguments after the image are split off as the command, so `-g` and friends are not dropped as docker options
- Runs entirely in your browser
How to use
- Paste a compose services section, or a docker run command
- Optionally name a single service to convert
- Read the command or snippet first, then the “what did not carry over” and “where the meaning shifts” sections
FAQ
- Why did some configuration not carry over?
- Because it has no counterpart in `docker run`. `deploy` is the clearest case: it configures replica count, resource limits and rolling-update policy, which belong to the orchestration layer, while `docker run` starts one container — “three replicas” simply does not exist in a single command (that takes `docker service` or an orchestrator). `depends_on` (start order) and `profiles` (gating) are the same. Quietly dropping what cannot be expressed suggests the command is equivalent to the original service, and you discover otherwise when you deploy with it.
- Why can relative paths end up wrong after converting?
- Because the two resolve against different directories: a relative path in compose is resolved against the compose file’s directory, while arguments on a `docker run` command line resolve against the current working directory. The entry `./site:/usr/share/nginx/html` means `/srv/app/site` when the compose file lives at `/srv/app/docker-compose.yml`, and means wherever you happen to be when you run the converted command elsewhere. The command looks identical; it mounts something else.
- Why do `-d` and `--rm` disappear?
- Because they are not part of a service definition in compose. `-d` (run detached) corresponds to `docker compose up -d`, which is a command-level flag and would be meaningless on an individual service, and `--rm` has no compose service key either. Their absence is correct: in compose terms they should not have been there.
- Why was the `-g` after the image not dropped as an option?
- Because docker’s grammar is `docker run [OPTIONS] IMAGE [COMMAND]`, and everything after the image is the command run inside the container. The `-g` in `docker run nginx -g "daemon off;"` is an nginx argument, not a docker switch. Splitting by position keeps it in the command; without that, it would be discarded as an unrecognised docker option while the compose file still looked complete.
- Can it convert to Podman or Kubernetes?
- No — this does compose and `docker run` only. Converting to Kubernetes is a different order of problem: how a Deployment splits into Services, ConfigMaps and Secrets depends on how your cluster is organised, so it is not a one-to-one mapping. YAML produced that way would run, and be hard to maintain.
- Where is the daemon.json address pool planning?
- In a separate tool, “Docker Subnet Planner”. This one only converts between compose and `docker run`: a service-orchestration file on one side, a single run command on the other. Address pools (`default-address-pools`) and docker0’s `bip` are daemon-level settings with no counterpart in a container’s run command, so they live in their own tool rather than mixing two different jobs on one page.
Related tools
Docker Subnet Planner
WebPlan Docker default-address-pools and bip: pick a prefix from containers per network, list subnets with usable addresses, and flag overlaps.
JSON Formatter
FormatFormat, validate and minify JSON in a collapsible tree with syntax highlighting and line numbers. Search, edit, delete or convert to Python dicts.
YAML Converter
FormatConvert YAML to JSON and back: multi-document files, anchors and merge keys, exact big integers, parse errors with a line and column.
Path Converter
WebGet the Windows, forward-slash, WSL (/mnt/c) and Git Bash (/c) forms of a path at once, with the trailing slash kept exactly. All in your browser.
URL Parser
WebParse a URL into scheme, host, port, path, query parameters and fragment, with each parameter shown raw and decoded. Runs entirely in your browser.
User-Agent Parser
WebParse a user agent into browser, version, OS, device type and engine, and see which rules matched. Pattern matching only. Runs entirely in your browser.