Vercel enables container deployment from a plain Dockerfile

- Reading
- 6 min
- Code
- 3
When no framework is detected, Vercel now builds the Dockerfile or Containerfile at the project root and routes all traffic to the resulting image. See the priority order between framework, container file, and the manual flag.
What changes in project detection
Vercel has always tried to guess what you want to run: it finds a next.config.js and assumes Next.js, it finds a manage.py and assumes Django. This automatic detection pipeline works well for the frameworks the platform recognizes, but it has always left out anyone who builds a custom runtime, uses a language off the radar, or simply wants full control over the image from scratch.
According to Vercel's changelog, a plain Dockerfile or Containerfile at the project root is now used when no other framework is detected. In that case, the platform selects the Container preset, builds that file, and routes all traffic to the resulting image. There's no longer an obligation to fit the project into a known buildpack to publish on Vercel.
The priority order that decides what gets built
Having a Dockerfile in the repository doesn't, by itself, guarantee it will be used. Vercel resolves the dispute between detected framework and container file in a fixed order, and it's this order that explains behaviors that at first glance look like bugs:
- If Vercel detects a known framework (the changelog cites Django as an example), that framework wins, even if there's a
Dockerfileat the root. - A file named
Dockerfile.vercelorContainerfile.vercelalways wins over the detected framework, even if the project looks, for example, like a Next.js app. - To force the container manually without renaming the file, you can run
vercel project update --framework containervia the CLI or declare"framework": "container"invercel.json. - Only when no framework is detected and there's no
.vercelin the name does the plainDockerfileorContainerfilekick in as an automatic fallback.
In practice: if your project has a package.json with a dependency on some framework Vercel recognizes, the root Dockerfile will be ignored until you force the switch through one of the three paths above. That's the most likely stumbling block for anyone testing this in a monorepo that already looks like a JS app but wants to run as a plain container.
The minimal Dockerfile used as an example
The example Vercel itself publishes in the changelog already serves as an honest starting point for testing the feature:
FROM node:26-alpine
RUN npm i -g srvx
COPY . /app
WORKDIR /app
EXPOSE 3000
CMD [ "srvx", "--port", "3000" ]Notice there's nothing magic here: it's a lean Node image, a server (srvx) installed globally, the code copied to /app, and an exposed port. Vercel doesn't need to understand what's inside the app within the container, it just needs it to listen on the declared port. That's exactly what changes the game for anyone using a runtime outside the React/Next/Django trio: Bun, Deno, a Rust binary, a Go worker, it doesn't matter, as long as it becomes an image.
Multi-service with vercel.json
A project with more than one service (a separate API and worker, for example) still uses the services block in vercel.json, with one entrypoint per service:
{
"framework": "container",
"services": {
"api": { "entrypoint": "services/api/Dockerfile" },
"worker": { "entrypoint": "services/worker/Dockerfile" }
}
}This matters for anyone who already organizes the repository as a monorepo with multiple Dockerfiles: the platform doesn't force you to consolidate everything into a single image, but it also won't build each folder on its own without you explicitly declaring the mapping.
Runtime in beta and billing by Active CPU
The Container runtime runs on top of Vercel Functions infrastructure and is in beta. This has two direct implications:
- Billing by Active CPU: the runtime is billed under the Active CPU pricing model, the same one used for Functions. The changelog doesn't detail the exact billing mechanism or compare costs with other hosting options, so it's worth reading the Container runtime documentation before estimating costs for your case.
- Beta surface area: image size limits, supported regions, and cold start behavior aren't detailed in the changelog. Before moving anything critical to production through this path, it's worth reading the Container runtime documentation linked by Vercel itself and testing with a representative load, not just the example Dockerfile.
How I'd test this in a real project
Editor's note: the steps below were not executed in a real environment by the editorial team; this is a proposed walkthrough, not a measurement made by the author. Validate before using in production.
If I were validating the feature today, the path I'd follow is straightforward, but with a checkpoint at each step:
- Update the Vercel CLI to the latest version before anything else, to make sure the commands and flags used below are available.
- Place the
Dockerfileat the root and test it locally withdocker build -t app-teste .followed bydocker run -p 3000:3000 app-teste, confirming the server comes up before deploying to Vercel. - Run
vercel deployand check in the dashboard whether the chosen preset was indeed Container; if the project has any trace of a recognized framework, that's where automatic detection can win without warning. - If you need to force the container even with a detectable framework, use
vercel project update --framework containeror rename the file toDockerfile.vercel, which has guaranteed priority. - Track the Active CPU invoice during the first few days to understand whether the service's traffic pattern fits better with this billing model than with a fixed instance.
What remains open for front-end builders
For those who live and breathe Next.js and Vercel Functions day to day, the direct impact is smaller: detected apps keep following the usual pipeline. The gain shows up in monorepos that mix the front end with auxiliary services (image processing, PDF generation, a backend in a language Vercel doesn't recognize) that today live scattered across another provider just because of that.
The changelog doesn't detail image limits, container cold start time, or whether there's full edge network support like in traditional Functions. Before consolidating an entire infrastructure there, it's worth treating the feature for what it is right now: a new door, still in beta, for those who already trust Vercel for the front end and want to stop maintaining a second provider just for what isn't a framework.
Source 1: Vercel Changelog (https://vercel.com/changelog/deploy-a-container-from-a-plain-dockerfile)
"Deploy a container from a plain Dockerfile" - Vercel Changelog.
You can deploy a plain Dockerfile or Containerfile at the project root using Vercel's Container runtime, when no other framework is detected. Vercel selects the Container preset, builds that file, and routes all traffic to the resulting image.
Example Dockerfile used in the changelog:
FROM node:26-alpine
RUN npm i -g srvx
COPY . /app
WORKDIR /app
EXPOSE 3000
CMD [ "srvx", "--port", "3000" ]When project detection finds another framework, such as Django, that framework still wins. To force the use of the Dockerfile or Containerfile, you can run vercel project update --framework container or declare "framework": "container" in vercel.json.
A Dockerfile.vercel or Containerfile.vercel file still wins over a detected framework, and multi-service projects still use the services block in vercel.json, with one entrypoint per service.
The Container runtime is in beta, runs on top of Vercel Functions, and is billed under the Active CPU pricing model. Vercel itself recommends reading the Container runtime documentation to get started.
Translated from the Brazilian Portuguese original · Read the original
Vercel cuts pnpm install time by up to 14% in builds
Vercel now reuses pnpm's supply-chain verification across deploys. In cases with restored cache, installs that used to take seconds now finish in milliseconds.


