Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frameworks/bun-websocket/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM oven/bun:latest
FROM oven/bun:1.3
WORKDIR /app
COPY server.ts entrypoint.sh ./
RUN chmod +x entrypoint.sh
Expand Down
2 changes: 1 addition & 1 deletion frameworks/dart-io/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1 — AOT compile the Dart server + build SO_REUSEPORT shim
FROM dart:stable AS build
FROM dart:3.12 AS build

WORKDIR /app
COPY frameworks/dart-io/pubspec.yaml ./
Expand Down
5 changes: 3 additions & 2 deletions frameworks/elysia/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# https://elysiajs.com/patterns/deploy.html#deploy-to-production
FROM oven/bun AS build
FROM oven/bun:1.3 AS build

WORKDIR /app

Expand All @@ -20,7 +20,8 @@ RUN bun build \
--outfile server \
server.ts

FROM gcr.io/distroless/base
# distroless publishes no version tags, so pin the digest
FROM gcr.io/distroless/base-debian12@sha256:62730825d3cf03571e0a1b8f014748de94d0404500f063593b614c23da38841d

WORKDIR /app

Expand Down
4 changes: 2 additions & 2 deletions frameworks/fasthttp/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand Down Expand Up @@ -29,7 +29,7 @@ COPY . .
# per-request allocation. Boehm keeps memory bounded; c0624b2's codegen wins still apply.
RUN v -prod . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends libpq5 && \
rm -rf /var/lib/apt/lists/*
Expand Down
2 changes: 1 addition & 1 deletion frameworks/fletch/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1 — AOT compile the Dart server + build SO_REUSEPORT shim
FROM dart:stable AS build
FROM dart:3.12 AS build

WORKDIR /app
COPY pubspec.yaml ./
Expand Down
2 changes: 1 addition & 1 deletion frameworks/frankenphp-trueasync/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM trueasync/php-true-async:latest-frankenphp
FROM trueasync/php-true-async:0.8.4-php8.6-frankenphp

WORKDIR /app

Expand Down
2 changes: 1 addition & 1 deletion frameworks/hono-bun/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM oven/bun:latest
FROM oven/bun:1.3
WORKDIR /app
COPY package.json ./
RUN bun install --production
Expand Down
4 changes: 2 additions & 2 deletions frameworks/lute/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG LUTE_VERSION=1.0.1-nightly.20260421

FROM buildpack-deps:curl AS bin
FROM buildpack-deps:bookworm-curl AS bin

RUN apt-get update && apt-get install -y --no-install-recommends unzip \
&& rm -rf /var/lib/apt/lists/*
Expand All @@ -13,7 +13,7 @@ RUN ARCH=$(echo "${TARGETARCH:-amd64}" | sed -e 's/arm64/aarch64/' -e 's/amd64/x
&& unzip lute.zip \
&& chmod +x lute

FROM debian:stable-slim
FROM debian:trixie-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates libssl3 \
Expand Down
4 changes: 2 additions & 2 deletions frameworks/pico/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand All @@ -19,7 +19,7 @@ COPY . .
# the default garbage collector is the safe choice here.
RUN v -prod . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends util-linux && \
rm -rf /var/lib/apt/lists/*
Expand Down
2 changes: 1 addition & 1 deletion frameworks/symfony-spawn-franken/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM trueasync/php-true-async:latest-frankenphp
FROM trueasync/php-true-async:0.8.4-php8.6-frankenphp

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer

Expand Down
4 changes: 2 additions & 2 deletions frameworks/vanilla-epoll/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand Down Expand Up @@ -79,7 +79,7 @@ COPY . .
# :8081); without it the tls module is a stub and the binary stays mbedtls-free.
RUN v -prod -gc none -d vanilla_tls . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends libpq5 liburing2 && \
rm -rf /var/lib/apt/lists/*
Expand Down
4 changes: 2 additions & 2 deletions frameworks/vanilla-h2c/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand Down Expand Up @@ -34,7 +34,7 @@ COPY . .
# allocation-free and the read-only dataset lives for the process lifetime.
RUN v -prod -gc none . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
# The binary links liburing.so.2 (the io_uring backend is compiled in on Linux
# even though this entry selects epoll at runtime).
RUN apt-get -qq update && \
Expand Down
4 changes: 2 additions & 2 deletions frameworks/vanilla-io_uring/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand Down Expand Up @@ -71,7 +71,7 @@ COPY . .
# module is a stub and mbedtls isn't linked).
RUN v -prod -d vanilla_tls . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends libpq5 liburing2 && \
rm -rf /var/lib/apt/lists/*
Expand Down
4 changes: 2 additions & 2 deletions frameworks/vanilla-ws/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand Down Expand Up @@ -31,7 +31,7 @@ WORKDIR /app
COPY . .
RUN v -prod -gc none . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
# The binary links liburing.so.2 (the io_uring backend is compiled in on
# Linux even though this entry selects epoll at runtime).
RUN apt-get -qq update && \
Expand Down
4 changes: 2 additions & 2 deletions frameworks/veb/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:stable-slim AS build
FROM debian:trixie-slim AS build

RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends \
Expand Down Expand Up @@ -28,7 +28,7 @@ COPY . .
# per-request allocation. Boehm keeps memory bounded; c0624b2's codegen wins still apply.
RUN v -prod . -o server

FROM debian:stable-slim
FROM debian:trixie-slim
RUN apt-get -qq update && \
apt-get -qy install --no-install-recommends libpq5 && \
rm -rf /var/lib/apt/lists/*
Expand Down
46 changes: 46 additions & 0 deletions scripts/validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,52 @@ has_test() {
[[ " $TESTS " == *" $1 "* ]]
}

# A benchmark has to be reproducible, so every base image must name a version
# (#471). Floating tags - latest, stable, nightly, or no tag at all - mean two
# runs months apart measure different software and the numbers can't be
# compared. major.minor is enough; a Debian/Ubuntu codename counts as one.
FROM_FILE="$ROOT_DIR/frameworks/$FRAMEWORK/Dockerfile"
if [ -f "$FROM_FILE" ]; then
UNPINNED=$(python3 - "$FROM_FILE" <<'PYEOF'
import re, sys

FLOATING = {"latest", "stable", "nightly", "edge", "main", "master",
"current", "devel", "testing", "rolling", "unstable"}
# distro codenames are a release, i.e. a major version
CODENAMES = {"bookworm", "trixie", "bullseye", "buster", "sid",
"jammy", "noble", "focal", "bionic", "plucky", "oracular"}

stages, bad = set(), []
for n, line in enumerate(open(sys.argv[1], encoding="utf-8", errors="replace"), 1):
m = re.match(r"\s*FROM\s+(\S+)(?:\s+AS\s+(\S+))?", line, re.I)
if not m:
continue
img, alias = m.group(1), m.group(2)
if alias:
stages.add(alias.lower())
if img.lower() in stages or img.startswith("$") or img.lower() == "scratch":
continue # earlier build stage, build arg, or scratch
if "@sha256:" in img:
continue # digest pin is the strongest form
name, _, tag = img.partition(":")
if not tag:
bad.append((n, img, "no tag (same as :latest)"))
elif tag.lower() in FLOATING or tag.lower().split("-")[0] in FLOATING:
bad.append((n, img, f"floating tag ':{tag}'"))
elif not any(c.isdigit() for c in tag) and not any(c in CODENAMES for c in tag.lower().split("-")):
bad.append((n, img, f"no version in ':{tag}'"))
for n, img, why in bad:
print(f"line {n}: {img} - {why}")
PYEOF
)
if [ -n "$UNPINNED" ]; then
echo "FAIL: Dockerfile base images must name a version (see #471)"
printf '%s\n' "$UNPINNED" | sed 's/^/ /'
echo " use e.g. node:22, python:3.13-slim, debian:trixie-slim, or an @sha256 digest"
exit 1
fi
fi

# Build — skip standalone build if framework only subscribes to compose profiles
# (gateway-64, gateway-h3, production-stack) and has no isolated tests.
GATEWAY_ONLY=true
Expand Down
18 changes: 18 additions & 0 deletions site/content/docs/add-framework/directory-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ frameworks/
... (source files)
```

## Pin your base images

A benchmark is only meaningful if it can be re-run, so every `FROM` must name a version. `latest`, `stable`, `nightly` or no tag at all mean two runs months apart measure different software, and the numbers stop being comparable.

```dockerfile
FROM node:22 # good - major
FROM python:3.13-slim # good - major.minor
FROM debian:trixie-slim # good - a Debian release is a version
FROM rust:1.83 AS build # good
FROM gcr.io/distroless/base-debian12@sha256:… # good - digest, for images with no version tags

FROM node:latest # rejected
FROM python # rejected (same as :latest)
FROM debian:stable-slim # rejected - "stable" moves with each Debian release
```

`scripts/validate.sh` enforces this, so a floating tag fails the PR check before a build is spent on it. Patch versions are not required - `3.13` is fine, `3.13.1` is also fine.

## Dockerfile

The Dockerfile should build and run your server. Containers are started with `--network host`, so bind to:
Expand Down