Dockerfile Templates
For most apps, you don't need a Dockerfile — just set a supported runtime (Python, Node.js, Go, Bun, static) and PromptShip generates the build for you.
These templates are for advanced users who need full control over the build (e.g. custom system packages, multi-stage builds, or unsupported runtimes like Rust or Java). Place the Dockerfile in your repo root (or in the root_dir you configured) and set runtime: "dockerfile".
Important: Your app must listen on the port specified by the PORT environment variable. Bind to 0.0.0.0:$PORT. All templates below are configured for this.
Python (Flask / FastAPI)
With requirements.txt
FROM python:3.12-slim
WORKDIR /app
# Install dependencies first for better layer caching
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE $PORT
# Flask
CMD gunicorn --bind 0.0.0.0:$PORT app:app
# FastAPI (uncomment and replace the line above)
# CMD uvicorn main:app --host 0.0.0.0 --port $PORT
With pyproject.toml
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir .
COPY . .
EXPOSE $PORT
CMD gunicorn --bind 0.0.0.0:$PORT app:app
Django
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Collect static files at build time
RUN python manage.py collectstatic --noinput
EXPOSE $PORT
CMD gunicorn --bind 0.0.0.0:$PORT myproject.wsgi:application
Node.js
Express / Fastify
FROM node:22-slim
WORKDIR /app
# Install dependencies first for better layer caching
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE $PORT
CMD ["npm", "start"]
npm ci requires a package-lock.json. Run npm install locally first to generate it.
Make sure your app listens on process.env.PORT:
// server.js
const port = process.env.PORT || 8080;
app.listen(port, '0.0.0.0');
Next.js
FROM node:22-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-slim
WORKDIR /app
COPY --from=builder /app/.next .next
COPY --from=builder /app/node_modules node_modules
COPY --from=builder /app/package.json .
COPY --from=builder /app/public public
EXPOSE $PORT
ENV PORT=8080
CMD ["npm", "start"]
Go
FROM golang:1.23 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .
FROM alpine:3.21
COPY --from=builder /app/server /server
EXPOSE $PORT
CMD ["/server"]
Make sure your Go app reads the port from the PORT environment variable:
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
http.ListenAndServe(":"+port, router)
Static Site / WASM
For static files, single-page apps, or WASM games. Uses nginx to serve files with SPA fallback routing.
FROM nginx:alpine
# Copy your static files
COPY . /usr/share/nginx/html
# nginx config template — $PORT is substituted at container start
RUN printf 'server {\n\
listen ${PORT};\n\
root /usr/share/nginx/html;\n\
index index.html;\n\
location / {\n\
try_files $uri $uri/ /index.html;\n\
}\n\
}\n' > /etc/nginx/conf.d/default.conf.template
EXPOSE $PORT
ENV PORT=8080
CMD ["/bin/sh", "-c", "envsubst '${PORT}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"]
Monorepo tip: If your static files are in a subdirectory (e.g. game/), set root_dir to that directory using configure_app. You can run multiple apps from the same repo — one for your API, one for your static site.
Rust
FROM rust:1.83 AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
# Cache dependency build
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release && rm -rf src
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/app /app
EXPOSE $PORT
CMD ["/app"]
Tips
- Layer caching: Copy dependency files (requirements.txt, package.json, go.mod) before copying the full source. This way, dependencies are only rebuilt when they change.
- Multi-stage builds: Use a builder stage for compiled languages (Go, Rust) to keep the final image small.
- PORT: Always bind to
0.0.0.0:$PORT(notlocalhostor127.0.0.1). The platform setsPORT=8080and routes HTTPS traffic to it. - .dockerignore: Add a
.dockerignorefile to excludenode_modules/,.git/,__pycache__/, and other unnecessary files from the build context.