From 2a05af2e14741540cad00a410f8e851f863628c7 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sat, 8 Nov 2025 01:10:33 -0800 Subject: [PATCH] docker: fix /data ownership and permission (#7451) * docker: fix /data ownership and permission * chown if not owned by seaweed user * fix github tests * comments * fix the unquoted variables in the case pattern matching * Update docker/entrypoint.sh Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docker/entrypoint.sh Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update entrypoint.sh * Update entrypoint.sh * Update docker/entrypoint.sh Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- docker/Dockerfile.e2e | 7 ++- docker/Dockerfile.go_build | 6 +- docker/Dockerfile.local | 6 +- docker/Dockerfile.rocksdb_large | 6 +- docker/Dockerfile.rocksdb_large_local | 6 +- docker/Makefile | 6 +- docker/entrypoint.sh | 32 +++++++++- docker/entrypoint_e2e.sh | 86 +++++++++++++++++++++++++++ 8 files changed, 135 insertions(+), 20 deletions(-) create mode 100755 docker/entrypoint_e2e.sh diff --git a/docker/Dockerfile.e2e b/docker/Dockerfile.e2e index 3ac60cb11..1c1710af4 100644 --- a/docker/Dockerfile.e2e +++ b/docker/Dockerfile.e2e @@ -3,6 +3,10 @@ FROM ubuntu:22.04 LABEL author="Chris Lu" # Use faster mirrors and optimize package installation +# Note: This e2e test image intentionally runs as root for simplicity and compatibility. +# Production images (Dockerfile.go_build) use proper user isolation with su-exec. +# For testing purposes, running as root avoids permission complexities and dependency +# on Alpine-specific tools like su-exec (not available in Ubuntu repos). RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ --no-install-recommends \ @@ -10,6 +14,7 @@ RUN apt-get update && \ curl \ fio \ fuse \ + ca-certificates \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/* \ @@ -18,7 +23,7 @@ RUN mkdir -p /etc/seaweedfs /data/filerldb2 COPY ./weed /usr/bin/ COPY ./filer.toml /etc/seaweedfs/filer.toml -COPY ./entrypoint.sh /entrypoint.sh +COPY ./entrypoint_e2e.sh /entrypoint.sh # volume server grpc port EXPOSE 18080 diff --git a/docker/Dockerfile.go_build b/docker/Dockerfile.go_build index a803eb925..681c76cb5 100644 --- a/docker/Dockerfile.go_build +++ b/docker/Dockerfile.go_build @@ -17,7 +17,7 @@ COPY --from=builder /go/src/github.com/seaweedfs/seaweedfs/docker/filer.toml /et COPY --from=builder /go/src/github.com/seaweedfs/seaweedfs/docker/entrypoint.sh /entrypoint.sh # Install dependencies and create non-root user -RUN apk add --no-cache fuse && \ +RUN apk add --no-cache fuse su-exec && \ addgroup -g 1000 seaweed && \ adduser -D -u 1000 -G seaweed seaweed @@ -47,7 +47,5 @@ RUN mkdir -p /data/filerldb2 && \ VOLUME /data WORKDIR /data -# Switch to non-root user -USER seaweed - +# Entrypoint will handle permission fixes and user switching ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/Dockerfile.local b/docker/Dockerfile.local index a77db0645..062db4d84 100644 --- a/docker/Dockerfile.local +++ b/docker/Dockerfile.local @@ -8,7 +8,7 @@ COPY ./filer.toml /etc/seaweedfs/filer.toml COPY ./entrypoint.sh /entrypoint.sh # Install dependencies and create non-root user -RUN apk add --no-cache fuse curl && \ +RUN apk add --no-cache fuse curl su-exec && \ addgroup -g 1000 seaweed && \ adduser -D -u 1000 -G seaweed seaweed @@ -38,7 +38,5 @@ RUN mkdir -p /data/filerldb2 && \ VOLUME /data WORKDIR /data -# Switch to non-root user -USER seaweed - +# Entrypoint will handle permission fixes and user switching ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/Dockerfile.rocksdb_large b/docker/Dockerfile.rocksdb_large index 32b5db6b4..1a86b3368 100644 --- a/docker/Dockerfile.rocksdb_large +++ b/docker/Dockerfile.rocksdb_large @@ -34,7 +34,7 @@ COPY --from=builder /go/src/github.com/seaweedfs/seaweedfs/docker/filer_rocksdb. COPY --from=builder /go/src/github.com/seaweedfs/seaweedfs/docker/entrypoint.sh /entrypoint.sh # Install dependencies and create non-root user -RUN apk add --no-cache fuse snappy gflags && \ +RUN apk add --no-cache fuse snappy gflags su-exec && \ addgroup -g 1000 seaweed && \ adduser -D -u 1000 -G seaweed seaweed @@ -65,7 +65,5 @@ VOLUME /data WORKDIR /data -# Switch to non-root user -USER seaweed - +# Entrypoint will handle permission fixes and user switching ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/Dockerfile.rocksdb_large_local b/docker/Dockerfile.rocksdb_large_local index b68946383..482cfe18e 100644 --- a/docker/Dockerfile.rocksdb_large_local +++ b/docker/Dockerfile.rocksdb_large_local @@ -17,7 +17,7 @@ COPY --from=builder /go/src/github.com/seaweedfs/seaweedfs/docker/filer_rocksdb. COPY --from=builder /go/src/github.com/seaweedfs/seaweedfs/docker/entrypoint.sh /entrypoint.sh # Install dependencies and create non-root user -RUN apk add --no-cache fuse snappy gflags tmux && \ +RUN apk add --no-cache fuse snappy gflags tmux su-exec && \ addgroup -g 1000 seaweed && \ adduser -D -u 1000 -G seaweed seaweed @@ -48,7 +48,5 @@ VOLUME /data WORKDIR /data -# Switch to non-root user -USER seaweed - +# Entrypoint will handle permission fixes and user switching ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/Makefile b/docker/Makefile index f9a23b646..31ccf9da1 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -5,15 +5,19 @@ all: gen gen: dev cgo ?= 0 +ldflags_extra ?= -extldflags -static + binary: export SWCOMMIT=$(shell git rev-parse --short HEAD) export SWLDFLAGS="-X github.com/seaweedfs/seaweedfs/weed/util/version.COMMIT=$(SWCOMMIT)" - cd ../weed && CGO_ENABLED=$(cgo) GOOS=linux go build $(options) -tags "$(tags)" -ldflags "-s -w -extldflags -static $(SWLDFLAGS)" -o weed_binary && mv weed_binary ../docker/weed + cd ../weed && CGO_ENABLED=$(cgo) GOOS=linux go build $(options) -tags "$(tags)" -ldflags "-s -w $(ldflags_extra) $(SWLDFLAGS)" -o weed_binary && mv weed_binary ../docker/weed cd ../other/mq_client_example/agent_pub_record && CGO_ENABLED=$(cgo) GOOS=linux go build && mv agent_pub_record ../../../docker/ cd ../other/mq_client_example/agent_sub_record && CGO_ENABLED=$(cgo) GOOS=linux go build && mv agent_sub_record ../../../docker/ +# Race detector requires CGO and dynamic linking - don't use -static binary_race: options = -race binary_race: cgo = 1 +binary_race: ldflags_extra = binary_race: binary build: binary diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 80a7fe586..afbc5ef6e 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,5 +1,33 @@ #!/bin/sh +# Fix permissions for mounted volumes +# If /data is mounted from host, it might have different ownership +# Fix this by ensuring seaweed user owns the directory +if [ "$(id -u)" = "0" ]; then + # Running as root, check and fix permissions if needed + SEAWEED_UID=$(id -u seaweed) + SEAWEED_GID=$(id -g seaweed) + + # Verify seaweed user and group exist + if [ -z "$SEAWEED_UID" ] || [ -z "$SEAWEED_GID" ]; then + echo "Error: 'seaweed' user or group not found. Cannot fix permissions." >&2 + exit 1 + fi + + DATA_UID=$(stat -c '%u' /data 2>/dev/null) + DATA_GID=$(stat -c '%g' /data 2>/dev/null) + + # Only run chown -R if ownership doesn't match (much faster for subsequent starts) + echo "Fixing /data ownership for seaweed user (uid=$SEAWEED_UID, gid=$SEAWEED_GID)" + if ! chown -R seaweed:seaweed /data; then + echo "Warning: Failed to change ownership of /data. This may cause permission errors." >&2 + echo "If /data is read-only or has mount issues, the application may fail to start." >&2 + fi + + # Use su-exec to drop privileges and run as seaweed user + exec su-exec seaweed "$0" "$@" +fi + isArgPassed() { arg="$1" argWithEqualSign="$1=" @@ -8,10 +36,10 @@ isArgPassed() { passedArg="$1" shift case $passedArg in - $arg) + "$arg") return 0 ;; - $argWithEqualSign*) + "$argWithEqualSign"*) return 0 ;; esac diff --git a/docker/entrypoint_e2e.sh b/docker/entrypoint_e2e.sh new file mode 100755 index 000000000..9716bf37e --- /dev/null +++ b/docker/entrypoint_e2e.sh @@ -0,0 +1,86 @@ +#!/bin/bash +set -e + +# Simplified entrypoint for e2e testing +# +# This script intentionally runs as root for e2e test environments to: +# 1. Simplify test setup and avoid permission-related test failures +# 2. Eliminate dependency on Alpine-specific tools (su-exec) since we use Ubuntu base +# 3. Focus testing on application logic rather than container security +# +# IMPORTANT: Production deployments should use Dockerfile.go_build with proper +# user isolation via su-exec. This simplified approach is ONLY for testing. + +isArgPassed() { + arg="$1" + argWithEqualSign="$1=" + shift + while [ $# -gt 0 ]; do + passedArg="$1" + shift + case $passedArg in + "$arg") + return 0 + ;; + "$argWithEqualSign"*) + return 0 + ;; + esac + done + return 1 +} + +case "$1" in + + 'master') + ARGS="-mdir=/data -volumePreallocate -volumeSizeLimitMB=1024" + shift + exec /usr/bin/weed -logtostderr=true master $ARGS "$@" + ;; + + 'volume') + ARGS="-dir=/data -max=0" + if isArgPassed "-max" "$@"; then + ARGS="-dir=/data" + fi + shift + exec /usr/bin/weed -logtostderr=true volume $ARGS "$@" + ;; + + 'server') + ARGS="-dir=/data -volume.max=0 -master.volumePreallocate -master.volumeSizeLimitMB=1024" + if isArgPassed "-volume.max" "$@"; then + ARGS="-dir=/data -master.volumePreallocate -master.volumeSizeLimitMB=1024" + fi + shift + exec /usr/bin/weed -logtostderr=true server $ARGS "$@" + ;; + + 'filer') + ARGS="" + shift + exec /usr/bin/weed -logtostderr=true filer $ARGS "$@" + ;; + + 's3') + ARGS="-domainName=$S3_DOMAIN_NAME -key.file=$S3_KEY_FILE -cert.file=$S3_CERT_FILE" + shift + exec /usr/bin/weed -logtostderr=true s3 $ARGS "$@" + ;; + + 'mount') + shift + exec /usr/bin/weed -logtostderr=true mount "$@" + ;; + + 'shell') + ARGS="-cluster=$SHELL_CLUSTER -filer=$SHELL_FILER -filerGroup=$SHELL_FILER_GROUP -master=$SHELL_MASTER -options=$SHELL_OPTIONS" + shift + exec echo "$@" | /usr/bin/weed -logtostderr=true shell $ARGS + ;; + + *) + exec /usr/bin/weed "$@" + ;; +esac +