No. Vercel has no Docker Compose deployment target, so you can't point a deployment at a `docker-compose.yml`. What Vercel runs is single container images as [Vercel Functions](https://vercel.com/docs/functions/container-images), and the multi-container shape a compose file describes maps to services declared in `vercel.json`.

This article maps each Compose concept to its Vercel equivalent, translates a small compose file into services, and covers what doesn't translate at all.

## [Copy link to heading](#how-does-vercel-run-containers-instead)How does Vercel run containers instead?

Vercel runs OCI container images as Vercel Functions. A `Dockerfile.vercel` (or `Containerfile.vercel`) at the project root is auto-detected, built during the build step, pushed to Vercel Container Registry, and served from a function that scales automatically. The container must open an HTTP server: the default port is 80, and you can override it with the `PORT` environment variable in project settings. Instances scale down after 5 idle minutes in production (30 seconds in preview) and receive `SIGTERM` with a 30-second grace period. Billing uses Active CPU pricing, the same model as other Vercel Functions. The guide on [Docker deployments on Vercel](https://vercel.com/kb/guide/does-vercel-support-docker-deployments) walks through those mechanics end to end, so this page won't repeat the walkthrough.

That covers one container. For the multi-container part, Vercel has [services](https://vercel.com/docs/services), currently in public beta: multiple backends and frontends deploy within a single Vercel project, declared under a `services` key in `vercel.json`. Each service has a `root`. A service is internal by default, and a top-level rewrite whose destination is `{ "service": "<name>" }` is what exposes it to the internet. To build a service as a container image, set the service's `runtime` to `container`; with container images, `entrypoint` points at the Dockerfile path relative to the service's `root`.

## [Copy link to heading](#how-do-compose-concepts-map-to-vercel)How do Compose concepts map to Vercel?

Each row's left side is a line you'd find in a `docker-compose.yml`; the right side is where that job lands on Vercel.

| Compose concept | Vercel equivalent |
| --- | --- |
| `services:` (each service block) | A service under `services` in `vercel.json` |
| `build:` / `dockerfile:` | `runtime: "container"` with `entrypoint` pointing at that service's `Dockerfile.vercel` |
| `ports:` mappings | One public surface: top-level `rewrites` route paths to services, and each container serves HTTP on `PORT` (default 80) |
| Compose networks / service DNS names | Service bindings: Vercel injects the target service's URL as an environment variable |
| `environment:` | Project environment variables |
| `volumes:` (named volumes, bind mounts) | No equivalent; databases and caches move to managed backing services, files to blob storage |
| `depends_on:` | No startup order to manage; all services in a project ship as one atomic deployment |
| `docker compose up` (local dev) | Keep it, or run `vercel dev`, which runs all services together |

## [Copy link to heading](#translate-a-compose-file-into-services)Translate a compose file into services

Take a common compose shape: a web frontend, an API it calls, and a Postgres database with a named volume.

```
services:
  web:
    build: ./web
    ports:
      - "3000:3000"
    environment:
      API_URL: http://api:4000
  api:
    build: ./api
    environment:
      DATABASE_URL: postgres://db:5432/app
    depends_on:
      - db
  db:
    image: postgres:16
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:
```

Two of the three services translate. `web` and `api` are HTTP services built from Dockerfiles, so each becomes a service in `vercel.json` with a `Dockerfile.vercel` in its root:

```
{
  "services": {
    "web": { "root": "web/", "entrypoint": "Dockerfile.vercel" },
    "api": { "root": "api/", "entrypoint": "Dockerfile.vercel" }
  },
  "rewrites": [
    { "source": "/api/(.*)", "destination": { "service": "api" } },
    { "source": "/(.*)", "destination": { "service": "web" } }
  ]
}
```

Here is where each remaining compose line went:

- The `ports:` mappings became the two `rewrites`. There is one public surface: requests under `/api/` route to `api`, everything else routes to `web`, and each container serves HTTP on `PORT` (default 80) instead of publishing its own host port.

- `API_URL: http://api:4000` relied on Compose's service DNS. On Vercel, `web` declares a binding to `api`, and Vercel injects the target service's URL as an environment variable, so the call never crosses the public internet. If you remove the `/api/(.*)` rewrite, `api` stays unreachable from the internet and only `web` can call it.

- `db` doesn't deploy at all. Containers on Vercel are stateless, so Postgres and its `dbdata` volume move to a managed backing service, such as a database from the Vercel Marketplace, and `DATABASE_URL` becomes a project environment variable.

- `depends_on: db` has nothing to point at anymore. There is no startup order to manage: all services in a project share the same deployment and deploy atomically.

For local development, `vercel dev` runs all services together with binding environment variables injected, so calls between services work the same locally as in production. Running container images locally requires the `docker` CLI and a running Docker daemon.

## [Copy link to heading](#what-doesn't-translate)What doesn't translate

- The compose file itself. There is no compose deployment target and no converter tool that turns a `docker-compose.yml` into `vercel.json`. The translation is manual, which is why the table above exists.

- Stateful services. Postgres, Redis, MinIO, and similar containers don't move into Vercel containers; they map to managed backing services. In-container databases are the part of a compose stack that gets re-homed, not translated.

- Volumes. Named volumes and bind mounts have no equivalent: files go to blob storage, data goes to managed databases.

- Non-HTTP services. Workers and one-shot init containers don't fit the request-driven model, since every container function must serve HTTP. Scheduled work maps to [cron jobs](https://vercel.com/docs/cron-jobs); an always-on worker belongs on a platform built for long-lived processes.

- Nothing on this list touches local development. Compose keeps that job, as the FAQ below spells out.

The compose question is one slice of running containers on Vercel; for the broader set of container workflows, from single images to services, see [7 ways to use Docker containers on Vercel](https://vercel.com/i/7-ways-to-use-docker-containers-on-vercel).

## [Copy link to heading](#frequently-asked-questions)Frequently asked questions

### [Copy link to heading](#do-i-have-to-rewrite-my-compose-file-to-deploy-on-vercel)Do I have to rewrite my compose file to deploy on Vercel?

You translate it once rather than rewrite it. Vercel does not read docker-compose.yml, and no converter tool exists, so you declare each HTTP service by hand under the services key in vercel.json. Your compose file stays untouched and keeps working for local development.

### [Copy link to heading](#what-replaces-the-volumes-in-my-compose-file)What replaces the volumes in my compose file?

Nothing on Vercel maps to compose volumes directly, because containers on Vercel are stateless. Data that lived in a volume moves to a managed backing service, such as a database or cache from the Vercel Marketplace, and files move to blob storage.

### [Copy link to heading](#how-do-containers-talk-to-each-other-without-a-compose-network)How do containers talk to each other without a compose network?

On Vercel, services in the same project call each other through bindings rather than a shared network. The calling service declares a binding, and Vercel injects the target service's URL as an environment variable, so the call never goes through the public internet. The target service stays unreachable from the internet unless a top-level rewrite exposes it.

### [Copy link to heading](#can-i-still-use-docker-compose-for-local-development)Can I still use Docker Compose for local development?

Yes. Deploying to Vercel changes nothing about local tooling, so docker compose up keeps its job. You can also run vercel dev, which runs all of a project's services together with binding environment variables injected; for container images it requires the docker CLI and a running Docker daemon.

## [Copy link to heading](#related-resources)Related resources

- [Does Vercel support Docker deployments?](https://vercel.com/kb/guide/does-vercel-support-docker-deployments) in the Knowledge Base

- [Which platform should host your Docker app?](https://vercel.com/i/which-platform-should-host-your-docker-app)

- [Vercel Services public beta announcement](/blog/vercel-services-run-full-stack-on-vercel) on the Vercel blog

- Migrate to Vercel from [Fly.io](https://vercel.com/kb/guide/migrate-fly-io-to-vercel), [Railway](https://vercel.com/kb/guide/migrate-railway-to-vercel), [Render](https://vercel.com/kb/guide/migrate-render-to-vercel), or [Google Cloud Run](https://vercel.com/kb/guide/migrate-cloud-run-to-vercel)