https://github.com/mainman94/docker-strapi
4.3K
Docker images for Strapi v5 — Alpine and Debian slim, multi-arch, rebuilt on every upstream release.
docker run -d -p 1337:1337 -e NODE_ENV=development dockerha08/strapi:alpine-latest
Open http://localhost:1337/admin. The container scaffolds a fresh Strapi project with an SQLite database on first boot and starts it.
With Compose, and a bind mount so the project survives the container:
services:
strapi:
image: dockerha08/strapi:alpine-latest
environment:
NODE_ENV: development # or production
ports:
- "1337:1337"
volumes:
- ./app:/srv/app # scaffolded here on first boot, reused after
Both variants run unprivileged, so a bind-mounted directory must be writable
by the image's user. Create it first and hand it over — uid 100 (gid 101) for
alpine, 1000 for debian-slim (sudo chown -R 1000:1000 ./app). The entrypoint
stops with this hint if it cannot write to /srv/app.
Runnable examples: SQLite · PostgreSQL.
| Tag | Base | Runs as | Notes |
|---|---|---|---|
alpine-latest | node:24-alpine | appuser (uid 100) | Smallest. Recommended. |
alpine-<version> | node:24-alpine | appuser (uid 100) | Pinned to a Strapi release. |
alpine-<version>-r<run> | node:24-alpine | appuser (uid 100) | Immutable. |
debian-slim-latest | node:24-trixie-slim | node (uid 1000) | glibc, for native modules Alpine trips on. |
debian-slim-<version> | node:24-trixie-slim | node (uid 1000) | Pinned to a Strapi release. |
debian-slim-<version>-r<run> | node:24-trixie-slim | node (uid 1000) | Immutable. |
<version> is the upstream Strapi version, e.g. alpine-5.52.3. The
<version> tag moves when the node:24 base image is rebuilt under the same
Strapi release; -r<run> (the publish run number) never moves. Pin that one,
or a digest, when you need exactly the image you tested.
Upgrading debian-slim from an image before the non-root switch: those ran as root, so the existing volume is root-owned. Hand it over once:
docker run --rm -v <volume>:/srv/app alpine chown -R 1000:1000 /srv/app.
Platforms: linux/amd64, linux/arm64. Every published image carries an
SBOM and provenance attestation, is signed with cosign (keyless, verify with
the command in SECURITY.md), and has OCI labels:
docker buildx imagetools inspect dockerha08/strapi:alpine-latest
docker inspect dockerha08/strapi:alpine-latest --format '{{json .Config.Labels}}' | jq
Variant details: alpine · debian.
On start, the entrypoint looks at /srv/app:
package.json → runs
create-strapi-app to
scaffold a project, configured from the DATABASE_* env vars below.node_modules → installs dependencies with yarn if
a yarn.lock exists, otherwise npm.strapi develop
when NODE_ENV=development,
strapi start
when NODE_ENV=production (building the admin panel first if
dist/build/index.html is missing).The Content-Type Builder is disabled when
NODE_ENV=production— that is Strapi's behaviour, not the image's.
To run an existing project, mount it at /srv/app. Anything other than
the default command is executed as-is, so docker run ... dockerha08/strapi:alpine-latest sh
gives you a shell.
Used when scaffolding a new project:
| Variable | Default | Description |
|---|---|---|
DATABASE_CLIENT | sqlite | sqlite, postgres or mysql |
DATABASE_HOST | – | Database host |
DATABASE_PORT | – | Database port |
DATABASE_NAME | – | Database name |
DATABASE_USERNAME | – | Database user |
DATABASE_PASSWORD | – | Database password |
DATABASE_SSL | – | true / false |
EXTRA_ARGS | – | Extra flags passed to create-strapi-app |
Used at runtime:
| Variable | Default | Description |
|---|---|---|
NODE_ENV | development | development → strapi develop, production → strapi start |
STRAPI_BUILD_MAX_OLD_SPACE_SIZE | 2048 | Node.js heap (MB) for the admin panel build |
Strapi's own variables (APP_KEYS, JWT_SECRET, ADMIN_JWT_SECRET, …) are
read from the project's .env; set them explicitly for anything long-lived.
These images are built for scaffolding and development. For production, build
an image from your project on top of node:24:
FROM node:24
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY favicon.ico ./favicon.ico
COPY src/ src/
COPY public/ public/
COPY database/ database/
COPY config/ config/
RUN yarn build
EXPOSE 1337
CMD ["yarn", "start"]
make build VARIANT=alpine
make smoke VARIANT=alpine
or by hand:
docker build -t strapi-alpine-test \
--build-arg STRAPI_VERSION="$(cat release-versions/strapi-latest.txt)" \
--build-arg NODE_DIGEST="$(cat release-versions/node-alpine-digest.txt)" \
images/strapi-alpine
./smoke-test.sh strapi-alpine-test
Build args: NODE_DIGEST (required — the base image is pinned by digest),
NODE_VERSION (default 24), STRAPI_VERSION, plus VCS_REF and
BUILD_DATE for the OCI labels.
A daily workflow reads the latest Strapi version from npm and the current
node:24 digests into release-versions/ and opens a pull request for it,
which merges once CI passes; the Dockerfiles build from exactly those digests.
A change there on main triggers a build of both variants for
both platforms, a smoke test, a push to Docker Hub, a second smoke test of the
pushed images on native amd64 and arm64, and a GitHub release. Nothing is
pushed that did not boot successfully first, and nothing is released that did
not boot after the push.
Issues and PRs welcome — see CONTRIBUTING.md, SECURITY.md and the Code of Conduct.
MIT. Fork of naskio/docker-strapi, which remains under its original copyright. Strapi is a trademark of Strapi Solutions SAS; this project is not affiliated with or endorsed by Strapi.
Content type
Image
Digest
sha256:86855b9f2…
Size
94.4 MB
Last updated
1 day ago
docker pull dockerha08/strapi:debian-slim-latest