Skip to main content

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 argValue
VESSL_GIT_BRANCHThe branch being deployed
VESSL_GIT_COMMITThe full commit SHA
VESSL_APP_NAMEThe 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 caseFlag
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.

Build-time secrets

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