Releasing & Building Images
This page is for contributors who need to build Lombok’s release container images locally, or who want to understand how official images get published. It does not cover running or deploying a Lombok instance — for that, see the Self-Hosting pages. For setting up a local development environment, see the Development pages.
Mental model: three separate things
Section titled “Mental model: three separate things”It is easy to conflate these, so keep them distinct:
| Activity | Where it happens | What it produces |
|---|---|---|
| Local image building | Your machine, via ./dx release … | A Docker image tagged into your local Docker daemon |
| CI publishing | GitHub Actions, on a version tag | Multi-arch images pushed to ghcr.io/lombokapp/… |
| Deployment / runtime | A server running a published or locally built image | A running Lombok instance |
This page covers the first two. The dev container you use for day-to-day work
(./dx up) is a different image entirely — it is the dev target of the same
Dockerfile and is not a release artifact.
The two image flavors
Section titled “The two image flavors”Lombok ships in two flavors, both built from docker/app.Dockerfile:
- Separate-DB (
releasetarget) — the application only. It expects an external PostgreSQL database. Published asghcr.io/lombokapp/lombok. - Standalone (
standalone-releasetarget) — the application with PostgreSQL embedded in the image (EMBEDDED_POSTGRES=true). Published asghcr.io/lombokapp/lombok-standalone.
The standalone target builds on top of the separate-DB target, adding the Postgres packages and an initialized data directory.
Building images locally
Section titled “Building images locally”The supported entry point is the ./dx CLI:
./dx release standalone <version>./dx release separate-db <version>The <version> argument is required. It is used verbatim as:
- the build ID baked into the image, and
- the tag suffix applied to the resulting local image.
The exact format is up to you — the tooling accepts whatever string you pass.
The dx help text shows a semver-style example, while the underlying build
scripts also show timestamp-style examples.
Under the hood, ./dx release runs the scripts in deploy/:
deploy/build-standalone.shdeploy/build-separate-db.sh
Each runs docker buildx build against the corresponding Dockerfile target.
What the local build produces
Section titled “What the local build produces”For a given <version>, the build produces per-architecture tags in your local
Docker daemon. For example, ./dx release standalone 1.2.1 yields tags like:
lombok-standalone:1.2.1-amd64lombok-standalone:latest-amd64lombok-standalone:1.2.1-arm64lombok-standalone:latest-arm64
The separate-DB build uses the image name lombok instead of
lombok-standalone.
Local builds produce architecture-suffixed tags and use --load to load each
platform into your local daemon one at a time. They do not assemble a
single multi-arch manifest — that only happens in CI.
Building for one architecture
Section titled “Building for one architecture”By default both linux/amd64 and linux/arm64 are built sequentially. Building a
platform that does not match your host requires emulation and can be slow. To
build only one architecture, use the helper scripts from package.json:
bun run build:standalone arm64bun run build:separate-db amd64These helpers auto-generate a build ID in the form
<UTC timestamp>-<git short hash> and forward the platform through to the build
script. Accepted platform values include amd64, arm64, linux/amd64, and
linux/arm64.
[!NOTE] If you call the
deploy/build-*.shscripts directly, the signature isbuild-<flavor>.sh <build-id> [platform]. Prefer./dx releaseor thebun run build:*scripts over invoking them by hand.
Caching
Section titled “Caching”Local builds run with --no-cache, so every local release build is a clean build
from scratch. This is intentional for reproducibility but makes local release
builds slower than incremental dev loops.
Build IDs
Section titled “Build IDs”Every release image has a build ID baked in at build time via the
LOMBOK_BUILD_ID build argument:
- the UI bundles it as a static
/build-idasset - the API exposes it at
/api/v1/public/build-id
This lets you confirm exactly which build a running instance came from. When you
run ./dx release <flavor> <version>, the <version> you pass becomes this build
ID.
[!NOTE] Do not confuse this with the dev build ID. During development,
./dxcomputes a separate per-invocation build ID for the dev container. That value is only for local development and is not used for release images.
Publishing in CI
Section titled “Publishing in CI”Official images are not published from a contributor’s machine. Publishing is
handled by .github/workflows/publish.yml, which:
- triggers on pushing a tag matching
v*.*.* - builds both flavors for
linux/amd64andlinux/arm64as a multi-arch manifest usingdocker/build-push-action - pushes to GitHub Container Registry:
ghcr.io/lombokapp/lombok:<tag>and:latestghcr.io/lombokapp/lombok-standalone:<tag>and:latest
- uses the GitHub Actions cache (
type=gha) to speed up builds
So the normal release flow is: merge the code, create a version tag, and let CI publish the images.
[!NOTE] Unlike local builds, CI publishes a single tag per flavor that resolves to the correct architecture automatically. There are no
-amd64or-arm64suffixes on published tags.
Using a locally built image
Section titled “Using a locally built image”You usually do not need to deploy a locally built image, but it can be useful for testing a release image end-to-end before tagging. The repo includes demo compose files that illustrate both patterns:
docker-compose.standalone.demo.ymlrunslombok-standalone:latestwithpull_policy: never, so it uses a locally built image if you tag it that way.docker-compose.demo.ymlrunsghcr.io/lombokapp/lombok:latestalongside a separate Postgres container.
Because local builds produce arch-suffixed tags, you may need to retag or adjust compose configuration so the image name matches what the compose file expects.
For runtime configuration such as environment variables, ports, persistent storage, and production deployment shape, use the Self-Hosting docs rather than relying on the demo compose files alone.
Quick reference
Section titled “Quick reference”# Build standalone (embedded Postgres), both arches, explicit version./dx release standalone 1.2.1-beta-rc3
# Build separate-DB (external Postgres), both arches, explicit version./dx release separate-db 1.2.1-beta-rc3
# Build one architecture with an auto-generated build IDbun run build:standalone arm64bun run build:separate-db amd64
# Publishing is CI-driven from version tags# (exact git push flow depends on your maintainer workflow)