Teral
Deploy

Dockerfile builds

Build with your own Dockerfile.

Use a Dockerfile when automatic builds don't fit: you need system packages, an unusual toolchain, or full control over the image.

Use a Dockerfile

Under Settings → Source & build → Dockerfile, pick the file. Teral lists the Dockerfiles it finds in the root directory, and you can also enter a path. Paths are relative to the root directory, which is also the build context for COPY and ADD.

To go back to automatic builds, select Automatic (no Dockerfile). The change applies from the next deployment.

Variables in the build

Teral hands the environment's variables to the build as one .env file, as a BuildKit secret. Mount it in the RUN steps that need it:

FROM node:22-alpine AS build
ARG TERAL_SECRETS_ID
WORKDIR /app
COPY . .
RUN npm ci
RUN --mount=type=secret,id=${TERAL_SECRETS_ID},target=/run/secrets/.env \
    set -a && . /run/secrets/.env && set +a && \
    npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=build /app .
CMD ["node", "dist/server.js"]
  • TERAL_SECRETS_ID is a build argument Teral sets. Declare ARG TERAL_SECRETS_ID in every stage that mounts the secret, because build arguments don't carry over between stages.
  • The value of TERAL_SECRETS_ID changes whenever a variable changes. Because the mount line contains it, the step reruns after a variable change and isn't served from the cache. Steps above it still use the cache.
  • set -a && . /run/secrets/.env && set +a exports every variable for that one step. Tools that read .env files themselves can read /run/secrets/.env directly.

Don't pass secrets through ARG or ENV: their values end up in the image history, where anyone with the image can read them. The secret mount exists only while the step runs.

Tips

  • Use the exec form for CMD, such as CMD ["node", "server.js"]. With the shell form, a shell becomes the main process and may not pass SIGTERM on to your app.
  • Add a .dockerignore so node_modules, .git and local .env files don't end up in the build context.
  • Pin base images to a version, such as node:22-alpine rather than node:latest.
Edit on GitHub

On this page