Dockerfile Builds
If your repository contains a Dockerfile, Vessl uses it automatically instead of Nixpacks. You get full control over the build process — base image, multi-stage builds, system dependencies, anything docker build supports.
How Vessl detects your Dockerfile
Vessl checks for a Dockerfile at the repository root (or your configured Root Directory). If found, the wizard pre-selects Docker as the build type. You can also select it manually.
What Vessl adds at build time
Vessl passes these --build-arg values to every Dockerfile build automatically:
| Build arg | Value |
|---|---|
VESSL_GIT_BRANCH | The branch being deployed |
VESSL_GIT_COMMIT | The full commit SHA |
VESSL_APP_NAME | The internal app name |
Any ARG you declare in your Dockerfile can be set as a build argument via Settings → Build Args. See the Build Args guide for details.
Start command
For Dockerfile builds, the container runs your image's CMD or ENTRYPOINT by default. If you set a Start command in Vessl, it appends to the docker run command, overriding CMD. Use this if you need to pick a specific entrypoint at deploy time without modifying the Dockerfile.
Custom Dockerfile path
If your Dockerfile isn't at the repository root — for example it lives at docker/Dockerfile.prod — set the Dockerfile Path field in the wizard or app Settings. The path is relative to your build context (the repository root, or your configured Root Directory).
Extra build flags
Use the Build command field to pass extra flags to docker build:
| Use case | Flag |
|---|---|
| Multi-stage target | --target production |
| Skip cache | --no-cache |
| Pull latest base images | --pull |
| Cross-platform | --platform linux/amd64 |
For example, to build a specific target from a multi-stage Dockerfile:
--target production
Example: multi-stage Node.js Dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json .
EXPOSE 3000
CMD ["node", "dist/index.js"]
Set Dockerfile Path to Dockerfile (default) and the app will build the production stage automatically if it's the last stage. To build a specific target: set Build command to --target production.
Example: Laravel with Dockerfile
FROM php:8.3-fpm-alpine
RUN apk add --no-cache nginx supervisor \
&& docker-php-ext-install pdo_pgsql opcache
WORKDIR /var/www
COPY . .
RUN composer install --no-dev --optimize-autoloader
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
EXPOSE 80
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
Environment variables at runtime
Vessl injects your app's environment variables at container start time as Docker -e flags — they're available as process.env.* / $VAR inside the running container.
Do not rely on ARG / ENV in your Dockerfile for secrets like database passwords — build args are stored in the image layer history and can be inspected with docker history. Secrets should only arrive at runtime via Vessl's environment variable injection.
Vessl limits which environment variables are passed as build args to a safe allowlist (public-prefix vars like NEXT_PUBLIC_*, VITE_*, etc.).
Post-deploy command
Dockerfile builds support post-deploy commands too — set one in Settings → Post-deploy command and it runs inside the container after the health check passes.
Common issues
Build fails: COPY path not found
The COPY instruction path is relative to the build context (your repo root or Root Directory). Make sure the file exists at that path in the repository.
Container exits immediately
Your CMD / ENTRYPOINT crashed on start. Check the deploy logs for the error. Common causes: a missing environment variable, a port binding issue (make sure you listen on 0.0.0.0, not 127.0.0.1), or a missing config file that wasn't COPYd into the image.
App ignores the Start command
If your Dockerfile uses ENTRYPOINT in exec form (["entrypoint"]), Vessl's Start command appends to it as CMD. If ENTRYPOINT is a shell script that ignores $@, the Start command has no effect. Change your entrypoint script to exec "$@" at the end to pass through the command.
Build arg value is empty
ARG must be declared in the Dockerfile before it can be used. Declare it before the FROM if you need it in multiple stages, or after FROM for a single stage:
ARG API_URL
ENV NEXT_PUBLIC_API_URL=$API_URL