From 9920d212fe5334541b362d6c9eb0b676e4622b39 Mon Sep 17 00:00:00 2001 From: pwadmore-ea <8915039+pwadmore-ea@users.noreply.github.com> Date: Fri, 20 Feb 2026 15:10:01 +0000 Subject: [PATCH 1/2] Update examples to reflect new Docker guidance: https://github.com/DEFRA/software-development-standards/pull/117 From 59c3ac40e73f99a07497f82580d4b2ab1a6f41a5 Mon Sep 17 00:00:00 2001 From: pwadmore-ea <8915039+pwadmore-ea@users.noreply.github.com> Date: Thu, 5 Mar 2026 08:57:09 +0000 Subject: [PATCH 2/2] Update examples to reflect new Docker guidance --- examples/Dockerfile.service | 13 ++++++++++--- examples/Dockerfile.web | 14 +++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/Dockerfile.service b/examples/Dockerfile.service index 13a5265..4ac1c54 100644 --- a/examples/Dockerfile.service +++ b/examples/Dockerfile.service @@ -1,7 +1,7 @@ # This assumes that the parent image has been built locally using production and development build configuration as defra-node # and defra-node-development tagged with a version. -ARG BASE_VERSION=2.7.0-node22.14.0 +ARG BASE_VERSION=2.10.3-node24.12.0 FROM defra-node:$BASE_VERSION AS base # Copy our package files so that our package install will do a clean install. This installs the exact versions of the packages @@ -39,7 +39,14 @@ CMD [ "npm", "run", "test" ] # Production stage exposes service port, copies in built app code and declares the Node app as the default command FROM base AS production +# Copy application artifacts and assign root ownership to prevent modification by other users. +COPY --from=development --chown=root:root /home/node/package*.json ./ +COPY --from=development --chown=root:root /home/node/app/ ./app/ + +# Install node modules and remove write permissions. +RUN npm ci --ignore-scripts --omit=dev && chmod -R a-w /home/node + # This is the command that is run for the production service. The parent image has an ENTRYPOINT that uses a lightweight -# init program "tini" that handles signals. As long as we don't override the ENTRYPOINT the "tini" routine will handle signals and -# orphaned processes +# init program "tini" that handles signals. As long as we don't override the ENTRYPOINT the "tini" routine will handle signals and +# orphaned processes CMD [ "node", "app/index" ] diff --git a/examples/Dockerfile.web b/examples/Dockerfile.web index 8664309..a6d3b5e 100644 --- a/examples/Dockerfile.web +++ b/examples/Dockerfile.web @@ -1,7 +1,7 @@ # This assumes that the parent image has been built locally using production and development build configuration as defra-node # and defra-node-development tagged with a version. -ARG BASE_VERSION=2.5.2-node22.14.0 +ARG BASE_VERSION=2.10.3-node24.12.0 FROM defra-node:$BASE_VERSION AS base # Set the port that is going to be exposed later on in the Dockerfile as well. @@ -53,10 +53,14 @@ WORKDIR /home/node EXPOSE ${PORT} # Copy in the files that we built using the tools in the development stage. The final production stage will have the built files, -# but none of the tools required to build those files. This reduces the attack surface, and also the size of the final production image -COPY --from=development /home/node/app/ ./app/ +# but none of the tools required to build those files. This reduces the attack surface, and also the size of the final production image +COPY --from=development --chown=root:root /home/node/package*.json ./ +COPY --from=development --chown=root:root /home/node/app/ ./app/ + +# Install node modules and remove write permissions. +RUN npm ci --ignore-scripts --omit=dev && chmod -R a-w /home/node # This is the command that is run for the production service. The parent image has an ENTRYPOINT that uses a lightweight -# init program "tini" that handles signals. As long as we don't override the ENTRYPOINT the "tini" routine will handle signals and -# orphaned processes +# init program "tini" that handles signals. As long as we don't override the ENTRYPOINT the "tini" routine will handle signals and +# orphaned processes CMD [ "node", "app/index" ]