Last updated 7 August 2026
Packaging an application as a container image is the point at which hosting becomes a genuinely portable decision. Every platform below takes an image and runs it, so you are no longer choosing a host that supports your language — you are choosing one whose build, registry, networking and storage model fit how you want to work.
That portability is real but not free. The things that break when you move a container between platforms are boringly consistent: an image built on an Apple Silicon laptop that will not start on an amd64 host, a private registry the platform cannot authenticate against, a process that ignores SIGTERM and gets killed mid-request on every deploy, and a volume somebody assumed was persistent. None of them are difficult; all of them are discovered late.
The short version: Fly.io is the cheapest way to keep a small container running, Cloud Run is the best fit when traffic is spiky and the container is stateless, Railway and Render are the smoothest if you want the platform to build the image for you, and Granite — our own platform — fits when you already build images in CI and want a private registry, databases and storage in the same project. If you only need to run one stateless container as cheaply as possible, we are not the cheapest and the table says so.
At a glance
| Provider | From /mo | Free tier | Managed DB | Persistent disk | Deploy from |
|---|---|---|---|---|---|
| Fly.io | ~$2 | Postgres (unmanaged app) | Dockerfile, buildpack | ||
| Railway | $5 | yes ($1 credits) | Git, Dockerfile, template | ||
| Render | $7 | yes (spins down) | Git, Dockerfile | ||
| Granite | $9 | from Advanced | Git, Docker image | ||
| Koyeb | $29 | limited | Serverless Postgres | Git, Dockerfile | |
| Google Cloud Run | usage-based | yes (monthly allowance) | via Cloud SQL | no (use GCS) | Container image |
Entry prices as published by each provider on 7 August 2026, sorted cheapest first. Usage, bandwidth and databases are billed on top almost everywhere — treat this column as a starting point, not a monthly bill.
Who builds the image, and does it need to keep anything?
Build on the platform, or build in CI? This is the first real fork, and it matters more than the choice of provider. Letting the platform build from a Dockerfile is fewer moving parts and one less system to maintain. Building in your own CI and pushing a finished image means the artefact you tested is byte-for-byte the one that runs, builds happen on hardware you control, and deploys are a pull rather than a compile. Most teams start with the first and move to the second, so it is worth choosing a platform that supports both.
Serverless containers — Cloud Run, and Koyeb's scale-to-zero — are the most literal expression of the container contract: an image, a port, and nothing else. The constraint is that instances exist only to serve requests. No local state, no background loops, no long-lived connections. Containers designed for a server rarely survive that transition without changes.
A managed platform sits in the middle and is where most containers end up: a long-lived process, a managed database beside it, TLS and rollouts handled, and a persistent volume available for the cases that genuinely need one.
Docker Compose is not a deployment target. Worth stating because it is such a common expectation. Compose describes services on one machine; a platform models each service as its own resource with its own scaling, and the relationships between them as network and configuration. Some platforms can import a Compose file as a starting point, but the mental model has to change — and on a single rented server, running Compose yourself is a perfectly legitimate alternative to any of this.
Long-lived process, a database beside it, maybe a volume
Managed platform
Prebuilt image or platform build, with storage and databases in the same project.
Granite · Railway · Render
Stateless, request-driven, and idle much of the time
Serverless containers
Free while idle — no local state, no background work, no open connections.
Cloud Run · Koyeb
Several containers that only make sense together, and you like the machine
Compose on a VPS
Cheapest per gigabyte, and every operational duty stays yours.
Hetzner · DigitalOcean · anyone
The options
Fly.io
- Best for
- The cheapest way to keep a small container online, and the best option for several regions.
- Pricing
- Pay as you go. The smallest shared-cpu-1x machine with 256 MB RAM works out at roughly $2.02/month, billed per second.
- Cheapest entry point in this table, billed per second, so stopped machines cost only storage.
- Runs your image essentially as-is, with volumes, private networking and multi-region routing available on the same primitives.
- Machines are an explicit, scriptable concept, which suits teams that want to orchestrate deployments themselves.
- That explicitness is also the cost: machines, volumes and networking are yours to understand and maintain.
- Databases are apps you run and back up yourself rather than managed services.
- No free tier for new organisations since October 2024.
Railway
- Best for
- Letting the platform build the image from a Dockerfile and wiring services together quickly.
- Pricing
- Hobby is $5/month including $5 of usage credits; Pro is $20/month per workspace including $20 of credits. A free plan gives $1 of monthly credits, and there is a 30-day trial.
- Builds from a Dockerfile or from source without one, and deploys prebuilt images from a registry too.
- Services in a project reach each other privately, so a container and its database need no public endpoint.
- The template catalogue covers most off-the-shelf images people want to self-host.
- Usage-based billing on top of the base fee makes the monthly cost hard to forecast.
- The Pro fee is charged per workspace, which adds up for small teams.
Render
- Best for
- A predictable monthly bill for a container that just needs to run.
- Pricing
- Free web services are available but spin down after 15 minutes without traffic. The cheapest paid instance, Starter, is $7/month for 0.5 vCPU and 512 MB RAM.
- Builds from a Dockerfile or pulls an existing image, with a real free tier for evaluating.
- Managed Postgres and Redis, persistent disks, background workers and cron jobs in one account.
- Fixed instance sizes, which makes the bill easy to explain to whoever signs it off.
- Free services spin down after 15 minutes idle.
- Fixed sizes mean scaling is a step change, and costs climb quickly beyond one small instance.
Granite
- Best for
- Teams that already build images in CI and want the registry, the databases and the storage in one project.
- Pricing
- Hobby is $9/month and includes $15 of monthly usage credits. Advanced is $39/month with $50 of credits, Professional $149/month with $200. Every plan has unlimited workspace seats.
- A private Docker registry is part of the platform, so images built in your CI have somewhere to live that the runtime can already authenticate against.
- Deploy a prebuilt image or let Granite build from GitHub, GitLab or Bitbucket — the two paths are interchangeable per resource.
- Managed Postgres, MySQL, Valkey and S3-compatible storage sit in the same project over internal DNS, with no public endpoints on the databases.
- HTTP apps, background workers and cron jobs are all just containers with different commands, so one image can back several resources.
- Unlimited workspace seats on every plan, and flat pricing that does not move with traffic.
- No free tier — the cheapest way in is $9/month.
- Persistent volumes start on the Advanced plan, so Hobby suits stateless containers only.
- Fewer regions than the hyperscalers, and no multi-region routing yet.
Koyeb
- Best for
- Global edge deployment of a container with scale-to-zero, if the entry price is acceptable.
- Pricing
- The Pro plan is $29/month; Scale is $299/month. Serverless Postgres has a small free allowance.
- Runs your image at edge locations that are included rather than sold separately.
- Scale-to-zero available for containers that start quickly.
- The highest entry price of any managed option here.
- Smaller ecosystem and community than Railway or Render, so there are fewer worked examples when something is unusual.
Google Cloud Run
- Best for
- Stateless containers with spiky traffic, where paying nothing while idle matters most.
- Pricing
- No monthly fee. You pay per request and per resource-second, with a monthly free allowance. Cloud SQL and networking are billed separately.
- Takes any container image and scales to zero, so an idle service is genuinely free.
- Effectively unlimited scale ceiling, with per-request billing.
- The most container-native model here: the contract is simply an image that listens on a port.
- No persistent disk, so any container that expects to write state locally needs redesigning before it will work at all.
- Instances are request-scoped, which rules out long-lived connections and any background loop that runs between requests.
- Registry, database, secrets and networking are separate GCP products you assemble and bill separately.
What a Docker app actually needs from a host
- Architecture, not just tags
- An image built on an Apple Silicon laptop is arm64, and most platforms run amd64. The failure is abrupt and unhelpful — exec format error, or a container that exits immediately — and it happens after a successful build and push. Build multi-arch with buildx, or set the target platform explicitly, and check what your host actually runs before you debug anything else.
- Where the image lives
- A public image is easy everywhere. A private one needs the platform to authenticate against your registry, which means credentials, rotation and — on some platforms — a specific registry type. A registry inside the same platform removes that entirely; a registry outside it is one more set of credentials to keep working.
- Deploy by digest, not by latest
- A mutable tag means two replicas started an hour apart can be running different code, and a rollback is not reproducible. Tag with the commit SHA and deploy by digest so a deployment identifies exactly one image. Platforms differ in whether they resolve the tag once at deploy time or on every pull, which is precisely the ambiguity you are removing.
- PID 1 and SIGTERM
- Rolling deploys send SIGTERM and then wait. A CMD written in shell form runs your process under /bin/sh, which does not forward signals, so the container is killed after the grace period with requests still in flight — on every single deploy. Use exec form, handle the signal, or add a tiny init process, and match your shutdown timeout to the platform's grace period.
- Listen on the port you were given
- Almost every platform injects a PORT environment variable and expects the container to bind it on 0.0.0.0. Hard-coding a port, or binding 127.0.0.1, produces a container that runs perfectly and receives no traffic — a health check that never passes, with completely healthy application logs.
- The filesystem is not storage
- The container filesystem is discarded when the container is replaced, which happens on every deploy, and it is not shared between replicas. Anything that must survive belongs in a database, a bucket, or an explicitly attached volume — and a volume usually binds the service to a single instance, which is a scaling decision as much as a storage one.
- Image size is a deploy-time cost
- The image is pulled on every deploy and every scale-up, so its size is latency you pay repeatedly. Multi-stage builds that leave the toolchain behind routinely cut images by five to a hundred times depending on the stack. Order the layers so the parts that rarely change sit underneath the parts that change on every commit.
- Secrets do not belong in layers
- Anything copied into an image stays in its history even if a later layer deletes it, and anyone who can pull the image can read it. Use build-time secret mounts for credentials the build genuinely needs, and inject runtime configuration as environment variables from the platform's encrypted storage.
- Whose health check?
- The HEALTHCHECK instruction in a Dockerfile is generally ignored by hosting platforms — they run their own HTTP or TCP probes and route traffic on the result. Configure the probe on the platform, point it at an endpoint that reflects readiness rather than merely being listening, and give it a start delay long enough for your slowest boot.
So which should you pick?
One small container, as cheaply as possible. Fly.io, at roughly $2/month for a 256 MB machine, billed per second.
Stateless and idle most of the day. Cloud Run. The container contract is at its purest here, and an idle service is genuinely free — provided nothing in the image expects a disk, a background loop or an open connection.
You want the platform to build it and to explain the bill. Render for fixed pricing, Railway if you would rather assemble a stack from templates.
You already build images in CI. This is where we would argue for Granite. The private registry is part of the platform, so pushing from CI and deploying by digest needs no external credentials; managed Postgres, MySQL, Valkey and S3-compatible storage sit in the same project over internal DNS with no public database endpoints; and web apps, workers and cron jobs are all just containers with different commands, so one image can back all three. From $9/month with $15 of usage credits.
Looking for advice specific to what is inside the image? The Go, Django and Next.js comparisons cover image size, memory and build caching per stack, and the Docker registry page covers pushing and pulling private images.
Hosting for other stacks
Six ways to run a Go binary, from a $2 machine to scale-to-zero — and why Go stays cheap longer.
Seven options weighed on the things Django actually needs: media storage, a real Postgres, Celery workers and enough memory for gunicorn.
Vercel and six alternatives, weighed on the things that actually break when you self-host: ISR across replicas, image optimization and build-time env vars.
Six platforms plus Kamal, weighed on what Rails really needs: a release phase for migrations, a job runner, Active Storage and enough memory for Puma.
Laravel Cloud and six alternatives, weighed on queue workers, the scheduler, writable storage and the caches you must rebuild on every deploy.
Six platforms weighed on what an ASGI service actually needs: worker processes, connections that stay open, and a database pool that does not multiply out of control.
Seven options for the framework that ships no opinions — weighed on the WSGI server you have to bring, the session key you must keep stable, and the extensions that decide the rest.
Six platforms weighed on the things Symfony assumes: a warmed cache built at build time, Messenger workers that restart on deploy, and Doctrine migrations that run exactly once.
Seven platforms for a framework that renders on every request — weighed on streaming, adapters, and how far the loaders sit from the database.
Six platforms weighed on what the JVM actually asks for: memory it is allowed to use, a container that knows its own limits, and a start-up you can afford to repeat.
Five ways to serve HTML that is already written — and an honest note about which of them we are not the right answer for.