With Dockerfile as the build type, HCode builds the image from your own Dockerfile and runs it. Use it when you need system packages, a specific base image or a multi-stage build that automatic builds don't give you.
Choose a Dockerfile build
When you create a project from GitHub, HCode looks for a Dockerfile at Dockerfile, docker/Dockerfile, .docker/Dockerfile or build/Dockerfile. If it finds one, the plan says "Your Dockerfile at" followed by the path, and suggests the port from its EXPOSE line. You can also pick Dockerfile under Build mode yourself.
For an existing project, open Settings, go to Build configuration and choose Dockerfile under Build type, then save and deploy.
Dockerfile path
Dockerfile path is the path to your Dockerfile from the project's root directory, ./Dockerfile by default. With the root directory set to /apps/api, ./Dockerfile means apps/api/Dockerfile in the repository. Absolute paths and paths that leave the project are refused with "Dockerfile path must be a relative file path".
When you create a project from GitHub with the root directory left at /, HCode uses the Dockerfile it found, such as docker/Dockerfile. With any other root directory it uses ./Dockerfile; if yours is elsewhere, create the project without deploying and change the path under Settings first.
If the file isn't there when the build starts, the deploy fails with "Deployment failed: build mode is dockerfile but Dockerfile was not found in source", with your path in place of Dockerfile. Commit the Dockerfile at that path, or correct the path.
Context path
Docker context path is the folder whose files the build can see, such as the files a COPY line copies. Like the Dockerfile path it is relative to the root directory, and ., the default, is the root directory itself. The Dockerfile doesn't have to be inside the context folder, the same as docker build -f docker/Dockerfile app. It is under Advanced Dockerfile options in Settings, and under Optional settings when you create the project.
If the folder doesn't exist, the deploy fails with "Deployment failed: the Docker context path" followed by your path and "is not a folder in the root directory".
The root directory, context path and Dockerfile path must stay inside your repository after symbolic links are followed. A path that leads out through a link fails the deploy, for example with "Deployment failed: The Docker context path "ctx" leads outside the repository through a symbolic link. Point it at a folder or file inside the repository."
Build stage
For a multi-stage Dockerfile, set Docker build stage to the name of the stage to build, for example production for a stage declared as FROM node:22 AS production. Leave it empty to build the last stage. It is under Advanced Dockerfile options in Settings, and under Optional settings when you create the project.
Build arguments
Build args (Build arguments when you create the project) passes values to ARG instructions in your Dockerfile. Write one KEY=VALUE per line:
NODE_ENV=production
APP_VERSION=1.4.2
Your Dockerfile only sees an argument it declares with ARG. Don't put secrets in build arguments.
Once saved, the field shows •••••••• instead of the values, and the saved set stays as it is when you save other changes. To replace it, type the full set again. To delete it, click remove them under the field and save.
The Runtime version (optional) setting adds its own argument here, such as NODE_VERSION. See Runtime versions.
Build secrets
Build secrets are for values a build step needs but that must not end up in the image, such as a token for a private package registry. Write one KEY=VALUE per line, like build arguments. Names use letters, digits and underscores and can't start with a digit; blank lines and lines starting with # are ignored. A line in any other form is refused with a message such as "Build secrets must be KEY=VALUE lines (e.g. NPM_TOKEN=xxxxx). Line 3 is not.", which gives the line number but never the line itself.
HCode stores build secrets encrypted and hands them to the build as Docker build secrets, never as build arguments, so they are not written into any image layer. Their values are also replaced in the build log. A step reads a secret by mounting it with its name as the id. Docker puts it in a file at /run/secrets/ plus the name, for that step only:
RUN --mount=type=secret,id=NPM_TOKEN \
NPM_TOKEN="$(cat /run/secrets/NPM_TOKEN)" npm ci
Like build arguments, saved secrets show as •••••••• and are kept until you type a new set or click remove them and save.
Note
Project environment variables are not passed to a Dockerfile build. They are set in the running container. Anything the build itself needs goes in Build args, or in Build secrets if it is secret.
Start command
Leave Start command (optional) empty to run the image's own CMD. Anything you enter overrides that CMD. HCode never swaps your command for its own static file server, even if the image contains an index.html.
Port
A Dockerfile web app needs a port when you create it. EXPOSE in your Dockerfile is only used to suggest one; after that the project's Runtime port is what counts. HCode sets PORT to that value in the container and sends traffic to it, so your app must listen on that port on 0.0.0.0. A background worker needs no port. See Web apps and workers.
Volumes
A path your image declares with VOLUME gets 1 GiB of scratch space. It is emptied when the container is replaced, on every deploy and restart, and it doesn't count toward your storage. A write past 1 GiB fails with "no space left on device". Keep data that must last in a database. The rest of the container's filesystem is writable as usual.