Sign inSign up

selfrail/strapi

By selfrail

•Updated about 2 months ago

Strapi 5 CMS image for the SelfRail app catalogue. Multi-arch, no baked secrets.

Image
0

110

selfrail/strapi repository overview

⁠Strapi image

Strapi publishes no official container image — their own documentation says so⁠ — so the catalogue entry cannot pin a vendor image the way Ghost or Directus do. This Dockerfile is ours: built from Strapi's documented production example, pinned to a released version, and auditable in-tree.

⁠Why it scaffolds a project

Strapi is a framework, not a stock service: a Strapi install is a generated project. Their Dockerfile assumes you already have one. The build therefore runs create-strapi-app and compiles the admin bundle, so the image contains a real, buildable Strapi rather than an empty directory.

Database connection details come from the environment at runtime; the scaffold only fixes which driver is installed (--dbclient postgres puts pg in the dependency tree).

⁠The image ships no .env

create-strapi-app generates a .env at scaffold time containing secrets it invented on the spot — APP_KEYS, ADMIN_JWT_SECRET, JWT_SECRET and the three salts. Those are baked at build time, so every pull of a published image would carry the same ones, and dotenv would quietly fall back to them whenever a deployment forgot to inject its own. A shared ADMIN_JWT_SECRET in a public image means anyone can forge an admin session.

The build therefore deletes that file. config/server.js reads env.array('APP_KEYS') with no default, so a container started without secrets fails to boot instead of coming up on public keys. SelfRail generates all seven per install — see configFields and secretEnv in packages/core/src/apps/catalog/strapi.json.

Running it outside SelfRail means supplying them yourself:

docker run --rm -p 1337:1337 \
  -e APP_KEYS="$(openssl rand -base64 32),$(openssl rand -base64 32)" \
  -e API_TOKEN_SALT="$(openssl rand -base64 32)" \
  -e ADMIN_JWT_SECRET="$(openssl rand -base64 32)" \
  -e TRANSFER_TOKEN_SALT="$(openssl rand -base64 32)" \
  -e JWT_SECRET="$(openssl rand -base64 32)" \
  -e ENCRYPTION_KEY="$(openssl rand -base64 32)" \
  -e DATABASE_CLIENT=postgres -e DATABASE_HOST=... \
  selfrail/strapi:5.52.3

HOST and PORT are the exceptions — those do have defaults (0.0.0.0, 1337).

⁠Build

docker build -t selfrail/strapi:5.52.3 -t selfrail/strapi:5 \
  --build-arg STRAPI_VERSION=5.52.3 docker/apps/strapi

Bumping Strapi is a one-line change to STRAPI_VERSION, a rebuild, and a matching image bump in packages/core/src/apps/catalog/strapi.json.

⁠Known trade-offs

  • ~2.4 GB. The runtime stage copies the whole app directory including node_modules, which is what Strapi's own example does. Selective copies of dist/build/, config/, public/ and src/ plus a production-only install would cut this substantially; correctness first, size second.
  • Content-Type Builder is off. The catalogue entry runs NODE_ENV=production, and Strapi disables the builder there by design — content types are code. Model them in a project and deploy it from Git rather than editing a running server.

Tag summary

Content type

Image

Digest

sha256:93b865079…

Size

383.6 MB

Last updated

about 2 months ago

docker pull selfrail/strapi:5