|
|
@@ -0,0 +1,68 @@
|
|
|
+#!/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}" "$@"
|