Skip to content

fix: seed nonroot-owned data dir in release Docker image - #49

Merged
leonid-shevtsov merged 1 commit into
mainfrom
fix/docker-volume-nonroot-ownership
Aug 3, 2026
Merged

fix: seed nonroot-owned data dir in release Docker image#49
leonid-shevtsov merged 1 commit into
mainfrom
fix/docker-volume-nonroot-ownership

Conversation

@leonid-shevtsov

@leonid-shevtsov leonid-shevtsov commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

What & why

Release image (Dockerfile.goreleaser) declared VOLUME /var/lib/mailtrap-local but never created that directory owned by distroless nonroot (UID 65532). Empty anonymous/named volumes then mounted as root:root, so the process could not create db.sqlite3 (unable to open database file (14)). --tmpfs worked because it is world-writable.

Fix: alpine stage seeds an empty dir; COPY --chown=nonroot:nonroot into the image (same pattern as the source-build Dockerfile). Ownership comes from --chown only — no redundant RUN chown.

CI: the docker job now also builds Dockerfile.goreleaser (reuses the binary from the source image) and boots it on the default CMD, so this class of VOLUME/ownership regression cannot slip past again.

Local smoke (linux/arm64 binary + docker build -f Dockerfile.goreleaser):

  • Broken (pre-fix): -v /var/lib/mailtrap-localopen store / unable to open database file (14)
  • Fixed: anonymous -v /var/lib/mailtrap-local → SMTP + HTTP listening; wrote secret.key + db.sqlite3
  • Fixed: named volume → same; volume root owned 65532:65532

How to test

  • docker run --rm -p 3535:3535 -p 3550:3550 -v /var/lib/mailtrap-local mailtrap/mailtrap-local:<this-build> starts without DB errors; UI at http://127.0.0.1:3550
  • Same with -v mailtrap-local:/var/lib/mailtrap-local (fresh named volume); no manual chown
  • CI docker job green (source Dockerfile + goreleaser image boots)

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The release Dockerfile adds an Alpine preparation stage that seeds /var/lib/mailtrap-local and assigns ownership to UID/GID 65532. The final distroless image copies the prepared directory and binary with nonroot ownership.

Changes

Release image filesystem setup

Layer / File(s) Summary
Seed and ownership setup
Dockerfile.goreleaser
An Alpine stage creates /data-empty, assigns it to the nonroot UID/GID, and the final image copies it into /var/lib/mailtrap-local alongside the binary.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • mailtrap/mailtrap-local#3: Also updates Dockerfile.goreleaser around the persisted data directory and its use for encryption state.

Suggested reviewers: sergeykorolev

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main change: seeding the nonroot-owned data directory in the release Docker image.
Description check ✅ Passed The description covers motivation, changes, and testing, with only a non-critical Images and GIFs section missing.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Anonymous/named Docker volumes inherited root ownership when
/var/lib/mailtrap-local was missing from the image, so SQLite
failed with unable to open database file (14). Match Dockerfile
by seeding the path from an alpine stage as UID 65532.

Co-authored-by: Cursor <cursoragent@cursor.com>
@leonid-shevtsov
leonid-shevtsov requested a review from Rabsztok July 31, 2026 14:29
@leonid-shevtsov
leonid-shevtsov merged commit 14b77b3 into main Aug 3, 2026
5 checks passed
@leonid-shevtsov
leonid-shevtsov deleted the fix/docker-volume-nonroot-ownership branch August 3, 2026 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants