diff --git a/Dockerfile b/Dockerfile index 447ed98b5e..06b7075b2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,6 +48,10 @@ FROM ${BASE_IMAGE} AS subtensor # ---- security hardening: create least-privilege user ---- RUN addgroup --system --gid 10001 subtensor && \ adduser --system --uid 10001 --gid 10001 --home /home/subtensor --disabled-password subtensor + +# Install gosu for privilege dropping +RUN apt-get update && apt-get install -y gosu && \ + rm -rf /var/lib/apt/lists/* # Writable data directory to be used as --base-path RUN mkdir -p /data && chown -R subtensor:subtensor /data @@ -61,10 +65,17 @@ COPY --chown=subtensor:subtensor --from=prod_builder /build/chainspecs/*.json ./ COPY --from=prod_builder /build/target/production/node-subtensor /usr/local/bin/ RUN chown subtensor:subtensor /usr/local/bin/node-subtensor +# Copy and prepare entrypoint +COPY ./scripts/docker_entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + EXPOSE 30333 9933 9944 -USER subtensor -ENTRYPOINT ["node-subtensor"] -CMD ["--base-path","/data"] + +# Run entrypoint as root to handle permissions, then drop to subtensor user +# in the script +USER root +ENTRYPOINT ["/entrypoint.sh"] +CMD ["--base-path", "/data"] ############################################################################### # ---------- 4. Local build stage -------------------------------------------- @@ -84,6 +95,10 @@ FROM ${BASE_IMAGE} AS subtensor-local RUN addgroup --system --gid 10001 subtensor && \ adduser --system --uid 10001 --gid 10001 --home /home/subtensor --disabled-password subtensor +# Install gosu for privilege dropping +RUN apt-get update && apt-get install -y gosu && \ + rm -rf /var/lib/apt/lists/* + RUN mkdir -p /data && chown -R subtensor:subtensor /data WORKDIR /home/subtensor @@ -93,11 +108,18 @@ COPY --chown=subtensor:subtensor --from=local_builder /build/chainspecs/*.json . COPY --from=local_builder /build/target/release/node-subtensor /usr/local/bin/ RUN chown subtensor:subtensor /usr/local/bin/node-subtensor +# Copy and prepare entrypoint +COPY ./scripts/docker_entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + # Generate a local chainspec for convenience (run as root before user switch) RUN node-subtensor build-spec --disable-default-bootnode --raw --chain local > /localnet.json \ && chown subtensor:subtensor /localnet.json EXPOSE 30333 9933 9944 -USER subtensor -ENTRYPOINT ["node-subtensor"] + +# Run entrypoint as root to handle permissions, then drop to subtensor user +# in the script +USER root +ENTRYPOINT ["/entrypoint.sh"] CMD ["--base-path","/data","--chain","/localnet.json"] diff --git a/scripts/docker_entrypoint.sh b/scripts/docker_entrypoint.sh new file mode 100644 index 0000000000..e5a5e15289 --- /dev/null +++ b/scripts/docker_entrypoint.sh @@ -0,0 +1,56 @@ +#!/bin/sh +set -e + +# Store original arguments to pass to the final exec call +original_args="$@" + +# Set default values +base_path='/data' +chain_spec='' + +# Parse arguments to find the real --base-path and --chain, handles both +# --key value and --key=value formats. +while [ $# -gt 0 ]; do + case "$1" in + --base-path) + # Check if the next argument exists and is not another option + if [ -n "$2" ] && ! expr "$2" : '--' > /dev/null; then + base_path="$2" + shift + fi + ;; + --base-path=*) + base_path="${1#*=}" + ;; + --chain) + # Check if the next argument exists and is not another option + if [ -n "$2" ] && ! expr "$2" : '--' > /dev/null; then + chain_spec="$2" + shift + fi + ;; + --chain=*) + chain_spec="${1#*=}" + ;; + esac + shift +done + +echo "entrypoint: ensuring permissions for base path: ${base_path}" +mkdir -p "$base_path" +chown -R subtensor:subtensor "$base_path" + +# Check if a chain spec was provided and if it's an existing file +if [ -n "$chain_spec" ] && [ -f "$chain_spec" ]; then + echo "entrypoint: ensuring permissions for chain spec: ${chain_spec}" + chown subtensor:subtensor "$chain_spec" +fi + +# Also check for the hardcoded /tmp/blockchain directory +if [ -d "/tmp/blockchain" ]; then + chown -R subtensor:subtensor /tmp/blockchain +fi + +# Execute node-subtensor with the original, unmodified arguments +echo "executing: gosu subtensor node-subtensor $original_args" +exec gosu subtensor node-subtensor $original_args \ No newline at end of file