DEV Community

octave Nkurunziza
octave Nkurunziza

Posted on Originally published at blog.hubfly.space

Deploy a docker-compose.yml as-is: 8 platforms, which keys survive, and what web + Postgres + Redis costs

Originally published on the Hubfly blog.

TL;DR

  • What you get: which platforms take your docker-compose.yml without a rewrite, which Compose keys survive, and a monthly price for the same 3-service stack (web + Postgres + Redis) on 8 platforms.
  • Who it's for: you have a Compose file that works on your laptop and you want it online without learning a new config format.
  • Time: 10 minutes to read. 2 minutes to try it on Hubfly.
  • Short answer: Hubfly runs the file as-is; Coolify's docs say it runs Compose natively; Railway imports it (some keys may not carry over). Render, DigitalOcean App Platform, Heroku and Koyeb want a rewrite. Cheapest always-on stack: about $6–12/month if you run Postgres yourself, $15–27 if you want them managed.

The problem: your Compose file works, until you try to host it

You have docker compose up working. Web, Postgres, Redis, a healthcheck, two volumes. Then you pick a host, and it wants a render.yaml, an app spec, a fly.toml or three separate services clicked together by hand.

Most "deploy Docker Compose" guides skip the two questions that matter. Will my file run unchanged? And what will the whole stack cost per month, not just the web box?

This post answers both, from each platform's docs and pricing page, plus a real Compose deploy on Hubfly with a stopwatch.

The reference stack

One small web service that waits for a healthy Postgres and a healthy Redis. Both data services have named volumes. A bind mount is included on purpose, to show what a platform does with it.

services:
  web:
    image: traefik/whoami:v1.10
    ports:
      - "80:80"
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy
    volumes:
      - ./static:/srv:ro        # bind mount, on purpose
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: change-me   # use a secret in real life
      POSTGRES_DB: app
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 3s
      retries: 10
    volumes:
      - pgdata:/var/lib/postgresql/data
  cache:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10
    volumes:
      - redisdata:/data
volumes:
  pgdata:
  redisdata:
Enter fullscreen mode Exit fullscreen mode

Which platforms take a Compose file?

Docs and pricing pages are linked in each row and in the price table below. "As-is" means you hand over the file, not a translation of it.

Platform Compose support How What the docs say about keys
Coolify (self-hosted) Yes, native Git repo or "Raw" mode build:, named volumes, healthchecks supported; bind mounts only inside the resource folder; avoid ports: (docs)
Hubfly Yes, native Paste or upload YAML in the Stack Composer Walkthrough below: depends_on conditions, healthchecks, named volumes, command, ports kept; bind mount dropped
Railway Yes, import Drag the file onto the project canvas Railway says it doesn't support every Compose config yet; per-key list not published (docs)
Fly.io Early [build.compose] in fly.toml Announced in a community post (July 2025), not in the main docs; many features listed as incompatible (post)
Render No Rewrite as a render.yaml Blueprint Compose isn't in the Blueprint spec; the feature request dates from 2019
DigitalOcean App Platform No App spec, from Git or images Compose not listed (support page)
Koyeb Workaround Docker-in-Docker in one privileged service Official tutorial uses the Privileged toggle; no native import
Heroku No Git or Docker deploys Compose isn't offered on the pricing page

Fair warning for every row: "supports Compose" never means every key. Swarm-only deploy: blocks, host networking and bind mounts are where files usually break.

Hubfly, step by step

Hubfly Stack Composer after importing the Compose YAML: 3 services, 2 volumes, $0.02 monthly estimate
The Stack Composer after pasting the YAML: 3 services, 2 volumes, monthly estimate $0.02.

  1. Import. Create → Compose Stack → YAML tab → paste → Import YAML. It loaded in under a second.
  2. What survives. Read the generated spec (JSON tab):
    • depends_on with condition: service_healthy → kept on web for both db and cache.
    • Both healthcheck blocks → kept, with interval, timeout and retries.
    • Named volumes → 2 volumes of 1 GB each, mounted at the right paths.
    • command: on Redis → kept.
    • ports: "80:80" → container port 80 exposed.
    • The bind mount ./static:/srv:ro → silently dropped. No warning in the composer. If your app needs files from the host, bake them into the image or use a volume.
  3. Deploy. Click Deploy Stack. "Stack deployment finished" arrives in about 79 seconds for 3 services and 2 volumes (the deploy page timer, which starts after validation, shows about 1 min 17 s).
  4. Order. The log is the useful part:
    • db deployed (10:54:10), then cache (10:54:26).
    • "Waiting for 'db' before deploying 'web'" → "Service condition satisfied" 2 s later.
    • Same for cache 3 s later. Then web deployed (10:54:48).

Compose deployment activity log: web waits for db and cache health conditions before deploying
The deploy activity log: web waits for db and cache to become healthy.

One oddity: the composer labels stages in file order. web shows as "Stage 1" even though it deploys last. The real order followed depends_on, so trust the log, not the stage number.

  1. Cost on the dashboard. The project summary projected $0.03/month, with the shared tier's auto-sleep on.

Project billing panel: projected cost $0.03 per month against a $10 monthly cap
Project Settings → Billing & Monthly Budget: projected $0.03/mo against a $10 cap.

The composer shows $0.02, the project page $0.03. The gap is most likely the storage class: the volumes were created as Balanced (1.5× the standard rate). 2 GB × $0.00001536 × 1.5 × 730 h = $0.034, which rounds to $0.03; at the standard rate it's $0.022. Shared-tier compute shows as free here. Treat that as a dev and staging number, not a production price.

  1. Cleanup. Project Settings → Danger Zone → Delete All Resources, then Delete Project. The whole run takes about 7 minutes.

What the same stack costs, platform by platform

Assumptions: always on, 730 hours a month, the smallest paid size each platform sells for web, Postgres and Redis, 1 GB of data each, no egress. Usage-based platforms are priced at 0.5 vCPU + 512 MB per service (or the nearest size), which is a ceiling, not an average.

Platform Web Postgres Redis Monthly total Managed DB? Pricing page
Coolify + Hetzner CX23 one box on the box on the box $6.49 + IPv4 ($11.49 + IPv4 with Coolify Cloud) No, you run it Hetzner, Coolify
Hubfly (dedicated, always on) $2.19 $2.19 + volume $2.19 + volume ≈ $6.67 No, containers + volumes Hubfly pricing, math below
Fly.io, self-run DBs $3.69 $3.69 + $0.15 vol $3.69 + $0.15 vol $11.37 (+$2 for a dedicated IPv4) No Fly pricing
Heroku $7 Basic $5 Mini $3 Mini $15 Yes Dynos, Postgres + Key-Value
Render $7 $6 $10 Key Value $23 Yes Render pricing
DigitalOcean App Platform $5 $7 Dev DB $15 Valkey $27 ($35.15 with a full managed Postgres) Yes App Platform, Valkey, Databases
Koyeb $5.36 micro $30.26 (Small $29.76 + 1 GB at $0.50) $1.61 eco-nano, self-run $37.23 (a plan fee may apply; check the pricing page) Postgres yes Instances, Postgres pricing
Railway $15 $15 + $0.15 vol $15 + $0.15 vol up to ≈ $45.30 No, services you run Plans
Fly.io, managed $3.69 $38.28 MPG Basic $10 Upstash fixed $51.97 Yes Fly pricing, Upstash on Fly

How to read Railway's row: it bills real usage, per second. $45.30 assumes all three services use their full 0.5 vCPU and 512 MB around the clock ($20/vCPU-month × 0.5 + $10/GB-month × 0.5 = $15 each). An idle side project uses far less, and the $5 Hobby fee covers the first $5. An idle Railway bill depends on your app, so it isn't quoted here.

The Hubfly math, so you can check it

Published rates (pricing page): CPU $0.004 per vCPU-hour, RAM $0.002 per GB-hour, storage $0.00001536 per GB-hour, 730 hours a month.

  • One service at 0.5 vCPU / 512 MB: 0.5 × 0.004 × 730 = $1.46 CPU, plus 0.5 × 0.002 × 730 = $0.73 RAM → $2.19.
  • Three services: 3 × $2.19 = $6.57.
  • Two 1 GB Balanced volumes: 2 × 0.00001536 × 1.5 × 730 = $0.034.
  • Container disk, 2 GB each (the dedicated tier's minimum in the dashboard): 6 × 0.00001536 × 730 = $0.067.
  • Total ≈ $6.67/month.

This row is computed from published dedicated-tier rates.

Where the competitors win (and they do)

  • Managed databases. Heroku, Render and DigitalOcean run Postgres and Redis for you. If you'd rather never think about Postgres upgrades or restores, the $15–27 tier is worth it. Render's $6 Postgres includes point-in-time recovery on the Hobby workspace, per its pricing page. On Hubfly, Coolify and self-run Fly, Postgres is a container you own, and backups are your job.
  • Coolify runs Compose closest to raw, including build: from your repo, and one flat-priced server. You also patch that server yourself.
  • Railway's import is drag-and-drop: drop the file on the canvas and review the staged services (docs).
  • Fly's 256 MB Machine is $2.19/month, and Fly lists 17 regions in its pricing selector, against Hubfly's 3. Koyeb's eco-nano ($1.61) is the cheapest always-on container in this table.
  • Heroku's cheapest managed Postgres + Redis pair costs $8 together, the lowest managed pair in this table.

Where Hubfly fits: your Compose file ran unchanged, depends_on health conditions were respected, and a 3-service always-on stack is about $6.67 by the published rates. The trade-off is that you manage the database containers. Hubfly doesn't document database backups, so schedule your own pg_dump to off-site storage.

What can go wrong

  1. Your bind mounts disappear. Hubfly dropped ./static:/srv:ro without a warning, and Coolify restricts them to the resource folder. Fix: COPY the files into the image, or use a named volume.
  2. The app starts before the database is ready. depends_on without a condition only waits for the container to start. Fix: add a healthcheck and condition: service_healthy, as above. For migrations, gate the app on a one-shot job (see the migration job guide).
  3. 502 after a "successful" deploy. Your app is listening on 127.0.0.1 inside the container. Fix: bind to 0.0.0.0 (1-line fix).

Bonus trap: a hard-coded POSTGRES_PASSWORD in Compose is fine on a laptop and bad in a repo. Use the platform's secret or encrypted env vars.

Try it yourself

  1. Create a Cell project with a $10 budget cap (Advanced Options at project creation).
  2. Create → Compose Stack → YAML → paste the file above (change the password) → Import YAML.
  3. Check the JSON tab to see what survived. Deploy Stack and watch the activity log.
  4. Delete All Resources, then Delete Project when you're done.

For competitor prices, open the linked pricing pages: prices change.

Takeaway

If you want your Compose file to run with no rewrite, your real shortlist is Coolify (your own server) or a platform with native import like Hubfly or Railway. If you want managed Postgres and Redis and don't mind translating your file, Heroku ($15) and Render ($23) are the honest picks.

Next: Canary releases with a weighted load balancer, once your stack is live and you want to ship v2 safely.

Price your own stack: open the Hubfly pricing calculator, set 3 dedicated services at 0.5 vCPU / 512 MB, and compare with the table above.

Top comments (0)