---
title: How Docker Compose concepts map to Vercel
description: "Translate your Docker Compose file to Vercel: Compose services become Vercel Services, networks become bindings, and volumes become Marketplace databases and Vercel Blob."
url: /kb/guide/docker-compose-concepts-on-vercel
canonical_url: "https://vercel.com/kb/guide/docker-compose-concepts-on-vercel"
last_updated: 2026-08-03
authors: Ben Sabic
related:
  - /docs/services
  - /docs/services/bindings
  - /docs/marketplace-storage
  - /docs/storage
  - /docs/global-config
  - /docs/environment-variables
  - /docs/fluid-compute
  - /docs/queues
  - /docs/workflow
  - /docs/cron-jobs
  - /kb/guide/vercel-services
  - /docs/functions/container-images
  - /kb/guide/does-vercel-support-docker-deployments
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

Your `compose.yaml` defines services, networks, and volumes, and Vercel does not read any of it. There is no `compose up` equivalent, so the translation is manual, but every concept in that file has a destination on the platform. Compose services become Vercel Services, service-name DNS becomes service bindings, and volumes decompose into Marketplace databases, Vercel Blob, and environment configuration. Use the mapping table below to find where each line of your Compose file goes, then follow the worked example to translate a complete five-service stack.

## Overview

In this guide, you'll learn:

- Which Vercel primitive replaces each Docker Compose concept
  
- How service-to-service networking changes from DNS names to bindings
  
- Where volume-backed state goes, whether that's a Marketplace database, Vercel Blob, or Global Config
  
- Which Compose patterns don't translate, and what to do instead
  

## The short answer

Each row links a Compose concept to its Vercel destination. The sections that follow explain each mapping with a code pairing.

| Compose concept                          | What it does                                                | Vercel equivalent                                                                                                                                                             |
| ---------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `services` (app containers)              | Defines each container to build and run                     | [Vercel Services](https://vercel.com/docs/services), declared under the `services` key in `vercel.json`                                                                       |
| Service-name DNS (`http://api:3000`)     | Containers reach each other by name on the default network  | [Service bindings](https://vercel.com/docs/services/bindings), which inject an internal URL environment variable                                                              |
| `ports`                                  | Publishes a container port to the host                      | Top-level `rewrites` in `vercel.json` targeting a service                                                                                                                     |
| `networks` (isolation)                   | Controls which services can reach each other                | Internal-by-default services plus explicit bindings                                                                                                                           |
| `volumes` for database data              | Persistent storage for Postgres, Redis, or Mongo containers | [Marketplace databases](https://vercel.com/docs/marketplace-storage) such as Neon, Supabase, and Upstash                                                                      |
| `volumes` for file uploads               | Shared filesystem for user files                            | [Vercel Blob](https://vercel.com/docs/storage)                                                                                                                                |
| `volumes` and `configs` for config files | Runtime configuration mounted as files                      | Environment variables, or [Global Config](https://vercel.com/docs/global-config) for read-heavy config                                                                        |
| `environment`, `env_file`                | Per-service variables                                       | Per-environment [environment variables](https://vercel.com/docs/environment-variables), pulled locally with `vercel env pull`                                                 |
| `depends_on`, `healthcheck`              | Startup ordering and readiness                              | No direct equivalent. Services deploy atomically and scale independently                                                                                                      |
| `deploy.replicas`, `restart`             | Manual scaling and restart policy                           | [Fluid compute](https://vercel.com/docs/fluid-compute) autoscaling                                                                                                            |
| Worker services (queue consumers)        | Long-running background containers                          | [Vercel Queues](https://vercel.com/docs/queues), [Vercel Workflow](https://vercel.com/docs/workflow), or [Cron Jobs](https://vercel.com/docs/cron-jobs), depending on the job |
| `docker compose up`                      | Runs the whole stack locally                                | `vercel dev` runs every service locally                                                                                                                                       |
| `docker compose logs -f app`             | Streams one service's logs                                  | The Logs UI filters by individual service                                                                                                                                     |

Vercel Services and container images are both in beta, available on all plans.

## Services: containers become Vercel Services

A Compose `services` block maps to the `services` key in `vercel.json`.

Each Vercel Service is an independently built unit with its own `root` directory, and a service that builds from a Dockerfile sets its `entrypoint` to a `Dockerfile.vercel` path, so a Compose service defined by `build:` maps one to one.

`services: web: build: ./web api: build: ./api`

`{ "services": { "web": { "root": "web/" }, "api": { "root": "api/", "runtime": "container", "entrypoint": "Dockerfile.vercel" } } }`

The deployment model is an upgrade over `compose up`. All services in a project deploy atomically, stay in sync on a shared domain, and roll back together, which replaces the best-effort startup coordination you get from Compose.

## Networking: DNS names become bindings

Compose and Vercel invert each other's defaults. On Compose's default network every service can reach every other service by name, and `ports` opts a service into public exposure. On Vercel every service is internal by default, and a top-level rewrite opts a service into public traffic. No rewrite means no public traffic.

Internal calls use bindings instead of DNS names. A binding is declared on the calling service, names the target, and injects the target's URL as an environment variable at runtime:

`{ "services": { "web": { "root": "web/", "bindings": [{ "type": "service", "service": "api", "format": "url", "env": "API_INTERNAL_URL" } ] }, "api": { "root": "api/" } }, "rewrites": [{ "source": "/(.*)", "destination": { "service": "web" } }] }` Where Compose code calls `http://api:3000/items/123`, Vercel code calls the injected URL: `await fetch(new URL('items/123', process.env.API_INTERNAL_URL));` Traffic over a binding stays on Vercel's internal network and never routes through the public internet. Bindings aren't available yet for services on the Go or Rust runtime; build those services as container images instead, which can use bindings. ## State: volumes decompose by role On Vercel you attach managed state instead of running stateful containers. A Compose volume serves three different jobs, and each job has a different destination. ### Database data moves to Marketplace databases Don't translate your `postgres` or `redis` service. Replace it with a managed database from the Vercel Marketplace, which provisions the resource and injects its credentials as environment variables: `# compose.yaml: a service and volume you delete services: db: image: postgres:16 volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata:` `# Vercel: attach a managed database instead vercel install neon # Postgres vercel install upstash # Redis` This is the biggest mental shift in the migration. Your application code keeps its Postgres or Redis client and reads the connection string from the injected environment variable. ### File uploads move to Vercel Blob A volume that holds user uploads or generated assets becomes [Vercel Blob](https://vercel.com/docs/storage), an object store for images, videos, and other files. There are no mounted paths; code writes and reads blobs through the SDK, authenticated with OIDC rather than a stored secret.

### Config files become environment variables

A volume or `configs` entry that mounts configuration files becomes environment variables. For configuration that's read on many requests and updated rarely, such as feature flags or redirect maps, use [Global Config](https://vercel.com/docs/global-config), a globally replicated store with reads of roughly 1 ms in every region.

## Background work: worker containers decompose by job type

A Compose worker service is one long-running container that does whatever jobs you feed it. On Vercel that container decomposes by job type. Use [Vercel Queues](https://vercel.com/docs/queues) for background jobs processed off the request path, [Vercel Workflow](https://vercel.com/docs/workflow) for durable multi-step processes that survive suspensions, and [Cron Jobs](https://vercel.com/docs/cron-jobs) for scheduled work. On the Hobby plan, cron jobs are limited to daily schedules.

## Configuration and local development

Per-service `environment` and `env_file` entries become Vercel environment variables, scoped per environment across production, preview, and development. Run `vercel env pull` to download them for local work, alongside the variables Vercel generates automatically for services and bindings.

The local loop also translates directly. `vercel dev` replaces `docker compose up` and runs every service in the project locally for a production-like environment. Services built from container images require the Docker CLI and a running Docker daemon on your machine. For observability, the Logs UI filters by individual service, replacing `docker compose logs -f app`, and the Deployments panel visualizes the services graph.

## What doesn't translate

Some Compose patterns have no Vercel mapping. Name them now to avoid surprises mid-migration.

- **Self-managed stateful containers**: You can't run your own Postgres or Redis container with local disk. Container-based functions are stateless; each instance keeps nothing between requests. Attach a Marketplace database instead. Vercel has announced durable storage attached to containers as upcoming, but it has not shipped.
  
- **Host bind mounts**: There is no host filesystem to mount from. Move files to Vercel Blob or bake them into the container image.
  
- `**depends_on**` **startup ordering**: Services deploy atomically and scale independently, with no startup ordering or readiness gating between them. Design each service to tolerate any startup order, for example by retrying dependent calls.
  
- **Privileged containers**: Workloads that need privileged host access, custom kernels, or host networking aren't supported.
  

## Worked example: translate a five-service stack

This canonical Compose stack covers the full mapping: a frontend, an API, two stateful services, and a worker.

`services: web: build: ./web ports: - "3000:3000" environment: - API_URL=http://api:8000 depends_on: - api api: build: ./api depends_on: - db - redis db: image: postgres:16 volumes: - pgdata:/var/lib/postgresql/data redis: image: redis:7 worker: build: ./worker depends_on: - redis volumes: pgdata:`

Five Compose services become two Vercel Services, two Marketplace databases, and a queue consumer.

**1\. Attach the databases.** The `db` and `redis` services disappear. Provision managed replacements, which inject connection strings as environment variables:

`vercel install neon vercel install upstash`

**2\. Define the app services.** `web` and `api` become Vercel Services. The `ports` mapping on `web` becomes the public rewrite, and the `API_URL` environment variable becomes a binding:

`{ "$schema": "https://openapi.vercel.sh/vercel.json", "services": { "web": { "root": "web/", "bindings": [{ "type": "service", "service": "api", "format": "url", "env": "API_INTERNAL_URL" } ] }, "api": { "root": "api/", "runtime": "container", "entrypoint": "Dockerfile.vercel" } }, "rewrites": [{ "source": "/(.*)", "destination": { "service": "web" } }] }` `api` has no rewrite, so it receives no public traffic. `web` reaches it through `process.env.API_INTERNAL_URL`. The container image listens on `$PORT`, which defaults to 80. The `depends_on` entries have no translation; the deployment is atomic and each service must tolerate any startup order. **3\. Replace the worker.** The `worker` service becomes a Vercel Queues consumer. Instead of a container polling Redis, the producer sends messages to a queue and Vercel invokes your consumer function to process each one off the request path. Run `vercel dev` to bring the translated stack up locally, then `vercel deploy` to ship it. ## Related resources and next steps - Configure multiple services in one project with the [Vercel Services documentation](https://vercel.com/docs/services)
  
- Read [The Complete Guide to Vercel Services](https://vercel.com/kb/guide/vercel-services) for routing, bindings, and billing in depth
  
- Build services from a Dockerfile with [Container Images](https://vercel.com/docs/functions/container-images)
  
- Choose a database, Blob, or Global Config in the [Storage overview](https://vercel.com/docs/storage)
  
- Process background jobs with [Vercel Queues](https://vercel.com/docs/queues)
  
- See which Docker surfaces Vercel supports in [Does Vercel support Docker deployments?](https://vercel.com/kb/guide/does-vercel-support-docker-deployments)