Docker
A service can build from a Dockerfile in the repo, or run an image you paste from a registry (+ Service → Docker images).
How it works
Section titled “How it works”If a Dockerfile is in the service root (or the configured root directory), StackBlaze uses it and skips Nixpacks. It builds in an ephemeral builder, pushes the image to a private registry, and deploys that image as the service.
You get full control over:
- Base image (OS, language version, system libraries)
- Build steps and layer caching
- Runtime user (avoid running as root)
ENTRYPOINTandCMD
Port configuration
Section titled “Port configuration”StackBlaze reads the port your container listens on from two sources, in priority order:
- The
PORTenvironment variable injected at runtime (takes precedence). - The
EXPOSEdirective in your Dockerfile.
Always make the process read $PORT rather than hardcoding a port.
FROM node:20-alpine
WORKDIR /appCOPY package*.json ./RUN npm ci --only=production
COPY . .RUN npm run build
EXPOSE 8080
CMD ["node", "dist/server.js"]Multi-stage builds (recommended)
Section titled “Multi-stage builds (recommended)”Multi-stage builds produce dramatically smaller images by separating the build environment from the runtime environment. A smaller image means faster pushes, faster startup, and a smaller attack surface.
# Stage 1: BuildFROM node:20-alpine AS builder
WORKDIR /appCOPY package*.json ./RUN npm ci # install dev deps for buildCOPY . .RUN npm run build # compile TypeScript, bundle, etc.
# Stage 2: RuntimeFROM node:20-alpine AS runtime
# Run as non-root userRUN addgroup -S appgroup && adduser -S appuser -G appgroupUSER appuser
WORKDIR /appCOPY package*.json ./RUN npm ci --only=production # only production deps
# Copy built artifacts from builderCOPY --from=builder /app/dist ./dist
EXPOSE 8080CMD ["node", "dist/server.js"]Python multi-stage example
Section titled “Python multi-stage example”# Stage 1: DependenciesFROM python:3.12-slim AS deps
WORKDIR /appCOPY requirements.txt .RUN pip install --user --no-cache-dir -r requirements.txt
# Stage 2: RuntimeFROM python:3.12-slim AS runtime
RUN useradd -m appuserUSER appuser
WORKDIR /appCOPY --from=deps /root/.local /home/appuser/.localCOPY . .
ENV PATH=/home/appuser/.local/bin:$PATH
EXPOSE 8080CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]Go example (tiny binary)
Section titled “Go example (tiny binary)”Go compiles to a single static binary, enabling minimal Docker images:
# Stage 1: BuildFROM golang:1.22-alpine AS builder
WORKDIR /appCOPY go.mod go.sum ./RUN go mod download
COPY . .RUN CGO_ENABLED=0 GOOS=linux go build -o /server ./cmd/server
# Stage 2: RuntimeFROM scratch AS runtime # empty base image, only the binary
COPY --from=builder /server /serverCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080ENTRYPOINT ["/server"]Base image layer caching
Section titled “Base image layer caching”StackBlaze caches Docker layer builds across deploys. To get the best cache hit rates:
- Copy and install dependencies before copying your source code
- Separate dependency installation into its own layer (a lock file change invalidates the cache; source changes don’t)
- Use
--no-cache-dir(pip) or--no-cache(npm) to avoid storing package manager caches inside the image layer
Build arguments
Section titled “Build arguments”Pass build-time arguments to your Dockerfile using ARG. Set them in Service Settings → Build → Build Arguments. Build args are not the same as environment variables — they are only available during the build, not at runtime.
ARG NODE_ENV=productionARG APP_VERSION=unknown
RUN echo "Building version ${APP_VERSION} for env ${NODE_ENV}"Import from Docker Compose
Section titled “Import from Docker Compose”If you have a docker-compose.yml that defines multiple services, map each Compose service to a StackBlaze app or managed add-on. See Docker Compose.
StackBlaze reads the service definitions and creates corresponding StackBlaze services for each container. Services of type db, redis, or postgres are converted to managed database services.
Supported compose fields
Section titled “Supported compose fields”| Compose field | StackBlaze equivalent |
|---|---|
image |
Pre-built image (bypasses build step) |
build |
Dockerfile + context path |
ports |
Service port (first mapped port) |
environment |
Environment variables |
depends_on |
Service startup ordering |
command |
Start command override |
Using a pre-built image
Section titled “Using a pre-built image”If you already have a Docker image in a registry, you can deploy it directly without connecting a GitHub repository. Create or update the app with deploymentstrategy: docker and the image on the spec, or apply a stackblaze.yaml service with runtime: image.
services: - name: api type: web runtime: image image: url: ghcr.io/my-org/my-app tag: latestFor private registries, configure registry credentials in Project Settings → Integrations → Container Registries.
Dockerfile location
Section titled “Dockerfile location”By default, StackBlaze looks for Dockerfile at the root of the repository (or the service’s rootDir if set). You can specify a custom path in Service Settings → Build → Dockerfile Path.