Containers Without the Ops
If your application is already packaged as a container image—a Go service, a Rails API, a Spring Boot app, or an nginx front—it just needs an HTTP port and a place to run. Vercel now accepts a Dockerfile.vercel file directly, handling the build, storage, deployment, and scaling of the image on Fluid compute. You are billed only for actual CPU cycles consumed, with no local daemons, registries, or clusters to manage.
The Two-File Path to Production
A basic Go server that reads its port from the $PORT environment variable looks like this:
main.go
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "80"
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello from a container on Vercel 👋")
})
http.ListenAndServe(":"+port, nil)
}
To turn that into a deployable service, add a Dockerfile.vercel with a standard multi-stage build:
Dockerfile.vercel
FROM golang:1.26-alpine AS build
WORKDIR /src
COPY . .
RUN go build -o /server main.go
FROM alpine:3.22
COPY --from=build /server /server
CMD ["/server"]
The build process compiles the binary and then copies it into a minimal Alpine base image that runs on boot. Deployment is a single command:
▲ vercel deploy
Vercel CLI
✓ Building image from Dockerfile.vercel
✓ Stored image in your project's registry
✓ Deployed to Fluid compute
Production: https://my-server.vercel.app
That command builds, stores, and ships the image to Fluid compute, outputting the production URL. From that point, every git push triggers a rebuild and generates a fresh, immutable preview URL. Running vercel deploys without a commit.
While the example uses Go, the process is language-agnostic. Rails, Express, Laravel, ASP.NET, FastAPI, and other services follow the same pattern. The sole requirement: the server must listen on $PORT, which defaults to 80. If your process speaks HTTP, it deploys.
First-Class Platform Features
Deployed containers are not isolated afterthoughts. They run on the same compute infrastructure as Vercel's frontend and function offerings, granting them several key benefits:
- Preview deployments for every push: Each commit gets a unique URL that can be shared and used for rollbacks.
- Bidirectional autoscaling: Instances spin up under load and wind down when traffic stops, eliminating fleet sizing and concurrency guesses.
- Active CPU pricing: Billing is based on execution time, not wall-clock time. Idle servers waiting on slow queries or API calls consume no billable CPU.
- Integrated observability: Logs, traces, and metrics for containers appear alongside all other shipped services in the same dashboard.
- Unified deployments: Containers run beside your frontend within the same project and domain, communicating privately over the Vercel network.
Optimized for a Fast First Byte
Startup speed dictates a container's usefulness. Vercel mitigates this by converting built images into optimized boot images—compressed snapshots tuned for rapid initialization.
During a boot event, the snapshot is streamed and decompressed on demand, eliminating the need to download the entire image before runtime begins. Your server can start handling requests before the full image has arrived.
Once an instance is live, Fluid compute keeps it warm and reuses it for many requests, mixing server responsiveness with the cost benefits of idle shutdown. Each container remains stateless: it responds to requests and retains nothing between them. Persistent data belongs in external services from the Vercel Marketplace, which allows the platform to freely add and retire instances with traffic. Durable storage for containers is planned.
Why This Approach Works Now
Vercel's original platform supported Dockerfile deployments a decade ago. The concept was sound, but the underlying infrastructure lagged. The intervening years have been spent building the primitives required to execute it properly—the same systems powering Builds, Functions, and Sandboxes. Containers now sit on that mature, traffic-scaled foundation with per-CPU billing.
Framework detection remains the recommended entry point for most applications; the source code often self-describes its required infrastructure. A Dockerfile is for the rest: services needing system libraries like FFmpeg or Chromium, frameworks without auto-detection, or apps you want to port unchanged. When there's no framework to parse, a Dockerfile is the universal specification for how a program should be built.
Every step around the Dockerfile—build, registry, rollout, scaling, and URL assignment—requires zero configuration.
Documentation is available, as are deployable templates to serve as starting points.



