feat: deprecate embedded postgres ahead of v4 - #3610
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a slim Docker image variant with Alpine Java 21, OpenTelemetry support, and health checks. Gradle tasks and release automation build and publish it, CI smoke-tests it against PostgreSQL, and startup logging warns when embedded PostgreSQL remains enabled. ChangesSlim image and release flow
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
gradle/docker.gradle (1)
95-123: Consider extracting shared publish logic to reduce duplication.
dockerPublishSlimis nearly identical todockerPublish— the only differences are the tag mapping and the-f Dockerfile.slimflag. If a third variant is ever added, the duplication will compound. A small helper (e.g., a closure takingdockerfileand atagResolver) would DRY this up without changing behavior.♻️ Sketch
def buildxPublish = { String dockerfile, Closure<String> tagResolver -> def version = System.getenv('VERSION') ?: 'latest' def imageName = System.getenv('DOCKER_IMAGE') ?: 'tolgee/tolgee' def tag = tagResolver(imageName, version) def cacheFrom = System.getenv('DOCKER_CACHE_FROM') def cacheTo = System.getenv('DOCKER_CACHE_TO') def cmd = ["docker", "buildx", "build", "."] if (dockerfile) cmd += ["-f", dockerfile] cmd += ["-t", tag, "--build-arg", "OTEL_AGENT_VERSION=${opentelemetryJavaagentVersion}", "--platform", "linux/arm64,linux/amd64", "--push"] if (cacheFrom) cmd += ["--cache-from", cacheFrom] if (cacheTo) cmd += ["--cache-to", cacheTo] exec { workingDir dockerPath; commandLine cmd } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@gradle/docker.gradle` around lines 95 - 123, dockerPublishSlim duplicates dockerPublish; extract the shared logic into a reusable closure (e.g., buildxPublish) that accepts a dockerfile name and a tag-resolver closure, move the environment reads (VERSION, DOCKER_IMAGE, DOCKER_CACHE_FROM, DOCKER_CACHE_TO) and common args (buildx build, OTEL_AGENT_VERSION build-arg, platforms, push) into that closure, then replace the dockerPublishSlim task body to call buildxPublish("Dockerfile.slim", { imageName, version -> /* slim tag logic */ }) and likewise call it from dockerPublish with the default Dockerfile and tag resolver, preserving the existing tag mapping and cache-from/cache-to handling.docker/app/Dockerfile.slim (1)
34-35: Pin the OTEL agent JAR by checksum (optional hardening).The agent JAR is fetched over HTTPS from GitHub Releases without integrity verification. A checksum check (the project publishes
.sha256/.ascalongside the jar) protects the image build from upstream tampering or transient corruption. Same concern applies to the non-slim Dockerfile; feel free to track separately and apply uniformly.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docker/app/Dockerfile.slim` around lines 34 - 35, The Dockerfile.slim RUN step that downloads opentelemetry-javaagent.jar using OTEL_AGENT_VERSION must be hardened by verifying the artifact checksum: fetch the corresponding .sha256 (or .sha256sum/.asc) published alongside the jar (using the same OTEL_AGENT_VERSION), validate the downloaded /app/opentelemetry-javaagent.jar with sha256sum (or gpg verify if using .asc), and fail the build if the verification fails; update the RUN instruction that does wget to also wget the checksum (or signature) and perform the verification before keeping the jar, and apply the same change to the non-slim Dockerfile equivalent so both images are protected from tampered or corrupted releases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docker/app/Dockerfile.slim`:
- Around line 1-3: The Dockerfile runs as root by default; create and switch to
a non-root user (e.g., user name "tolgee") by adding a user/group creation step,
ensure ownership of runtime directories like /data is changed (chown) so the new
user can write, copy application files as that non-root user (or adjust
ownership after copy), and set USER tolgee before the ENTRYPOINT to run the
container non-root; update any steps that assume root accordingly.
---
Nitpick comments:
In `@docker/app/Dockerfile.slim`:
- Around line 34-35: The Dockerfile.slim RUN step that downloads
opentelemetry-javaagent.jar using OTEL_AGENT_VERSION must be hardened by
verifying the artifact checksum: fetch the corresponding .sha256 (or
.sha256sum/.asc) published alongside the jar (using the same
OTEL_AGENT_VERSION), validate the downloaded /app/opentelemetry-javaagent.jar
with sha256sum (or gpg verify if using .asc), and fail the build if the
verification fails; update the RUN instruction that does wget to also wget the
checksum (or signature) and perform the verification before keeping the jar, and
apply the same change to the non-slim Dockerfile equivalent so both images are
protected from tampered or corrupted releases.
In `@gradle/docker.gradle`:
- Around line 95-123: dockerPublishSlim duplicates dockerPublish; extract the
shared logic into a reusable closure (e.g., buildxPublish) that accepts a
dockerfile name and a tag-resolver closure, move the environment reads (VERSION,
DOCKER_IMAGE, DOCKER_CACHE_FROM, DOCKER_CACHE_TO) and common args (buildx build,
OTEL_AGENT_VERSION build-arg, platforms, push) into that closure, then replace
the dockerPublishSlim task body to call buildxPublish("Dockerfile.slim", {
imageName, version -> /* slim tag logic */ }) and likewise call it from
dockerPublish with the default Dockerfile and tag resolver, preserving the
existing tag mapping and cache-from/cache-to handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bae4c2b4-b78c-46bb-821a-5f6e662feb93
📒 Files selected for processing (3)
.github/workflows/release.ymldocker/app/Dockerfile.slimgradle/docker.gradle
|
This PR is stale because it has been open for 30 days with no activity. |
The existing `tolgee/tolgee` image is based on `postgres` to support `postgres-autostart.mode: EMBEDDED`. For production deployments against an external database, the postgres server binaries and their transitive OS packages aren't used at runtime. Add a slim variant built from `eclipse-temurin:21-jre-alpine` that carries only what the application needs. Published alongside the existing image: - tolgee/tolgee:slim (floating, tracks latest) - tolgee/tolgee:<version>-slim The slim image sets `TOLGEE_POSTGRES_AUTOSTART_ENABLED=false` by default since embedded postgres isn't available in this variant; it must be run against an external database. Revives the approach from PR #3193 (stale). Current Dockerfile and default `tolgee/tolgee` tag are unchanged — this is purely additive. Co-authored-by: Matthew Sekirin <matthew.sekirin@gmail.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Match #3676's policy for the default image — relying on the registry layer cache pins the apk layer to the previously published image and masks CVE fixes. Drop DOCKER_CACHE_FROM from both dockerPublishSlim invocations so each release re-resolves apk packages.
615ddf6 to
448a8be
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
docker/app/Dockerfile.slim (1)
1-3:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRun the slim image as non-root before startup.
This Dockerfile still defaults to root at runtime. Please create a dedicated user, fix ownership for
/appand/data, and setUSERbeforeENTRYPOINT.Suggested patch
FROM eclipse-temurin:21-jre-alpine RUN apk --no-cache add bash +RUN addgroup -S tolgee \ + && adduser -S -G tolgee tolgee \ + && mkdir -p /app /data \ + && chown -R tolgee:tolgee /app /data @@ -COPY BOOT-INF/lib /app/lib -COPY META-INF /app/META-INF -COPY BOOT-INF/classes /app -COPY --chmod=755 cmd.sh /app +COPY --chown=tolgee:tolgee BOOT-INF/lib /app/lib +COPY --chown=tolgee:tolgee META-INF /app/META-INF +COPY --chown=tolgee:tolgee BOOT-INF/classes /app +COPY --chown=tolgee:tolgee --chmod=755 cmd.sh /app @@ # Define the startup command +USER tolgee ENTRYPOINT ["/app/cmd.sh"]Also applies to: 13-13, 23-27, 41-42
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docker/app/Dockerfile.slim` around lines 1 - 3, Create a non-root runtime user and ensure app directories are owned by it: add steps after the base image and package install (FROM eclipse-temurin:21-jre-alpine and RUN apk --no-cache add bash) to create a dedicated user/group (e.g., appuser), create or ensure /app and /data exist, chown them to that user, and finally set USER appuser before the ENTRYPOINT so the container runs non-root; apply the same pattern to the other Dockerfile variants referenced (lines 13, 23-27, 41-42).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@docker/app/Dockerfile.slim`:
- Around line 1-3: Create a non-root runtime user and ensure app directories are
owned by it: add steps after the base image and package install (FROM
eclipse-temurin:21-jre-alpine and RUN apk --no-cache add bash) to create a
dedicated user/group (e.g., appuser), create or ensure /app and /data exist,
chown them to that user, and finally set USER appuser before the ENTRYPOINT so
the container runs non-root; apply the same pattern to the other Dockerfile
variants referenced (lines 13, 23-27, 41-42).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 12f35f0d-701b-4dfd-a25c-14ebe36dd39b
📒 Files selected for processing (2)
.github/workflows/release.ymldocker/app/Dockerfile.slim
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/release.yml
Build the slim image, run it against a real postgres service container, and wait for /actuator/health to report UP. Catches regressions where a change works on the default postgres-based image but breaks on slim (missing native deps, JRE-distribution divergence, autostart assumptions in startup code, etc.).
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/test.yml:
- Around line 545-548: Replace the fragile sed-based JSON parsing that sets the
status variable from the curl output with a jq-based extraction so the top-level
"status" is returned deterministically; change the command that assigns status
(the curl ... | sed ... pipeline) to use jq -r '.status' (or equivalent jq
expression) to pull the root status, preserving the existing loop and condition
that checks if "$status" = "UP".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fc708a9f-ada6-40ad-9741-a538ebaddd82
📒 Files selected for processing (1)
.github/workflows/test.yml
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/test.yml:
- Around line 499-503: The docker-slim-smoke job currently inherits default
GITHUB_TOKEN permissions; update the job definition for docker-slim-smoke to
declare explicit least-privilege permissions (e.g., add a permissions block with
contents: read) so the job only has read access to repository contents for
checkout/build/run and does not inherit broader default scopes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 29c59737-c937-41f0-a448-093000e83c80
📒 Files selected for processing (1)
.github/workflows/test.yml
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
The bundled PostgreSQL will be removed once the slim image becomes the default tolgee/tolgee image. Warn operators running the embedded server so they can migrate to an external database before that change.
…rning The slim image is no longer published to Docker Hub. Self-hosters migrate by pointing the current image at an external database, which the fat image already supports, so a public slim tag would only advertise a name that becomes obsolete once v4 drops the bundled postgres. The image is still built on demand by the EE image build and the smoke test, so dockerSlim stays and dockerPublishSlim goes.
Only the EMBEDDED mode goes away in v4. DOCKER mode stays, as it is how Tolgee starts postgres when running with Java, so the deprecation is scoped to the mode rather than the whole postgres-autostart config.
The notices linked the external database section, which sets up an empty database on postgres:15. That is the wrong target for the people the notices reach: a bundled database is postgres:13, and postgres:15 refuses to start on its files.
Postgres 13 went end of life in November 2025. The backend test suite already runs against 16.3 via the docker autostart runner, so 17 is a small step from what is tested today, and it is the version the self hosting docs point at.
76ee870 to
9ef40c2
Compare
…ation (#1121) ## What Two changes: 1. **`platform/self_hosting/running_with_docker.mdx`** — warns that Tolgee v4 removes the bundled PostgreSQL from the `tolgee/tolgee` image, and adds a **Migrate from the bundled database** section with the actual procedure. 2. **`.github/workflows/update-generated-code.yaml`** — the docs codegen job booted `ghcr.io/tolgee/tolgee-ee` standalone and relied on its embedded postgres. The EE image is becoming slim (no bundled DB), so the job now starts a `postgres` service and points the app at it. ## Why In v4 the bundled postgres goes away, so anyone running it has to move to an external database first. The good news is that this needs **no dump and restore**: the bundled server keeps its files in `data/postgres` on the volume users already mount, which is exactly where a separate postgres container looks for them. Pin the container to `postgres:13` and it adopts the directory in place. **This also fixes a live trap.** The existing external-database example runs `postgres:15` and mounts `./data/postgres:/var/lib/postgresql/data` — the same directory a bundled user already has. Copy-pasting it as a migration fails hard: ``` FATAL: database files are incompatible with server DETAIL: The data directory was initialized by PostgreSQL version 13, which is not compatible with this version 15.17 ``` That example is fine for fresh installs and now says it's for fresh installs. ## Verified end-to-end Against the real `tolgee/tolgee:v3.212.0` image, not by reasoning: - Booted with the bundled DB, confirmed `PG_VERSION` is `13` at `data/postgres`, created a marker translation key via the API. - `postgres:15` on that directory → exits(1), incompatible-files error above. - `postgres:13` on that directory → starts, all 103 tables intact. - Tolgee with `postgres-autostart.enabled=false` against the external `postgres:13` → boots, starts no embedded server, original admin password still works, marker key still present. ## Notes for review - "Running Tolgee in single container" keeps a caution for now, deleted when v4 ships. - Companion PRs: tolgee/tolgee-platform#3610 (startup deprecation warning) · tolgee/billing#274 (EE image switch).
# [3.215.0](v3.214.1...v3.215.0) (2026-07-30) ### Features * auto-invalidate caches by value shape instead of wiping on startup ([#3813](#3813)) ([7e1db10](7e1db10)) * Community translation v1.1 — Contributors (pitch [#3806](#3806)) ([#3819](#3819)) ([3232c4f](3232c4f)) * deprecate embedded postgres ahead of v4 ([#3610](#3610)) ([3cef7ad](3cef7ad)), closes [tolgee/documentation#1121](tolgee/documentation#1121) [tolgee/billing#274](tolgee/billing#274) [#3193](#3193)
What
Two changes, both preparing for v4 dropping the bundled postgres from
tolgee/tolgee:WARNon startup when it's actually running the bundled postgres, pointing at the external-database docs.Dockerfile.slim+ thedockerSlimGradle task. Not published. Built on demand by the EE image build and by the smoke test.Why
In v4,
tolgee/tolgeeloses the embedded postgres. Self-hosters running the bundled database have to move to an external one before upgrading.They can already do that today on the current image by setting
postgres-autostart.enabled=false(this is what the external-database docs section has always described). So the warning gives them a full release cycle of notice, on every boot, for a migration that needs nothing new from us.The slim image is deliberately not published: a public
:slimtag would only advertise a name that goes obsolete the moment v4 makes it the default, and it buys users nothing they can't already do. It exists so the internal EE image can drop the postgres layers now.Notes for review
Dockerfileand thetolgee/tolgeetag are untouched.enabled=trueandmode=EMBEDDED, so it stays silent for external-database setups and for Java +DOCKERautostart (that mode isn't going away).docker-slim-smokeboots the slim image against a postgres service and waits for/actuator/health.