From 33a5fadf67943fa8e945390abef5348ac9202699 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Wed, 3 Sep 2025 20:47:50 +0200 Subject: [PATCH] web-app-chess: fix Corepack/Yarn EACCES and switch to ARG-driven Dockerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Add roles/web-app-chess/files/Dockerfile using build ARGs (CHESS_VERSION, CHESS_REPO_URL, CHESS_REPO_REF, CHESS_ENTRYPOINT_REL, CHESS_ENTRYPOINT_INT, CHESS_APP_DATA_DIR, CONTAINER_PORT). Enable Corepack/Yarn as root in the runtime stage to avoid EACCES on /usr/local/bin symlinks, then drop privileges to 'node'. • Delete Jinja-based templates/Dockerfile.j2; docker-compose now passes former Jinja vars via build.args. • Update templates/docker-compose.yml.j2 to forward all required build args. • Update config/main.yml: add CSP flag 'script-src-elem: unsafe-inline'. Ref: https://chatgpt.com/share/68b88d3d-3bd8-800f-9723-e8df0cdc37e2 --- roles/web-app-chess/config/main.yml | 4 +- roles/web-app-chess/files/Dockerfile | 69 +++++++++++++++++++ roles/web-app-chess/templates/Dockerfile.j2 | 52 -------------- .../templates/docker-compose.yml.j2 | 5 ++ 4 files changed, 77 insertions(+), 53 deletions(-) create mode 100644 roles/web-app-chess/files/Dockerfile delete mode 100644 roles/web-app-chess/templates/Dockerfile.j2 diff --git a/roles/web-app-chess/config/main.yml b/roles/web-app-chess/config/main.yml index 72641cdb..05314fcf 100644 --- a/roles/web-app-chess/config/main.yml +++ b/roles/web-app-chess/config/main.yml @@ -21,7 +21,9 @@ features: server: csp: whitelist: {} - flags: {} + flags: + script-src-elem: + unsafe-inline: true domains: canonical: - "chess.{{ PRIMARY_DOMAIN }}" diff --git a/roles/web-app-chess/files/Dockerfile b/roles/web-app-chess/files/Dockerfile new file mode 100644 index 00000000..bf02d2f6 --- /dev/null +++ b/roles/web-app-chess/files/Dockerfile @@ -0,0 +1,69 @@ +# Multi-stage build for castling.club + +# Allow a dynamic base image version in both stages +ARG CHESS_VERSION + +# -------- Stage 1: build -------- +FROM node:${CHESS_VERSION} AS build + +# Build-time inputs +ARG CHESS_REPO_URL +ARG CHESS_REPO_REF + +RUN apt-get update && apt-get install -y --no-install-recommends \ + git ca-certificates openssl dumb-init python3 build-essential \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /src +RUN git clone --depth 1 --branch "${CHESS_REPO_REF}" "${CHESS_REPO_URL}" ./ + +# Prepare Yarn 4 as root (safe during build stage) +RUN corepack enable && corepack prepare yarn@4.9.1 --activate && yarn -v +RUN yarn install --immutable --inline-builds +RUN yarn build + +# -------- Stage 2: runtime -------- +FROM node:${CHESS_VERSION} + +# Runtime inputs (formerly Jinja variables) +ARG CHESS_ENTRYPOINT_REL +ARG CHESS_ENTRYPOINT_INT +ARG CHESS_APP_DATA_DIR +ARG CONTAINER_PORT + +WORKDIR /app + +# Minimal runtime deps + curl for healthcheck +RUN apt-get update && apt-get install -y --no-install-recommends \ + bash openssl dumb-init postgresql-client ca-certificates curl \ + && rm -rf /var/lib/apt/lists/* + +# Copy built app +COPY --from=build /src /app + +# Install entrypoint +COPY ${CHESS_ENTRYPOINT_REL} ${CHESS_ENTRYPOINT_INT} +RUN chmod +x ${CHESS_ENTRYPOINT_INT} + +# Fix: enable Corepack/Yarn as root so shims land in /usr/local/bin +RUN corepack enable && corepack prepare yarn@4.9.1 --activate && yarn -v + +# Create writable dirs and set ownership +RUN mkdir -p ${CHESS_APP_DATA_DIR} /app/.yarn/cache /home/node \ + && chown -R node:node /app /home/node + +# Use project-local Yarn cache +ENV YARN_ENABLE_GLOBAL_CACHE=false \ + YARN_CACHE_FOLDER=/app/.yarn/cache \ + HOME=/home/node + +# Drop privileges +USER node + +# Expose the runtime port (build-time constant) +EXPOSE ${CONTAINER_PORT} + +ENTRYPOINT ["dumb-init", "--"] +# Use a shell so the value can be expanded reliably +ENV CHESS_ENTRYPOINT_INT=${CHESS_ENTRYPOINT_INT} +CMD ["sh","-lc","exec \"$CHESS_ENTRYPOINT_INT\""] diff --git a/roles/web-app-chess/templates/Dockerfile.j2 b/roles/web-app-chess/templates/Dockerfile.j2 deleted file mode 100644 index b0c13921..00000000 --- a/roles/web-app-chess/templates/Dockerfile.j2 +++ /dev/null @@ -1,52 +0,0 @@ -# Multi-stage build for castling.club -# Stage 1: build -FROM node:{{ CHESS_VERSION }} AS build - -ARG CHESS_REPO_URL={{ CHESS_REPO_URL }} -ARG CHESS_REPO_REF={{ CHESS_REPO_REF }} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - git ca-certificates openssl dumb-init python3 build-essential \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /src -RUN git clone --depth 1 --branch "${CHESS_REPO_REF}" "${CHESS_REPO_URL}" ./ - -# Use Yarn 4 for the build -RUN corepack enable && corepack prepare yarn@4.9.1 --activate && yarn -v -RUN yarn install --immutable --inline-builds -RUN yarn build - -# Stage 2: runtime -FROM node:{{ CHESS_VERSION }} - -WORKDIR /app - -# Minimal runtime packages + dumb-init (+ curl for healthcheck) -RUN apt-get update && apt-get install -y --no-install-recommends \ - bash openssl dumb-init postgresql-client ca-certificates curl \ - && rm -rf /var/lib/apt/lists/* - -# Copy built app from builder -COPY --from=build /src /app - -# Entrypoint script (root so chmod works in /usr/local/bin) -COPY {{ CHESS_ENTRYPOINT_REL }} {{ CHESS_ENTRYPOINT_INT }} -RUN chmod +x {{ CHESS_ENTRYPOINT_INT }} - -# Create data dir for signing keys and Yarn cache; fix ownership -RUN mkdir -p {{ CHESS_APP_DATA_DIR }} /app/.yarn/cache /home/node \ - && chown -R node:node /app /home/node - -# Use project-local yarn cache (avoid /root/.yarn) -ENV YARN_ENABLE_GLOBAL_CACHE=false -ENV YARN_CACHE_FOLDER=/app/.yarn/cache - -# Switch to non-root and prep yarn 4 -USER node -ENV HOME=/home/node -RUN corepack enable && corepack prepare yarn@4.9.1 --activate && yarn -v - -EXPOSE {{ container_port }} -ENTRYPOINT ["dumb-init", "--"] -CMD ["{{ CHESS_ENTRYPOINT_INT }}"] diff --git a/roles/web-app-chess/templates/docker-compose.yml.j2 b/roles/web-app-chess/templates/docker-compose.yml.j2 index 3649e7f6..59412d4e 100644 --- a/roles/web-app-chess/templates/docker-compose.yml.j2 +++ b/roles/web-app-chess/templates/docker-compose.yml.j2 @@ -4,8 +4,13 @@ context: . dockerfile: Dockerfile args: + CHESS_VERSION: "{{ CHESS_VERSION }}" CHESS_REPO_URL: "{{ CHESS_REPO_URL }}" CHESS_REPO_REF: "{{ CHESS_REPO_REF }}" + CHESS_ENTRYPOINT_REL: "{{ CHESS_ENTRYPOINT_REL }}" + CHESS_ENTRYPOINT_INT: "{{ CHESS_ENTRYPOINT_INT }}" + CHESS_APP_DATA_DIR: "{{ CHESS_APP_DATA_DIR }}" + CONTAINER_PORT: "{{ container_port | string }}" image: "{{ CHESS_CUSTOM_IMAGE }}" container_name: "{{ CHESS_CONTAINER }}" hostname: "{{ CHESS_HOSTNAME }}"