DevTools Logo

Docker Compose Builder

Docker Compose Builder

Describe your services in a form and get a valid, correctly-indented docker-compose.yml — generated in your browser.

2 services configured

Service: web

Service: db

    Examples

    Default two-service stack (nginx + postgres)

    Input
    service web:
      image:    nginx:latest
      ports:    80:80
      restart:  unless-stopped
      depends:  db
    
    service db:
      image:        postgres:16
      volumes:      pgdata:/var/lib/postgresql/data
      environment:  POSTGRES_PASSWORD=secret
                    POSTGRES_DB=app
      restart:      unless-stopped
    Output
    services:
      web:
        image: nginx:latest
        ports:
          - "80:80"
        depends_on:
          - db
        restart: unless-stopped
      db:
        image: postgres:16
        volumes:
          - pgdata:/var/lib/postgresql/data
        environment:
          - POSTGRES_PASSWORD=secret
          - POSTGRES_DB=app
        restart: unless-stopped
    
    volumes:
      pgdata:

    The builder quotes every port mapping so a value like `8080:80` is never misread as a number. Named volumes (`pgdata`) are detected by the regex `^[a-zA-Z0-9][\w.-]*$` and collected into a top-level `volumes:` block; bind-mounts that start with `.` or `/` are left inline only.

    Single service — bind-mount, env, command, restart

    Input
    service api:
      image:        node:20-alpine
      command:      node server.js
      ports:        3000:3000
      volumes:      ./data:/app/data
      environment:  NODE_ENV=production
      restart:      always
    Output
    services:
      api:
        image: node:20-alpine
        command: node server.js
        ports:
          - "3000:3000"
        volumes:
          - ./data:/app/data
        environment:
          - NODE_ENV=production
        restart: always

    With one service and no named volumes, no top-level `volumes:` block is emitted. The restart policy is included only when it is not `no`, the command is emitted verbatim, and the environment is written as the list form (`- KEY=value`) so values containing `=` are preserved.

    Three-service stack with a shared dependency chain

    Input
    service api:
      image:        node:20-alpine
      ports:        3000:3000
                    9000:9000
      environment:  NODE_ENV=production
                    DATABASE_URL=postgres://user:pass@db:5432/app
                    REDIS_URL=redis://cache:6379
      depends:      db, cache
      restart:      always
    
    service db:
      image:        postgres:16-alpine
      volumes:      pgdata:/var/lib/postgresql/data
      environment:  POSTGRES_PASSWORD=secret
      restart:      unless-stopped
    
    service cache:
      image:        redis:7-alpine
      volumes:      redisdata:/data
      restart:      always
    Output
    services:
      api:
        image: node:20-alpine
        ports:
          - "3000:3000"
          - "9000:9000"
        environment:
          - NODE_ENV=production
          - DATABASE_URL=postgres://user:pass@db:5432/app
          - REDIS_URL=redis://cache:6379
        depends_on:
          - db
          - cache
        restart: always
      db:
        image: postgres:16-alpine
        volumes:
          - pgdata:/var/lib/postgresql/data
        environment:
          - POSTGRES_PASSWORD=secret
        restart: unless-stopped
      cache:
        image: redis:7-alpine
        volumes:
          - redisdata:/data
        restart: always
    
    volumes:
      pgdata:
      redisdata:

    Multiple ports are split on newlines or commas into separate list items. The `dependsOn` field is tokenised the same way and emitted as a YAML list. Named volumes `pgdata` and `redisdata` are gathered and emitted under a single `volumes:` block at the bottom of the file.

    About this tool

    docker-compose.yml is easy to break: YAML is indentation-sensitive, an unquoted port mapping can be misread, and a mis-nested key can stop a whole stack from coming up. This builder lets you describe services in a form and generates correctly-indented, spec-compliant Compose YAML you can drop straight into a project.

    Add as many services as you need and configure the image, published ports, bind-mount and named volumes, environment variables, a restart policy, a command override and depends_on relationships. The tool quotes port mappings so values like 8080:80 aren't misread, collects named volumes into the top-level volumes: block automatically, and follows the modern Compose specification (no obsolete version: key). The YAML updates live and everything is generated in your browser.

    How to use

    1. Add your services

      Create a service per container and set its image (e.g. nginx:latest, postgres:16).

    2. Configure each service

      Add ports, volumes, environment variables, a restart policy and depends_on links.

    3. Watch the YAML build

      The docker-compose.yml regenerates live as you edit, with named volumes gathered automatically.

    4. Copy or download

      Copy the YAML or download docker-compose.yml ready to run with docker compose up.

    Use cases

    Scaffolding a local dev environment

    Add a web, api, db and cache service, paste the published ports and bind-mounts you need, and run `docker compose up` — the builder produces a single, correctly-indented YAML file ready to commit.

    Translating a manual YAML into a reproducible form

    When a docker-compose.yml has grown by hand-edits, paste the same services into the builder, save the result, and diff it against the original to catch unquoted ports and stray tabs that YAML parsers don't always accept.

    Building a minimal smoke-test stack

    Two services — one app, one database — with no bind-mounts, no named volumes, and `restart: no` is enough to verify a Docker image works locally. The builder makes that one-screen configuration effortless.

    Documenting a deployment topology

    Express a known stack as a Compose file once and keep it in the repo; readers can run the same services locally to reproduce a staging or production setup.

    Per-service options

    FieldCompose key
    Imageimage:
    Portsports: (quoted host:container mappings)
    Volumesvolumes: (bind mounts + named volumes)
    Environmentenvironment: (KEY=value list)
    Restartrestart: (no / always / on-failure / unless-stopped)
    Depends ondepends_on: (startup ordering)

    Follows the current Compose spec — no obsolete version key.

    Common mistakes

    Mistake:Writing unquoted port mappings like `8080:80` and getting a YAML parse error.

    Fix:Unquoted, `8080:80` is parsed by some YAML loaders as the sexagesimal number `8080:80` (≈ 8,080 × 60 + 80). The builder always quotes port mappings (`- "80:80"`) — trust the output and don't strip the quotes.

    Mistake:Listing a bind-mount (`./data:/app/data`) as a named volume.

    Fix:The builder decides by prefix: `./` and `/` mean a host bind-mount, anything else is a named volume. Use `./data` or an absolute path to keep the source on the host, and only use bare identifiers when you want Docker to manage the volume.

    Mistake:Adding a `version: '3'` key to the top of the YAML.

    Fix:The current Compose spec deprecates the `version` key — it is ignored by `docker compose` and triggers a warning in modern installs. The builder deliberately omits it; don't add it back when you hand-edit the file.

    Mistake:Forgetting to set `restart: unless-stopped` on a long-running service.

    Fix:Without a restart policy, a service that crashes stays down until you `docker compose up` again. The builder defaults to `no`, so any production-style service needs an explicit `always`, `on-failure` or `unless-stopped`.

    Frequently asked questions

    References & standards