diff --git a/Dockerfile b/Dockerfile index 5d32392c..ab771ec5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,73 +1,66 @@ -FROM node:22.12-bookworm-slim AS base +FROM node:22.12-bookworm-slim as builder ARG BUILD_NUMBER ARG GIT_REF -ARG GIT_BRANCH - -LABEL maintainer="HMPPS Digital Studio " - -ENV TZ=Europe/London -RUN ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" > /etc/timezone - -RUN addgroup --gid 2000 --system appgroup && \ - adduser --uid 2000 --system appuser --gid 2000 - -WORKDIR /app - -# Cache breaking and ensure required build / git args defined -RUN test -n "$BUILD_NUMBER" || (echo "BUILD_NUMBER not set" && false) -RUN test -n "$GIT_REF" || (echo "GIT_REF not set" && false) -RUN test -n "$GIT_BRANCH" || (echo "GIT_BRANCH not set" && false) - -# Define env variables for runtime health / info -ENV BUILD_NUMBER=${BUILD_NUMBER} -ENV GIT_REF=${GIT_REF} -ENV GIT_BRANCH=${GIT_BRANCH} - -RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/* RUN apt-get update && \ apt-get upgrade -y RUN apt-get -y install g++ make python3 curl && rm -rf /var/lib/apt/lists/* +WORKDIR /app RUN curl https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem \ > /app/root.cert -# Stage: build assets -FROM base AS build +COPY . . -ARG BUILD_NUMBER -ARG GIT_REF -ARG GIT_BRANCH +RUN CYPRESS_INSTALL_BINARY=0 npm ci --no-audit && \ + npm run build && \ + export BUILD_NUMBER=${BUILD_NUMBER:-1_0_0} && \ + export GIT_REF=${GIT_REF:-dummy} && \ + npm run record-build-info -COPY package*.json ./ -RUN CYPRESS_INSTALL_BINARY=0 npm ci --no-audit -ENV NODE_ENV='production' +RUN npm prune --production -COPY . . +FROM node:22.12-bookworm-slim +LABEL maintainer="HMPPS Digital Studio " + +# Cache breaking +ENV BUILD_NUMBER ${BUILD_NUMBER:-1_0_0} + +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/* -RUN npm run build -RUN npm prune --no-audit --omit=dev +RUN addgroup --gid 2000 --system appgroup && \ + adduser --uid 2000 --system appuser --gid 2000 +ENV TZ=Europe/London +RUN ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" > /etc/timezone -# Stage: copy production assets and dependencies -FROM base +# Create app directory +RUN mkdir /app && chown appuser:appgroup /app +USER 2000 +WORKDIR /app -COPY --from=build --chown=appuser:appgroup \ +COPY --from=builder --chown=appuser:appgroup \ /app/package.json \ /app/package-lock.json \ + /app/dist \ + /app/root.cert \ + /app/build-info.json \ ./ -COPY --from=build --chown=appuser:appgroup \ - /app/dist ./dist +COPY --from=builder --chown=appuser:appgroup \ + /app/assets ./assets -COPY --from=build --chown=appuser:appgroup \ +COPY --from=builder --chown=appuser:appgroup \ /app/node_modules ./node_modules +COPY --from=builder --chown=appuser:appgroup \ + /app/server/views ./server/views + ENV PORT=3000 EXPOSE 3000 diff --git a/package.json b/package.json index ab268995..5f13e398 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "watch-views": "nodemon --watch server/views -e html,njk -x npm run copy-views", "watch-ts": "tsc -w", "watch-node": "DEBUG=gov-starter-server* DB_PORT=5433 nodemon -r dotenv/config --watch dist/ dist/server.js | bunyan -o short", - "start": "node $NODE_OPTIONS dist/server.js | bunyan -o short", "start:dev": "npm run build && concurrently -k -p \"[{name}]\" -n \"Views,TypeScript,Node\" -c \"yellow.bold,cyan.bold,green.bold\" \"npm run watch-views\" \"npm run watch-ts\" \"npm run watch-node\"", "start-feature": "export $(cat feature.env) && node $NODE_DEBUG_OPTION dist/server.js | bunyan -o short", "watch-node-feature": "export $(cat feature.env) && nodemon -r dotenv/config --watch dist/ $NODE_DEBUG_OPTION dist/server.js | bunyan -o short", diff --git a/server/config.js b/server/config.js index 2e625e82..8d2249ef 100755 --- a/server/config.js +++ b/server/config.js @@ -13,8 +13,6 @@ function get(name, fallback, options = {}) { const requiredInProduction = { requireInProduction: true } module.exports = { - buildNumber: get('BUILD_NUMBER', '1_0_0', requiredInProduction), - db: { username: get('DB_USER', 'use-of-force'), password: get('DB_PASS', 'use-of-force'),