Guide
Converting docker run commands into a Compose file
Project READMEs and tutorials love long docker run commands with a dozen flags. They work, but they are hard to read, easy to mistype and impossible to review in a pull request. Docker Compose describes the same containers in a YAML file you can commit and start with docker compose up -d. This converter reads one or more docker run commands and writes that file.
Why Compose
A Compose file keeps every setting in one place under version control, starts several containers with one command and in dependency order, puts them on a shared network where they find each other by name, and makes changes reviewable. Rebuilding an environment on a new machine becomes a clone and a single command instead of copying commands from a wiki.
How flags map to keys
Each command becomes a service named after --name, or after the image when there is no name. -p becomes ports, -v becomes volumes, -e becomes environment and --env-file becomes env_file. --restart, --network, -w (working_dir), -u (user), --label and --entrypoint have direct equivalents. Memory and CPU limits from --memory and --cpus go under deploy.resources.limits, and the --health-cmd, --health-interval and related flags become a healthcheck block. Anything after the image name is the container’s command, written as a JSON-style array so arguments with spaces survive.
Volumes and networks
A volume source without a path, such as pgdata:/var/lib/postgresql/data, is a named volume, so it is also declared in the top-level volumes section, where Docker creates it on first start. Bind mounts like ./uploads:/app/uploads are left as they are. A user-defined --network is declared at the top level with external: true, because a docker run command assumes the network already exists.
Quoting in YAML
YAML guesses types, which can bite. A port mapping like 22:22 may be read by YAML 1.1 parsers as a base-60 number, and values such as true, no or 3000 would become booleans or numbers. The converter quotes values that could be misread, so "8080:3000" and environment values reach Compose as the strings you wrote. The obsolete top-level version: key is left out, because Compose v2 ignores it.
A worked example
The Sample has two commands: a PostgreSQL 16 database and a web app. The output has services: with db and web. The database keeps its environment variables, health check (pg_isready -U app every 10s), restart policy and the port 127.0.0.1:5432:5432, so it is reachable only from the host. The web service gets the port "8080:3000", the bind mount ./uploads:/app/uploads, env_file: .env, the command ["node","server.js","--port","3000"] and limits of cpus: "1.5" and memory: 512m. At the bottom, pgdata is declared as a volume and appnet as an external network.
Flags that need attention
Some options have no direct key or change meaning in Compose. --mount long syntax, --network-alias and rarely used flags such as --cgroup-parent are reported in a warning instead of being guessed. --rm gets a note, because docker compose down removes containers anyway, and -it is dropped since services run in the background. Options such as --sysctl, --ulimit, --pid and --stop-signal are translated to their Compose keys. Check deploy limits on older Docker versions, and remember that secrets in environment end up in the file; move them to an .env file that stays out of Git.
Related tools
- Dockerfile Generator builds the image the web service runs.
- .env Converter turns a .env file into an environment block.
- Kubernetes YAML Generator is the next step when Compose is not enough.
- YAML to JSON checks that the file parses as you expect.
Checked against the current version of the docker run to Compose on .

