From 619d4e9575b04cb5d6e534aa96b5df8aa5382d4f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Oct 2025 13:32:01 +0000 Subject: [PATCH] Implement Docker rootless user with reviewer feedback improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit implements the rootless user functionality for both production and development Docker images with all improvements from PR #837 review: Changes made: - Added rootless user setup using 'rails' username (not 'rails_api_base') - Used ARG instead of ENV for USERNAME, USER_UID, and USER_GID build variables - Set proper file ownership and permissions (700) for security - Added explanatory comment for temporary root switch in jemalloc symlink creation - Applied --chown and --chmod flags to all COPY operations Security improvements: - Application now runs as non-root user (UID/GID 1000) - Reduced attack surface by limiting privileges - Follows Docker security best practices Files modified: - Dockerfile: Added rootless user for production image - Dockerfile.dev: Added rootless user for development image 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- Dockerfile | 31 ++++++++++++++++++++++++------- Dockerfile.dev | 23 ++++++++++++++++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index b5e0804a..3046df29 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,19 +61,36 @@ RUN apt-get update -qq && \ apt-get install --no-install-recommends -y curl libpq-dev libvips libjemalloc2 libyaml-dev && \ apt-get clean && rm -rf /var/lib/apt/lists/* -# Create app directory. -RUN mkdir -p "${APP_HOME}" +# Setup rootless user for security +ARG USERNAME=rails +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid $USER_GID $USERNAME && \ + useradd --uid $USER_UID --gid $USER_GID -m $USERNAME + +# Create app directory with proper ownership +RUN mkdir -p "${APP_HOME}" && \ + chown -R $USERNAME:$USERNAME $APP_HOME && \ + chmod -R 700 $APP_HOME + +# Switch to non-root user +USER $USERNAME # Setup work directory. WORKDIR $APP_HOME -# Copy everything from the builder image -COPY --link . . -COPY --from=builder $APP_HOME/public/ $APP_HOME/public/ -COPY --from=builder $APP_HOME/tmp/ $APP_HOME/tmp/ -COPY --from=builder $APP_HOME/vendor/ $APP_HOME/vendor/ +# Copy everything from the builder image with proper ownership +COPY --link --chown=$USERNAME:$USERNAME --chmod=700 . . +COPY --from=builder --chown=$USERNAME:$USERNAME --chmod=700 $APP_HOME/public/ $APP_HOME/public/ +COPY --from=builder --chown=$USERNAME:$USERNAME --chmod=700 $APP_HOME/tmp/ $APP_HOME/tmp/ +COPY --from=builder --chown=$USERNAME:$USERNAME --chmod=700 $APP_HOME/vendor/ $APP_HOME/vendor/ +# Temporarily switch to root to create system-level symlink for jemalloc +# This is required because symlink creation in /usr/lib requires root privileges +USER root RUN ln -s /usr/lib/*-linux-gnu/libjemalloc.so.2 /usr/lib/libjemalloc.so.2 +USER $USERNAME # Deployment options ENV RAILS_LOG_TO_STDOUT=true diff --git a/Dockerfile.dev b/Dockerfile.dev index 30916f82..c5ca41ae 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -20,8 +20,21 @@ ENV WORK_ROOT=/src ENV APP_HOME=$WORK_ROOT/app/ ENV LANG=C.UTF-8 -# Create app directory. -RUN mkdir -p $APP_HOME +# Setup rootless user for security +ARG USERNAME=rails +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid $USER_GID $USERNAME && \ + useradd --uid $USER_UID --gid $USER_GID -m $USERNAME + +# Create app directory with proper ownership +RUN mkdir -p $APP_HOME && \ + chown -R $USERNAME:$USERNAME $APP_HOME && \ + chmod -R 700 $APP_HOME + +# Switch to non-root user +USER $USERNAME # Setup work directory. WORKDIR $APP_HOME @@ -29,15 +42,15 @@ WORKDIR $APP_HOME RUN gem install foreman bundler # Copy dependencies files and install libraries. -COPY --link package.json yarn.lock .yarnrc.yml ./ +COPY --link --chown=$USERNAME:$USERNAME --chmod=700 package.json yarn.lock .yarnrc.yml ./ RUN corepack enable RUN yarn install --immutable && yarn cache clean -COPY --link Gemfile Gemfile.lock .ruby-version ./ +COPY --link --chown=$USERNAME:$USERNAME --chmod=700 Gemfile Gemfile.lock .ruby-version ./ RUN bundle install -j 4 -COPY --link . . +COPY --link --chown=$USERNAME:$USERNAME --chmod=700 . . RUN yarn build