Skip to main content
Deploying applications on Unkey is in public beta. To try it, open the product switcher in the top-left of the dashboard and select Deploy. During beta, deployed resources are free. We’re eager for feedback, so let us know what you think on Discord, X, or email support@unkey.com.
By default Unkey builds your application automatically; you don’t need a Dockerfile. When your build needs more control, for example system packages, custom build steps, or a toolchain detection doesn’t cover, add a Dockerfile and Unkey builds with it instead. If you’re not comfortable writing a Dockerfile from scratch, the AI Dockerfile prompt generates one tuned for Unkey’s runtime.

Switching to Dockerfile builds

Configure the Dockerfile path in your app settings. Unkey auto-detects Dockerfiles in your build context and offers them in the dropdown. Once a path is set, every deployment of that app and environment builds with the Dockerfile. To switch back to automatic builds, set the Dockerfile field to Automatic (no Dockerfile). Changes apply on the next deployment.

Build configuration

SettingDescriptionDefault
Root directoryThe build context directory, where COPY and ADD are relative to. (repo root)
DockerfilePath to the Dockerfile within the root directoryAutomatic
See App settings for the full reference.

Build-time environment variables

Some builds need access to environment variables during the build step, for example to install private packages or generate code. All variables configured for the environment are available as Docker build secrets. Unkey mounts all your variables as a .env file at /run/secrets/.env inside the build container. To use them, add a --mount=type=secret flag to the RUN step that needs them. Unkey exposes a build argument called UNKEY_SECRETS_ID that you reference as the mount’s id (see Variable changes and the build cache). Here’s a complete example for a Node.js app that needs environment variables during the build step:
Dockerfile
FROM node:lts-alpine AS builder
ARG UNKEY_SECRETS_ID

WORKDIR /app
COPY . .
RUN npm install

# Mount the secrets file and load variables into the shell
RUN --mount=type=secret,id=${UNKEY_SECRETS_ID},target=/run/secrets/.env \
    set -a && . /run/secrets/.env && set +a && \
    pnpm build

FROM node:lts-alpine
WORKDIR /app
COPY --from=builder /app .
CMD ["node", "dist/index.js"]
Declare ARG UNKEY_SECRETS_ID inside every stage that mounts the secret. ARG values aren’t inherited across stages, so each FROM ... AS <stage> that consumes variables needs its own declaration. The secrets file uses standard .env syntax, one variable per line:
/run/secrets/.env
DATABASE_URL=postgres://prod-db.acme.com/api
NPM_TOKEN=npm_abc123
FEATURE_FLAG=true
The set -a && . /run/secrets/.env && set +a pattern loads every variable from the file into the shell environment for that RUN step. The secret file is not persisted in the final image. How you consume the file depends on your toolchain:
  • Tools that expect environment variables (npm, pip, go): use the set -a pattern above to load them into the shell.
  • Frameworks that read .env files directly (Node.js with dotenv, Ruby with dotenv): reference /run/secrets/.env in your build script instead of sourcing it.

Why secret mounts instead of ARG or ENV?

Docker’s ARG and ENV instructions are stored in the image layer history. Anyone with access to the image can extract them with docker history or docker inspect. Secret mounts avoid this problem: the file is available only during the RUN step and is never written to a layer.

Variable changes and the build cache

UNKEY_SECRETS_ID is a hash of your project’s variables. When you write id=${UNKEY_SECRETS_ID} on the mount line, BuildKit’s cache key for that RUN includes the id, so any variable change produces a new id and a fresh execution of that step and everything after it in the same stage. Steps before the secret mount (base image pulls, dependency installs) keep caching normally.

Troubleshoot Dockerfile builds

When a build fails, check the build logs in the Deployments tab. Common issues:
  • Missing Dockerfile: Verify the Dockerfile path in your app settings.
  • Dependency installation failures: Check that your base image includes the tools your Dockerfile needs.
  • Context too large: If your build context includes large files (node_modules, data files), add a .dockerignore to exclude them.

Next steps

Generate a Dockerfile with AI

A prompt that produces a Dockerfile tuned for Unkey’s runtime

App settings

Configure the Dockerfile path, root directory, and watch paths
Last modified on June 12, 2026