mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 19:21:33 +02:00
Two related failure modes have been biting Docker users repeatedly, most recently in #1211: 1. Docker named volumes are created by the daemon as root:root, and the previous `chmod 777 /app/data` Dockerfile workaround only covered the named-volume root — so subdirs Bambuddy creates at runtime (virtual_printer/uploads, virtual_printer/certs, etc.) inherited wrong ownership when the container ran as 1000:1000. 2. The shipped docker-compose.yml ships `./virtual_printer:/app/data/virtual_printer` uncommented, and dockerd creates a missing bind-mount source on the host as root before the container starts — leaving the host directory unwritable by uid 1000 inside the container even though the named volume above it had the chmod-777 workaround. Symptom either way: [Errno 13] Permission denied: '/app/data/virtual_printer/uploads', no virtual printer ever starts, "VP doesn't work" support reports follow. Replace the chmod-777 hack with a proper entrypoint: - deploy/docker-entrypoint.sh runs as root, chowns /app/data and /app/logs (and /app/data/virtual_printer when bind-mounted) to PUID:PGID, then drops to that uid via gosu before exec'ing the app. The chown is gated behind a top-level ownership check so subsequent restarts skip the recursive traversal — no multi- second startup penalty on multi-GB archive directories. - A sentinel .bambuddy file in each data path prevents Docker from re-syncing image directory metadata on every mount (otherwise empty volumes have their ownership reverted from the image on each restart, defeating the idempotency). - When the container is started with an explicit `user:` directive or `--user` flag the entrypoint detects it isn't root and falls through to direct exec — preserving compatibility for users who pin a specific uid. Compose template changes: - Remove `user: "${PUID:-1000}:${PGID:-1000}"` (entrypoint owns privilege drop now). - Add PUID / PGID env vars with the same defaults. - Comment out the ./virtual_printer:/app/data/virtual_printer bind mount by default, with explicit "only needed if you also run a native install of Bambuddy on the same host and want both to share the VP CA cert" guidance. The entrypoint chowns the host-side dir through the bind mount the first time it sees wrong ownership, so existing uncomented installs continue to work and #1211 specifically gets fixed.
69 lines
2.9 KiB
Bash
Executable File
69 lines
2.9 KiB
Bash
Executable File
#!/bin/sh
|
|
# Bambuddy container entrypoint.
|
|
#
|
|
# Runs as root (the image leaves USER unset, so containers start as
|
|
# root by default), chowns /app/data and /app/logs to PUID:PGID, then
|
|
# drops to PUID:PGID via gosu and execs the application. This fixes the
|
|
# class of "Permission denied" errors that bit users when:
|
|
#
|
|
# - a Docker named volume was first created with root ownership and
|
|
# the container was running with `user: 1000:1000` (named volumes
|
|
# created by the daemon take its ownership; Dockerfile chmod hacks
|
|
# cover the parent path but not subdirs created at runtime).
|
|
# - a bind-mount source path didn't exist on the host yet, so dockerd
|
|
# created it as root before the container started, leaving it
|
|
# unwritable by uid 1000 inside the container — see #1211 / #668
|
|
# for the virtual_printer bind-mount case the shipped compose
|
|
# template ships uncommented.
|
|
#
|
|
# If the container is started with an explicit `user:` directive
|
|
# (compose `user:` or `docker run --user`), the entrypoint runs as that
|
|
# user instead of root and chown isn't possible. The script falls
|
|
# through to direct exec without modifying ownership — preserving the
|
|
# previous behavior for users who pin a specific uid via compose.
|
|
|
|
set -eu
|
|
|
|
# Default to 1000:1000 to match the legacy `user: "1000:1000"` default
|
|
# in our previously-shipped compose template; overridable via env so
|
|
# users who run docker as a different uid can match their host without
|
|
# editing the compose user: directive.
|
|
PUID="${PUID:-1000}"
|
|
PGID="${PGID:-1000}"
|
|
|
|
# If we're not root, we can't chown anything. Exec the original command
|
|
# and trust that the user has set up host-side ownership themselves.
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
exec "$@"
|
|
fi
|
|
|
|
# `chown -R` is gated behind a top-level ownership check so a correctly-
|
|
# owned directory isn't traversed on every container start. A user with
|
|
# a multi-GB archive directory would otherwise pay seconds-to-minutes
|
|
# of chown traversal at every restart.
|
|
chown_if_needed() {
|
|
target="$1"
|
|
[ -d "$target" ] || mkdir -p "$target"
|
|
current="$(stat -c '%u:%g' "$target" 2>/dev/null || echo '')"
|
|
if [ "$current" != "$PUID:$PGID" ]; then
|
|
echo "[entrypoint] chown -R ${PUID}:${PGID} ${target}"
|
|
chown -R "${PUID}:${PGID}" "$target" || true
|
|
fi
|
|
}
|
|
|
|
chown_if_needed /app/data
|
|
chown_if_needed /app/logs
|
|
|
|
# Bind-mount-source path needs the same treatment when present. dockerd
|
|
# creates missing bind-mount sources as root on the host before the
|
|
# container starts; the chown here propagates through the bind mount to
|
|
# the host-side directory and fixes the issue once and for all.
|
|
if [ -d /app/data/virtual_printer ]; then
|
|
chown_if_needed /app/data/virtual_printer
|
|
fi
|
|
|
|
# Drop privileges and run the application. python's file capabilities
|
|
# (cap_net_bind_service=+ep, set in the Dockerfile) survive the uid
|
|
# switch, so binding to :322 / :990 still works post-drop.
|
|
exec gosu "${PUID}:${PGID}" "$@"
|