If your app builds with docker build, it runs on Hangar. A Dockerfile is the way to deploy a language the automatic builder does not cover, or to control exactly what goes into the image.
A Dockerfile that deploys well
Three things matter more than the rest:
- Listen on
0.0.0.0and on a known port. - Read configuration from environment variables, not from files baked into the image.
- Use a multi-stage build, so the final image carries the app and not the compiler.
A Go service as an example:
FROM golang:1.25 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server
FROM gcr.io/distroless/static-debian12
COPY --from=build /app /app
EXPOSE 8080
CMD ["/app"]
Add a .dockerignore that leaves out .git, dependency folders and local env files. It makes builds faster and keeps secrets out of the image.
1. Create the service
Create a project, add a service and pick your repository and branch. Choose a region.
2. Choose the Dockerfile builder
In the service's Settings → Source, select Dockerfile and set the path to the file, relative to the root directory. The default is Dockerfile.
For less common layouts, the advanced settings take a build context and a target stage. See Builds.
3. Variables and build arguments
Runtime configuration goes in the Variables tab and reaches the container as environment variables.
Values a RUN step needs during the build are build arguments, declared in the Dockerfile with ARG:
ARG APP_VERSION
RUN echo "building $APP_VERSION"
Do not pass secrets as build arguments: they can remain in the image's history. Use build secrets for credentials a build step needs, such as a private registry token.
4. Deploy and add a domain
Deploy the service. In Settings → Networking, add a domain, set the container port to the port your app listens on (8080 in the example) and turn HTTPS on.
5. Push to deploy
Every push to the connected branch rebuilds the image and deploys it. Layers that did not change are reused from the cache.
Deploying a prebuilt image
If your CI already builds and pushes an image, skip the build: create a service with Docker image as its source and give it the image name, plus registry credentials if the image is private.
Troubleshooting
- The build cannot find a file: the build context is not the directory you expect. Set it explicitly.
- 502 on the domain: the container port does not match, or the app listens on
127.0.0.1. - The container exits immediately: read the runtime logs. The usual cause is a missing environment variable.