Docker hosting — 6 options compared

Once your application is an image, the language stops mattering and a different set of questions takes over: who builds it, which registry it comes from, what architecture it was built for, and what happens to the filesystem when the container is replaced.

Where should you run a Docker container in 2026?

Once the application is an image, the language stops mattering and price and plumbing take over. Fly.io keeps a small container running from roughly $2/month; Cloud Run costs nothing while a stateless container is idle; Railway at $5/month and Render at $7/month will build the image for you from a Git push.

Granite — our own platform — is $9/month with $15 of usage credits and includes a private Docker registry, managed databases and S3-compatible storage in the same project as the container, so the image never leaves the network it is deployed into.

Last updated 1 September 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.

How much does Docker hosting cost?

Sorted by entry price. Every provider here can build and run a Docker service; the columns are what separates them.
ProviderFrom /moFree tierManaged DBPersistent diskDeploy from
Fly.io~$2Postgres (unmanaged app)Dockerfile, buildpack
Railway$5yes ($1 credits)Git, Dockerfile, template
Render$7yes (spins down)Git, Dockerfile
Granite$9from AdvancedGit, Docker image
Koyeb$29limitedServerless PostgresGit, Dockerfile
Google Cloud Runusage-basedyes (monthly allowance)via Cloud SQLno (use GCS)Container image

Entry prices as published by each provider on 1 September 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?

Pick the category before you pick the provider — it decides more than the logo does.

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.

Where should the container run?

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 question that decides this is not which language is inside the image — it is whether the container needs to keep anything, and who builds it.

What does each platform actually give you?

Prices as published by each provider on the date above. Check them before you commit — they move.

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
Billing is per second of actual usage against a monthly minimum: $5 on Hobby and $20 on Pro, each including that much usage credit. The free plan is a 30-day trial with $5 of credits and $1 a month afterwards, capped at 1 vCPU and 0.5 GB per service. Pro includes unlimited workspace seats.
  • 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.
  • Hobby is a single-developer workspace, so the first teammate you invite moves the minimum from $5 to $20 a month.

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
Pro is $29/month plus compute and includes $10 of it; Scale is $299/month including $100. Serverless Postgres has a free tier of 5 hours a month at 0.25 vCPU, 1 GB RAM and 1 GB of storage, after which the smallest always-on instance is $29.76/month plus $0.50 per GB stored.
  • 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 does a containerised app need from a host?

The requirements that matter for Docker are different from the ones every generic hosting listicle repeats.
Container-specific criteria
These have nothing to do with the language inside the image, which is exactly why they are the ones that catch people out.
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.
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.

Where do background jobs and queue workers run?

In their own container, which is the part of a Compose file that survives the move to a platform. The worker service in docker-compose.yml usually shares the image with the web service and overrides command: — that pattern maps directly onto a hosting platform, where it becomes a second resource from the same image with a different command. On Granite that resource type is worker: no public domain, internal ports only, always running. What does not carry across is restart: unless-stopped and the one-process-per-container rule you were enforcing with an init system. The platform is the supervisor now, it restarts on exit, and a container that forks a queue consumer beside the server hides the failure of one behind the health of the other.

How do scheduled tasks and cron work?

A cron container running crond in the foreground is the Compose answer, and it is the wrong shape here: it is a container you pay for around the clock to do five minutes of work, and it is invisible to the platform's restart and log handling. Every provider in this comparison offers scheduled runs instead. On Granite a cron-job resource starts the container on a cron expression and stops it when the command exits, with Forbid or Allow deciding what happens when the previous run has not finished, and it takes no replica count — one run, one container. Its output lands in novps resources logs <id>, not in the web service's stream.

Is Postgres managed, and what about backups?

The postgres:16 service in your Compose file is the one thing that should not be lifted as-is. A database container on an ephemeral filesystem loses everything on the next deploy, and on a platform without persistent volumes it cannot be made safe at all. Use the managed engine: Render, Railway, Koyeb and Granite all provide one, with a version you choose and credentials generated for you. Granite backs it up on a schedule into external storage, offers point-in-time recovery for Postgres through support on request, and gives the database no public endpoint — internal DNS for the app, novps port-forward database <id> -l 5432 for you. An attached volume is the other answer, and it is a scaling decision as much as a storage one: it binds the service to a single instance.

How do deploys and migrations work?

Two routes: push to a branch and let the platform build the image, or build it yourself and let the platform watch a tag or a digest. Migrations belong in neither the Dockerfile nor the entrypoint — a CMD that runs migrate before starting the server executes once per replica per deploy. Render and Railway have a release command; on Granite you run it from the resource's Console tab or over a forwarded database port, before the new image rolls. During the rollout both versions are briefly live, which is why SIGTERM handling and a health check that reflects readiness matter more here than the size of the image does.

What does it actually cost per month?

A web container, a worker container and a managed Postgres, as of 1 September 2026. Fly.io is $2.02 per 256 MB machine and $3.32 at 512 MB, with the database left to you. Render is $7 for each service and $6 for a 256 MB Postgres — $20 for the set. Railway bills per second against a $5 monthly minimum on Hobby, which suits a worker that is idle most of the day. Granite is $9 with $15 of credits shared between all three, capped at 1 vCPU and 1 GiB per service — the ceiling that decides whether your image fits, rather than the price.

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

Go hosting

Six ways to run a Go binary, from a $2 machine to scale-to-zero — and why Go stays cheap longer.

Django hosting

Seven options weighed on the things Django actually needs: media storage, a real Postgres, Celery workers and enough memory for gunicorn.

Next.js hosting

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.

Node.js hosting

Six ways to run an Express, NestJS or Fastify service — weighed on the event loop, the connection pool, and what a long-lived process costs while it waits.

Rails hosting

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 hosting

Laravel Cloud and six alternatives, weighed on queue workers, the scheduler, writable storage and the caches you must rebuild on every deploy.

Python hosting

Seven platforms for Django, Flask, FastAPI or a script with no HTTP port at all — and how to tell which of those you are actually deploying.

FastAPI hosting

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.

Flask hosting

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.

Symfony hosting

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.

Remix hosting

Seven platforms for a framework that renders on every request — weighed on streaming, adapters, and how far the loaders sit from the database.

Spring Boot hosting

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.

Static site hosting

Five ways to serve HTML that is already written — and an honest note about which of them we are not the right answer for.

Docker hosting questions

More questions? Email us at support@granite.so

Be first in line for updates
and special pricing
Get early access to new features and exclusive discounts delivered straight to your inbox