mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-31 20:58:04 +00:00
fix(docker): repair broken entrypoint from bad merge conflict resolution
The merge of PR58 into PR59's branch produced a corrupt docker-entrypoint.sh (97 lines) where PR59's if block was cut off mid-way (missing exec su-exec and closing fi) and then PR58's entire if block was appended. This caused: /usr/local/bin/docker-entrypoint.sh: line 98: syntax error: unexpected end of file (expecting "fi") Fix: overwrite with the clean 71-line version and add a defensive `sed -i 's/\r//'` step in the Dockerfile to strip Windows CRLF line endings at build time, preventing this class of error even if CRLF slips past .gitattributes in future.
This commit is contained in:
+5
-1
@@ -75,7 +75,11 @@ RUN addgroup -S sencho && adduser -S -G sencho sencho \
|
|||||||
# security scanners (Trivy, Clair) may flag "running as root" — this is a known
|
# security scanners (Trivy, Clair) may flag "running as root" — this is a known
|
||||||
# and accepted trade-off for self-hosted apps with user-supplied volume mounts.
|
# and accepted trade-off for self-hosted apps with user-supplied volume mounts.
|
||||||
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
# Strip Windows CRLF line endings that can sneak in on Windows dev machines
|
||||||
|
# even with .gitattributes eol=lf, then make executable. A shell script with
|
||||||
|
# \r in tokens like "fi\r" will fail with "unexpected end of file" in Alpine.
|
||||||
|
RUN sed -i 's/\r//' /usr/local/bin/docker-entrypoint.sh \
|
||||||
|
&& chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
# Expose port
|
# Expose port
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|||||||
+8
-42
@@ -17,7 +17,7 @@ DATA_DIR="${DATA_DIR:-/app/data}"
|
|||||||
# exec's directly without crashing.
|
# exec's directly without crashing.
|
||||||
if [ "$(id -u)" = '0' ]; then
|
if [ "$(id -u)" = '0' ]; then
|
||||||
|
|
||||||
# ── 1. Fix data volume ownership ────────────────────────────────────────
|
# 1. Fix data volume ownership.
|
||||||
# Handles host volumes previously created by root or a different UID, which
|
# Handles host volumes previously created by root or a different UID, which
|
||||||
# would cause SQLITE_READONLY errors when the non-root sencho user starts.
|
# would cause SQLITE_READONLY errors when the non-root sencho user starts.
|
||||||
# Only touches files with wrong user OR group (efficient on large dirs).
|
# Only touches files with wrong user OR group (efficient on large dirs).
|
||||||
@@ -26,25 +26,17 @@ if [ "$(id -u)" = '0' ]; then
|
|||||||
-exec chown sencho:sencho '{}' +
|
-exec chown sencho:sencho '{}' +
|
||||||
echo "[entrypoint] Data directory ownership ensured: $DATA_DIR"
|
echo "[entrypoint] Data directory ownership ensured: $DATA_DIR"
|
||||||
|
|
||||||
# ── 2. Fix Docker socket group access ───────────────────────────────────
|
# 2. Fix Docker socket group access.
|
||||||
# The Docker socket on the host is owned by the host's docker group, whose
|
# The Docker socket on the host is owned by the host's docker group, whose
|
||||||
# GID varies by Linux distribution and does not match any group inside the
|
# GID varies by Linux distribution and does not match any group inside the
|
||||||
# container by default.
|
# container by default.
|
||||||
#
|
|
||||||
# Solution: detect the socket's GID at runtime, create a matching group
|
|
||||||
# inside the container if one doesn't already exist, then add sencho to it.
|
|
||||||
# su-exec calls getgrouplist() which reads /etc/group, so supplementary
|
|
||||||
# groups added here ARE inherited by the Node process.
|
|
||||||
if [ -S /var/run/docker.sock ]; then
|
if [ -S /var/run/docker.sock ]; then
|
||||||
DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock)
|
DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock)
|
||||||
DOCKER_SOCK_MODE=$(stat -c '%a' /var/run/docker.sock)
|
DOCKER_SOCK_MODE=$(stat -c '%a' /var/run/docker.sock)
|
||||||
echo "[entrypoint] Docker socket found: GID=$DOCKER_SOCK_GID mode=$DOCKER_SOCK_MODE"
|
echo "[entrypoint] Docker socket found: GID=$DOCKER_SOCK_GID mode=$DOCKER_SOCK_MODE"
|
||||||
|
|
||||||
if [ "$DOCKER_SOCK_GID" = "0" ]; then
|
if [ "$DOCKER_SOCK_GID" = "0" ]; then
|
||||||
# Socket is owned by root:root. The only way to access it without
|
echo "[entrypoint] WARNING: Docker socket is root:root -- adding sencho to root group"
|
||||||
# running as root is to make it group-readable and assign a shared
|
|
||||||
# group. We create a 'docker-sock' group with GID 0 for clarity.
|
|
||||||
echo "[entrypoint] WARNING: Docker socket is root:root — adding sencho to root group"
|
|
||||||
addgroup sencho root 2>/dev/null || true
|
addgroup sencho root 2>/dev/null || true
|
||||||
else
|
else
|
||||||
if ! getent group "$DOCKER_SOCK_GID" > /dev/null 2>&1; then
|
if ! getent group "$DOCKER_SOCK_GID" > /dev/null 2>&1; then
|
||||||
@@ -56,41 +48,15 @@ if [ "$(id -u)" = '0' ]; then
|
|||||||
echo "[entrypoint] Added sencho to group '$DOCKER_GROUP' (GID $DOCKER_SOCK_GID)"
|
echo "[entrypoint] Added sencho to group '$DOCKER_GROUP' (GID $DOCKER_SOCK_GID)"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "[entrypoint] WARNING: /var/run/docker.sock not found — Docker features will be unavailable"
|
echo "[entrypoint] WARNING: /var/run/docker.sock not found -- Docker features unavailable"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[entrypoint] Dropping privileges to sencho (uid=$(id -u sencho))"
|
echo "[entrypoint] Dropping privileges to sencho (uid=$(id -u sencho))"
|
||||||
|
|
||||||
# ── 3. Drop privileges ──────────────────────────────────────────────────
|
# 3. Drop privileges.
|
||||||
# Replace this shell process with su-exec so that Node becomes PID 1 and
|
# Replace this shell with su-exec so Node becomes PID 1 and receives
|
||||||
# receives SIGTERM/SIGINT directly from Docker. su-exec calls getgrouplist()
|
# SIGTERM/SIGINT directly. su-exec calls getgrouplist() for named users,
|
||||||
# for named users, so all supplementary groups set above are inherited.
|
# so all supplementary groups added above are inherited by the process.
|
||||||
# If running as root (the default Docker container start), fix volume ownership
|
|
||||||
# then drop privileges before executing the application.
|
|
||||||
#
|
|
||||||
# This handles the common case where the host-mounted data volume was created by
|
|
||||||
# root (or a different UID) from a previous run or backup restore — causing
|
|
||||||
# SQLITE_READONLY errors when the non-root sencho user tries to write.
|
|
||||||
#
|
|
||||||
# This is the industry-standard pattern used by the official PostgreSQL, Redis,
|
|
||||||
# and MariaDB Docker images.
|
|
||||||
#
|
|
||||||
# The UID guard also ensures compatibility with strict environments like
|
|
||||||
# Kubernetes (runAsNonRoot: true) or OpenShift, where the container is forced to
|
|
||||||
# run as a random high UID. In that case the chown block is skipped entirely and
|
|
||||||
# the app exec's directly without crashing.
|
|
||||||
if [ "$(id -u)" = '0' ]; then
|
|
||||||
mkdir -p "$DATA_DIR"
|
|
||||||
|
|
||||||
# Fix files where user OR group is wrong — not just user. This covers the
|
|
||||||
# case where a file ends up as sencho:root after a partial previous fix.
|
|
||||||
# The -exec '{}' + form batches arguments for efficiency (like xargs).
|
|
||||||
find "$DATA_DIR" \( \! -user sencho -o \! -group sencho \) \
|
|
||||||
-exec chown sencho:sencho '{}' +
|
|
||||||
|
|
||||||
# Replace this shell process with su-exec so that Node becomes PID 1 and
|
|
||||||
# receives SIGTERM/SIGINT directly from Docker. Without exec the shell would
|
|
||||||
# intercept signals and the container would hang for 10s before SIGKILL.
|
|
||||||
exec su-exec sencho "$@"
|
exec su-exec sencho "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user