From 7082c299fb3940d41cf40261f0072c205ef1762b Mon Sep 17 00:00:00 2001 From: compwron Date: Thu, 23 Apr 2026 22:45:40 -0700 Subject: [PATCH 1/2] Improve Dockerfile security, layering, and dev/prod parity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Run app as non-root user (addgroup/adduser + USER app) - Remove vim from production image - Fix ARG ROOT: remove no-op global declaration, add default per-stage - Copy package*.json before COPY . . to improve npm layer caching - Replace fragile npm symlink with direct COPY from node-source - Add apk cache cleanup to build stage - Align devcontainer Ruby version with production (3.3 → 4.0) Co-Authored-By: Claude Sonnet 4.6 --- .devcontainer/Dockerfile | 2 +- Dockerfile | 20 ++++++++++++-------- Gemfile.lock | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 6080811e25..d133406b0c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,2 +1,2 @@ -FROM mcr.microsoft.com/devcontainers/ruby:dev-3.3-bookworm +FROM mcr.microsoft.com/devcontainers/ruby:dev-4.0-bookworm RUN apt-get update && apt-get install -y vim curl gpg postgresql postgresql-contrib tzdata imagemagick diff --git a/Dockerfile b/Dockerfile index ade5d92371..df6c488ef8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,9 @@ -ARG ROOT=/usr/src/app/ - # available alpine packages: https://pkgs.alpinelinux.org/packages FROM node:24-alpine AS node-source FROM ruby:4.0.2-alpine AS build - ARG ROOT + ARG ROOT=/usr/src/app/ WORKDIR $ROOT RUN apk update && apk upgrade && apk add --update --no-cache \ @@ -15,7 +13,8 @@ FROM ruby:4.0.2-alpine AS build yaml-dev \ linux-headers \ postgresql-dev \ - tzdata + tzdata \ + && rm -rf /var/cache/apk/* RUN bundle config set force_ruby_platform true @@ -23,7 +22,7 @@ FROM ruby:4.0.2-alpine AS build RUN bundle install FROM ruby:4.0.2-alpine - ARG ROOT + ARG ROOT=/usr/src/app/ WORKDIR $ROOT RUN apk update && apk upgrade && apk add --update --no-cache \ @@ -33,15 +32,20 @@ FROM ruby:4.0.2-alpine imagemagick \ postgresql-client \ tzdata \ - vim \ && rm -rf /var/cache/apk/* - COPY . . + RUN addgroup -S app && adduser -S app -G app && chown app:app $ROOT + COPY --from=node-source /usr/local/bin/node /usr/local/bin/node COPY --from=node-source /usr/local/lib/node_modules /usr/local/lib/node_modules - RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm + COPY --from=node-source /usr/local/bin/npm /usr/local/bin/npm + + USER app + + COPY --chown=app:app package*.json ./ RUN npm ci + COPY --chown=app:app . . COPY --from=build /usr/local/bundle/ /usr/local/bundle/ EXPOSE 3000 diff --git a/Gemfile.lock b/Gemfile.lock index 612fffe621..469ef93e83 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -804,4 +804,4 @@ RUBY VERSION ruby 4.0.2 BUNDLED WITH - 4.0.9 + 4.0.10 From d469d6d12d7b00a3b2a1cb7f1b7bbb2d46690bed Mon Sep 17 00:00:00 2001 From: compwron Date: Thu, 23 Apr 2026 22:54:39 -0700 Subject: [PATCH 2/2] Fix npm cli resolution: revert to symlink over direct COPY COPY resolves the file to /usr/local/bin/npm, so Node sets __dirname to /usr/local/bin/ and require('../lib/cli.js') in npm-cli.js points to /usr/local/lib/cli.js (missing). A symlink keeps the real file at /usr/local/lib/node_modules/npm/bin/npm-cli.js so __dirname resolves correctly and the relative require works. Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index df6c488ef8..583b0121de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,7 @@ FROM ruby:4.0.2-alpine COPY --from=node-source /usr/local/bin/node /usr/local/bin/node COPY --from=node-source /usr/local/lib/node_modules /usr/local/lib/node_modules - COPY --from=node-source /usr/local/bin/npm /usr/local/bin/npm + RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm USER app