Docker/Podman Composer — Examples
Hands-on conversions: nginx to Compose, volumes/ports/env, a multi-flag command, the Compose→Run reverse direction, and a podman example.
Back to the overview: Docker/Podman Composer · Open the tool live: www.jpkc.com/tools/docker/
The manual explains both directions and every supported flag in detail. This page shows concrete conversions with input and the actual result. The interface is in English, so tab and button names are given in their original spelling.
Example 1: A simple nginx container (Run → Compose)
The classic — a short run command becomes a Compose file. Input in the Run → Compose tab:
docker run -d --name web -p 8080:80 nginx:alpineAfter clicking Convert to YAML:
services:
web:
image: nginx:alpine
container_name: web
ports:
- 8080:80Note: the -d (detach) disappears — it's implicit in Compose. The service name web comes from --name; without --name, the tool would have derived it from the image (nginx).
Example 2: Volumes, ports, environment, and a health check
A realistic database container with several flag types. Input:
docker run -d \
--name db \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
-p 5432:5432 \
--restart unless-stopped \
--health-cmd "pg_isready -U postgres" \
--health-interval 10s \
--memory 512m \
postgres:16Result:
services:
db:
image: postgres:16
container_name: db
restart: unless-stopped
ports:
- 5432:5432
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=secret
mem_limit: 512m
healthcheck:
test:
- CMD-SHELL
- pg_isready -U postgres
interval: 10sTwo things are worth noting: the --health-cmd becomes a test list in CMD-SHELL form, and --memory lands as mem_limit. The quoted health-check command stays a single argument thanks to the tokenizer.
Example 3: A multi-flag command with combined short flags
Here combined flags and a trailing command come into play. Input:
docker run -it --rm -p 3000:3000 node:20 bashResult:
services:
node:
image: node:20
tty: true
stdin_open: true
ports:
- 3000:3000
command: bashWhat happens here: -it is split into -i and -t, yielding stdin_open: true and tty: true. The --rm is discarded (it has no Compose equivalent), and a -d would have vanished too. The bash after the image name becomes the command. Since no --name is set, the tool derives the service name from the image: node.
Example 4: The full feature set (the Example button)
The Example button in the run tab loads an nginx web server with almost everything at once:
docker run -d \
-p 8080:80 \
-p 443:443 \
-v /var/www:/usr/share/nginx/html:ro \
-v nginx-logs:/var/log/nginx \
-e NGINX_HOST=example.com \
-e NGINX_PORT=80 \
--name webserver \
--restart unless-stopped \
--network mynet \
--label app=webserver \
--label env=production \
--memory 256m \
--health-cmd "curl -fs http://localhost/" \
--health-interval 30s \
--health-retries 3 \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx:1.27-alpineResult:
services:
webserver:
image: nginx:1.27-alpine
container_name: webserver
restart: unless-stopped
ports:
- 8080:80
- 443:443
volumes:
- /var/www:/usr/share/nginx/html:ro
- nginx-logs:/var/log/nginx
environment:
- NGINX_HOST=example.com
- NGINX_PORT=80
networks:
- mynet
labels:
- app=webserver
- env=production
mem_limit: 256m
logging:
driver: json-file
options:
max-size: 10m
max-file: "3"
healthcheck:
test:
- CMD-SHELL
- curl -fs http://localhost/
interval: 30s
retries: 3Flags given multiple times (-p, -v, -e, --label, --log-opt) collect into lists or the logging.options block. Note the "3" for max-file: the serializer quotes a pure number meant as a string so YAML doesn't read it as an integer.
Example 5: The reverse direction — Compose → Run with multiple services
Switch to the Compose → Run tab and paste a Compose file with two services:
services:
web:
image: nginx:alpine
container_name: web
ports:
- "8080:80"
restart: unless-stopped
app:
image: node:20-alpine
container_name: app
restart: always
working_dir: /app
volumes:
- ./app:/app
environment:
NODE_ENV: production
PORT: "3000"
ports:
- "3000:3000"
networks:
- mynet
depends_on:
- webAfter Convert to Commands (Runtime: docker), each service gets its own command:
# web
docker run -d \
--name web \
--restart unless-stopped \
-p 8080:80 \
nginx:alpine
# app
docker run -d \
--name app \
--restart always \
--workdir /app \
-p 3000:3000 \
-v ./app:/app \
-e NODE_ENV=production \
-e PORT=3000 \
--network mynet \
node:20-alpineImportant: the depends_on: [web] does not appear in the generated command — docker run has no concept of start dependencies, so it's dropped. A top-level networks: definition with driver options would be ignored too; only the service reference mynet becomes --network mynet. The environment object is unpacked into individual -e KEY=VALUE flags.
Example 6: Generating commands for Podman
The same Compose input, but with podman selected in the Runtime switch. The web service then becomes:
# web
podman run -d \
--name web \
--restart unless-stopped \
-p 8080:80 \
nginx:alpineThe only difference is the command word podman instead of docker — the flags stay the same, because Podman reproduces the docker run options compatibly. Handy when you want to test an existing Compose file by hand on a Podman host.
Going deeper: the manual for every flag, the tips & tricks for the limits and knacks. You can try everything directly in the tool.