Why the translation matters
Ad-hoc docker run commands grow into unmaintainable one-liners: five flags become fifteen, and nobody remembers why --shm-size was set. Docker Compose files are the answer, but translating flags by hand is error-prone — the naming doesn't map one-to-one. This guide is the mapping.
Flag-to-YAML translation table
| docker run flag | compose.yaml |
|---|---|
--name myapp | container_name: myapp |
-p 8080:80 | ports: ["8080:80"] |
-v /data:/var/lib/app | volumes: ["/data:/var/lib/app"] |
-e KEY=value | environment: [KEY=value] or a map |
--env-file .env | env_file: .env |
--restart unless-stopped | restart: unless-stopped |
-d | (default — compose detaches) |
--network host | network_mode: host |
--link redis | service name + depends_on |
-m 512m --cpus 1.5 | deploy.resources.limits or mem_limit/cpus |
-u 1000:1000 | user: "1000:1000" |
A worked example
This run command:
docker run -d --name gateway -p 80:8080 -e LOG_LEVEL=info \
-v ./config:/etc/gateway --restart unless-stopped \
--link redis myrepo/gateway:2.4
becomes:
services:
gateway:
image: myrepo/gateway:2.4
container_name: gateway
ports: ["80:8080"]
environment:
LOG_LEVEL: info
volumes:
- ./config:/etc/gateway
restart: unless-stopped
depends_on:
- redis
redis:
image: redis:7
Common mistakes
--linkis deprecated. In Compose, services on the same network reach each other by service name — no links needed.- Volume paths are relative to the compose file, not your shell's working directory.
- Quoting:
ports: ["8080:80"]must be quoted or YAML parses it as a base-60 sexagesimal number. - Healthchecks: the
--health-cmdflag maps to ahealthcheck:block, anddepends_onshould usecondition: service_healthyto wait for readiness.
Paste any docker run command into the Docker to Compose converter to get a ready-to-use compose.yaml — conversion is entirely client-side.