Dockerfile Requirements
For static sites (HTML, CSS, JS), you don't need a Dockerfile — Caster automatically serves your files with nginx.
For dynamic apps (Node.js, Python, Go, etc.), include a Dockerfile in your project root. This page covers the rules your Dockerfile must follow.
For complete, copy-paste-ready Dockerfiles for every major language and framework, see Example Dockerfiles.
When You Need a Dockerfile
- Static sites: No Dockerfile needed. Caster injects
FROM nginx:alpineand serves your files automatically. - Dynamic apps: Include a Dockerfile in the root of your project (git repo or upload archive).
Requirements
If you provide a Dockerfile, it must satisfy these rules:
- Dockerfile in the project root — Caster looks for a file named
Dockerfilein the root - Use
EXPOSEto declare your port — Caster reads theEXPOSEdirective to determine which port your app listens on. If noEXPOSEis found, it defaults to port 80 - Health check endpoint — your app should respond to
GET /with a 200 status (used for readiness checks)
Installing System Packages
Many applications need system libraries (database drivers, image processing, build tools). How you install them depends on your base image.
Debian / Ubuntu (-slim images)
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libpq-dev \
imagemagick \
&& rm -rf /var/lib/apt/lists/*
Alpine (-alpine images)
RUN apk add --no-cache \
postgresql-dev \
imagemagick
Common Packages
| Need | Debian (apt-get) |
Alpine (apk) |
|---|---|---|
| PostgreSQL client libs | libpq-dev |
postgresql-dev |
| MySQL client libs | default-libmysqlclient-dev |
mariadb-dev |
| Git | git |
git |
| C compiler / make | build-essential |
build-base |
| Image processing | imagemagick |
imagemagick |
| SSL / crypto | libssl-dev |
openssl-dev |
| XML parsing | libxml2-dev |
libxml2-dev |
| Curl | curl |
curl |
Docker Layer Caching
Docker caches each layer. The key insight: copy dependency files first, install dependencies, then copy your source code. This way, npm install or pip install only reruns when your dependency files change — not on every code change.
# 1. Copy only the dependency manifest
COPY package.json package-lock.json ./
RUN npm ci --production
# 2. Copy everything else
COPY . .
Multi-Stage Builds
Use multi-stage builds to keep your final image small:
FROM golang:1.23-alpine AS build
WORKDIR /app
COPY . .
RUN go build -o server .
FROM alpine:3.20
COPY --from=build /app/server /server
EXPOSE 80
CMD ["/server"]
Tips
- Always include an
EXPOSEdirective — Caster uses it to detect your app's port (defaults to 80 if omitted) - Use
-slimor-alpinebase images to reduce build time and image size - Pin your base image version (
node:22-alpine, notnode:alpine) for reproducible builds - See Example Dockerfiles for complete, working examples for every major stack