Skip to content
RunStack
docker run ↔ Compose

docker run ⇄ docker compose converter

Paste one or more docker run commands to get compose.yaml, or the other way round. Anything that does not convert is listed separately.

PrivacyConversion runs in your browser: commands and environment variables are not sent to a server.

compose.yamlservices: 2

services:
  app:
    image: ghcr.io/example/app:1.4.2
    container_name: app
    restart: unless-stopped
    environment:
      NODE_ENV: production
      DATABASE_URL: postgres://app:secret@db:5432/app
    ports:
      - "8080:3000"
    volumes:
      - app_uploads:/app/uploads
    networks:
      - backend
    healthcheck:
      test:
        - CMD-SHELL
        - wget -qO- http://localhost:3000/health || exit 1
      interval: 30s
    mem_limit: 512m
    cpus: 1
  db:
    image: postgres:16-alpine
    container_name: db
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - backend
volumes:
  app_uploads: {}
  pgdata: {}
networks:
  backend:
    external: true

Not converted or needs attention

  • networksCustom networks are declared external: true — they must already exist (docker network create). Drop external to let Compose create them.

What is supported

Ports, volumes (-v and --mount: bind, volume, tmpfs), env vars and --env-file, --restart, networks with aliases and fixed IPs, healthcheck, logging, memory and CPU limits, --gpus, ulimit, sysctl, capabilities, devices, --entrypoint and the command after the image. Named volumes go to the volumes section, custom networks to networks. No version key is added: it is obsolete in Compose v2.

After converting

Check the result with docker compose config — it prints the final configuration with variables filled in. Move passwords from -e into a .env file next to compose.yaml, reference them as ${DB_PASSWORD}, and keep .env out of git.

FAQ

Which docker run flags are not converted?

Those with no Compose equivalent: --rm, -P (--publish-all), --cidfile, --sig-proxy, --label-file and similar. They are listed under the result. -d is not needed: docker compose up -d runs services in the background.

Why are networks marked external: true?

A custom network in docker run (--network backend) already exists and was created by hand. With external: true Compose attaches to it instead of creating a new one with the project prefix. Drop external if the network should belong to the project.

What about $HOME and passwords containing $?

Variables that were unquoted or in double quotes stay variables — Compose fills them from the environment or .env. A $ that was literal in the shell (single quotes or escaped) is written as $$ so Compose does not interpolate it.

Why does the reverse conversion create an app_default network?

Compose puts services on a shared project network where they resolve each other by name. Plain docker run uses the bridge network without name resolution, so for several services a docker network create and --network are added to keep links such as db:5432 working.