@John , thank you for taking actions to improve the open-source part of the Ghost. I hope you will find great people for those new roles and we all as the Ghost community will see the results of this very soon. Hopefully we’ll all have direct communication opportunities with the new team members.
In the meantime, I would like to publicly share here as well, I’m also open for taking voluntary responsibilities, if you need anything suitable for me, as an active member of the community.
7 Likes
Off topic: Your channel is awesome too! Thanks for your videos
2 Likes
Thank you @John
I really appreciate it.
1 Like
I see that something is already on the road even without waiting for new team members.
main ← feat/production-docker-images
opened 08:43PM - 11 Feb 26 UTC
closes https://linear.app/ghost/issue/BER-3292/add-production-docker-image-build… -to-ghost-ci
## Problem
Ghost CI builds a dev image for E2E tests, but the production image lives in Ghost-Moya. Moya clones Ghost, rebuilds from source every commit (~12 min), and ships an artifact that was never tested by CI. We need Ghost to own its own production image so what we test is what we ship.
## Proposal
Add a CI job that builds and pushes two production Docker images to GHCR on every commit:
- `ghcr.io/tryghost/ghost-core` — server + production deps, no admin (base for Ghost-Pro)
- `ghcr.io/tryghost/ghost` — core + built admin (self-hosters)
The Dockerfile mirrors Moya's proven production setup (bookworm-slim, jemalloc, sqlite3, ghost user). A `pack:standalone` script in ghost/core wraps `npm pack` to produce a standalone distribution that works outside the monorepo.
Nothing consumes these images yet. This is laying the foundation.
## Not Doing
- Switching Moya to use these images (BER-3294, separate PR)
- Running E2E tests against the production image (BER-3293)
- Multi-stage Docker build (builds on CI runner using existing Nx/yarn cache instead)
- Fixing Ghost's dependency bloat (`@faker-js/faker` in production deps, etc.)
- Version tags — those come from the release workflow, not CI
## Trade-offs
- **Host build, not Docker build.** We build on the CI runner and `COPY` into Docker rather than using a multi-stage Dockerfile. This reuses CI's dependency cache (fast) but means the Dockerfile isn't self-contained. Conventional wisdom says multi-stage, but Ghost's monorepo + monobundle + Nx cache make that impractical today.
- **Two images, one job.** Both images build sequentially in one job. Parallel jobs would be faster but double the build cost since they'd each need to build assets from scratch.
- **Image size ~1.1-1.3GB.** Comparable to the official Ghost Docker Hub image. Mostly `node_modules`. Not great, but not our problem to solve here.
## Rollback
**Easy.** Delete the CI job and Dockerfile. Nothing depends on these images yet. No data, no migrations, no customer impact.
## Blast Radius
None. Purely additive. Existing CI jobs, Moya, and production are completely untouched. The images are pushed to GHCR but nothing reads from them until we explicitly wire up Moya in a follow-up.
3 Likes
This is great news, @John . Thank you!