Skip to content

build: official container image with release, nightly and preview channels - #960

Open
rmdes wants to merge 3 commits into
mainfrom
feat/docker-image
Open

rmdes wants to merge 3 commits into
mainfrom
feat/docker-image

Conversation

@rmdes

@rmdes rmdes commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Why

Deploying Indiekit today means building your own image from an example config. A published runtime image makes it a config file plus docker compose up, and gives starter themes something to point at. This adds one. Happy to convert this into a proposal issue first if you would rather discuss the shape before reviewing the files.

Yours to veto

Three decisions in here are yours, and each is a small change:

  • Registry. This uses ghcr.io/getindiekit/indiekit, which needs no secrets. example-config already uses the Docker Hub-shaped name getindiekit/indiekit; switching is two lines.
  • Nightly channel. A daily multi-arch build costs your Actions minutes and leaves a main-<sha> version in the registry per run. It is one file; I can drop it, make it weekly, or add a retention step.
  • Preview channel. Manual only, severable on its own.

What

  • Dockerfile and .dockerignore: node:24-alpine (the engine floor is >=24.17), the whole workspace installed with npm ci --omit=dev --ignore-scripts, so every official plugin resolves by name from a mounted indiekit.config.js. Ignoring install scripts is safe here: the root postinstall is husky; bcrypt@6 resolves its prebuild through node-gyp-build at require time; sharp, esbuild and lightningcss resolve through optional platform packages; the lockfile carries the musl and arm64 variants of all of them. Runs as the unprivileged node user, working directory /app, entrypoint node packages/indiekit/bin/cli.js serve rather than npx, so the container can run as any --user. 128 MB.
  • .github/workflows/docker-image.yml: one reusable job that builds linux/amd64 and linux/arm64 and pushes with OCI labels, using the repository token with packages: write. Guarded to this repository, so forks never publish.
  • docker-release.yml: on release: published (and manual dispatch with a tag). I checked how releases happen here: lerna publish creates the tag and the GitHub release is created by hand afterwards, the last four all by you about a quarter of an hour after each tag, so the release event does fire. A tag pushed by the publish job's own token could not trigger a workflow, which is why the tag push is not the trigger. The channel is derived from the version string rather than the release's prerelease flag, because the beta releases here are not flagged as prereleases. Tags: <version> plus beta while the version is a prerelease; latest, <major>, <major>.<minor> once a stable release lands, with no workflow change.
  • docker-nightly.yml: daily from main, tags nightly and main-<sha>, skipped when the registry already has that sha.
  • docker-preview.yml: manual, any ref, a named channel such as preview-v1 or rc, for milestone testing without cutting a release.
  • docker-check.yml: on pull requests touching the Dockerfile, builds the amd64 image without pushing and starts the CLI as an arbitrary user, so the Dockerfile cannot rot between releases.
  • docs/docker.md, linked from the sidebar and from Get started.

No JavaScript changes, so build.yml is unaffected. Every file is root-level, so Lerna's version bumping sees nothing. create-indiekit's generated Dockerfile and compose file are untouched and out of scope; a follow-up could point its compose at the published image and drop the generated Dockerfile.

Proof

Built locally from this branch and run with MongoDB, a mounted indiekit.config.js (the Eleventy preset and the file-system store, six post types) and a mounted content/ directory, as the host user. Signed in through the browser and created a note from the Posts UI. The store received content/notes/c7c13.md, owned by the host user, and an Eleventy build of the mounted site rendered it at /notes/c7c13/ and in its feeds.

Two things the proof taught, both in the docs: the container must run as the host user or a mounted store is read-only to it, and PUBLICATION_URL must resolve from inside the container because the server fetches its own URL during sign-in.

Only the amd64 image has been started. The arm64 image builds under QEMU but has not been run; the lockfile carries the arm64 and musl native variants, so it should work, but that is not proven.

Limits

  • Third-party plugins are not in the image. Build on top of it to add them.
  • Multi-arch builds under QEMU are slow; the Actions cache is enabled.
  • The root dependencies include lerna and husky, so they ride along in the image. Moving them to devDependencies would shave the image; not touched here because it changes your development setup.

What I would most like a second opinion on

The tag policy, and whether you want the nightly at all.

@rmdes rmdes self-assigned this Sep 6, 2026
@rmdes rmdes added question Further information is requested onboarding Set-up and first run github_actions Pull requests that update GitHub Actions code labels Sep 6, 2026
@rmdes rmdes added this to the v1.0 milestone Sep 6, 2026
@rmdes
rmdes marked this pull request as ready for review September 6, 2026 16:25
@rmdes

rmdes commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator Author

This is in preparation to a new eleventy theme and a new indiekit-quickstart repo that would depend on these images, as for the 3 starters example, they will allow us to provide a repo from which indiekit can be bootstrap in few steps.

At first it will bootstrap indiekit as it is today, with mongodb if edit/deleted etc..
but in the future we could have sqlite running the show (as other db drivers) and let the user choose right from the indiekit-quickstart how he/she wants to boot the stack

@rmdes

rmdes commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

github_actions Pull requests that update GitHub Actions code onboarding Set-up and first run question Further information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant