Build a docker compose file without fighting YAML
This Docker Compose generator writes a compose.yaml for a typical stack from a few cards: your app built from a Dockerfile, PostgreSQL or MySQL, Redis, MongoDB, nginx in front, RabbitMQ, and development helpers such as Mailpit and Adminer. Each service gets its ports, environment variables, volumes, restart policy, profiles, a health check and depends_on links, and the file follows the current Compose Specification used by docker compose v2.
The point is fewer surprises when you run docker compose up: ports are always quoted (so 22:22 is never read as a base-60 number), environment values such as false or 3000 stay strings, named volumes are declared at the top level, and dependencies on databases wait for service_healthy rather than just “container started”. The generator also checks your input — invalid service names, malformed or duplicated host ports, broken volume syntax, dependency cycles — and warns about example passwords and unpinned latest tags.
Everything happens in your browser; no part of your stack description is uploaded.
How to use the Docker Compose Generator
- Set the Project name (it prefixes container, network and volume names) and the shared Network name, or clear it to use Compose’s default network.
- Use Add a service to append PostgreSQL, MySQL, Redis, MongoDB, nginx, Mailpit, RabbitMQ, Adminer, another app or any custom image. The example starts with app + Postgres + Redis.
- Open a service card and edit its name, image or build context, command, restart policy, profiles, ports, environment and volumes. Tick the services it depends_on.
- Fix anything listed in red; read the yellow warnings (example passwords, unpinned tags).
- Press Copy YAML or Download compose.yaml, put it next to your Dockerfile and run
docker compose up -d.
Docker Compose Generator features
Service templates with sane defaults
Official images with pinned major versions, the right data directories for persistent volumes, and working health checks: pg_isready, mysqladmin ping, redis-cli ping, mongosh and rabbitmq-diagnostics.
Health-aware depends_on
Dependencies use the long syntax: condition: service_healthy when the target has a health check, otherwise service_started, so your app does not boot before the database accepts connections.
Validation before you run it
Service and project names, port mappings (including IP-bound and ranges), host-port collisions between services, volume syntax, environment variable names and dependency cycles are all checked as you type.
Correct YAML quoting
Values that YAML would reinterpret — yes, no, on, numbers, strings containing : or # — are quoted automatically; ports are always written as strings.
Profiles and networks
Mark helpers such as Mailpit or Adminer with a dev profile so they only start with --profile dev, and attach every service to one named bridge network.
Example: what the default stack produces
The starting example is a web app that talks to Postgres and Redis. The generated file declares the pgdata and redisdata named volumes, puts all three containers on the backend network, and makes app wait until both db and cache report healthy. Inside the network, containers reach each other by service name, which is why the app’s DATABASE_URL uses db:5432 rather than localhost.
| Service | Image | Host port | Data volume | Health check |
|---|---|---|---|---|
| app | build: . | 3000 | — | curl -fsS http://localhost:3000/health |
| db | postgres:16-alpine | 5432 | pgdata → /var/lib/postgresql/data | pg_isready -U app -d app |
| cache | redis:7-alpine | 6379 | redisdata → /data | redis-cli ping |
Common docker compose mistakes this avoids
- Unquoted ports. YAML 1.1 parsers read
22:22as the number 1342. Quoted strings are always safe. - Waiting on the wrong thing. Plain
depends_on: [db]only waits for the container to start, not for Postgres to accept connections. - Publishing database ports in production. Remove the
portslines of internal services (or bind them to127.0.0.1:) — other containers reach them over the network anyway. - Secrets in the file. Replace
change-mevalues with${POSTGRES_PASSWORD}and keep the real values in an.envfile next tocompose.yaml; the .env converter helps you produce one. - The obsolete version key.
version: "3.8"is ignored by Compose v2 and prints a warning; the generator leaves it out.
Next steps
Need the image for the app service? The Dockerfile Generator writes a multi-stage Dockerfile for Node, Python, Go, Java, PHP, Ruby or Rust. For the nginx service, generate its nginx.conf with the nginx config generator in reverse-proxy mode with http://app:3000 as the upstream. To tidy or convert an existing compose file, use the YAML Formatter.
Docker Compose Generator FAQ
Is the output a docker-compose.yml or compose.yaml?
Either name works. compose.yaml is the preferred name in the Compose Specification; docker compose also finds docker-compose.yml. Rename the downloaded file if your tooling expects the older name.
Why does the Docker Compose generator not write a version line?
Compose v2 implements the Compose Specification, which made the top-level version field obsolete. Including it only produces a warning.
How do containers in the same compose file talk to each other?
By service name on the shared network: the app connects to db:5432 or redis://cache:6379. Published ports are only for access from your host machine.
What does a profile do?
A service with profiles: [dev] is skipped by docker compose up and started only with docker compose --profile dev up. It is a tidy way to keep mail catchers and admin UIs out of production.
Why is $$ used in the MySQL health check?
Compose interpolates $VAR from your shell or .env file when it reads the file. $$ escapes the dollar sign so the variable is expanded inside the container instead.
Can I validate an existing compose file here?
This tool generates files from its form rather than importing them. For an existing file, run docker compose config, which prints the fully resolved configuration or the exact error.