From afb3d2e281aeed6ffcb621702aafd3c95925788a Mon Sep 17 00:00:00 2001 From: Adam Goldstone <13471320+agoldstone93@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:20:26 +0000 Subject: [PATCH] Combine dockerfile into one and update config.yml Make use of multi stage dockerfile and docker layer caching to try to reduce build times and efficiency --- .circleci/config.yml | 13 +++---- Dockerfile | 85 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6bea4457f2..95285a0256 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,6 +47,7 @@ commands: --build-arg BUILD_DATE=$(date +%Y-%m-%dT%H:%M:%S%z) \ --build-arg BUILD_TAG="app-${CIRCLE_SHA1}" \ --build-arg APP_BRANCH=${CIRCLE_BRANCH} \ + --cache-from ${ECR_REGISTRY}/${ECR_REPOSITORY}:latest \ -t app . | while read line ; do echo "$(date +"%T") > $line" ; done ; - aws-cli/setup: role_arn: $ECR_ROLE_TO_ASSUME @@ -118,7 +119,8 @@ jobs: executor: linting-executor steps: - checkout - - setup_remote_docker + - setup_remote_docker: + docker_layer_caching: true - *update_packages - *restore_gems_cache - *install_gems @@ -218,6 +220,8 @@ jobs: executor: test-executor steps: - checkout + - setup_remote_docker: + docker_layer_caching: true - *restore_gems_cache - *install_gems - *save_gems_cache @@ -267,14 +271,14 @@ jobs: executor: cloud-platform-executor steps: - checkout - - setup_remote_docker + - setup_remote_docker: + docker_layer_caching: true - build-and-push-to-ecr deploy_uat: &deploy_uat executor: cloud-platform-executor steps: - checkout - - setup_remote_docker - *authenticate_k8s_live - run: name: Helm deployment to UAT @@ -288,7 +292,6 @@ jobs: executor: cloud-platform-executor steps: - checkout - - setup_remote_docker - *authenticate_k8s_live - run: name: Helm deployment to staging @@ -304,7 +307,6 @@ jobs: executor: cloud-platform-executor steps: - checkout - - setup_remote_docker - *authenticate_k8s_live - run: name: Helm deployment to production @@ -320,7 +322,6 @@ jobs: executor: cloud-platform-executor steps: - checkout - - setup_remote_docker - *authenticate_k8s_live - run: name: Delete dependabot deployment diff --git a/Dockerfile b/Dockerfile index 6f9f29167c..7dba83d234 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,45 @@ -FROM ministryofjustice/apply-base:latest-3.3.6 +# Stage 1: Base image with build dependencies +FROM ruby:3.3.6-alpine3.21 AS base + LABEL org.opencontainers.image.authors="apply for legal aid team" +# fail early and print all commands +RUN set -ex + +# Install build dependencies +RUN apk --no-cache add --virtual build-dependencies \ + build-base \ + libxml2-dev \ + libxslt-dev \ + postgresql-dev \ + git \ + curl \ + yaml-dev + +# Install runtime dependencies +RUN apk --no-cache add \ + postgresql-client \ + nodejs \ + yarn \ + jq \ + linux-headers \ + clamav-daemon \ + libreoffice \ + ttf-dejavu \ + ttf-droid \ + ttf-freefont \ + ttf-liberation \ + bash + +# Install Chromium and Puppeteer for PDF generation +RUN apk --no-cache add chromium + +# Clean up build dependencies +RUN apk del build-dependencies + +# Stage 2: Build application dependencies +FROM base AS builder + # add non-root user and group with alpine first available uid, 1000 RUN addgroup -g 1000 -S appgroup \ && adduser -u 1000 -S appuser -G appgroup @@ -9,11 +48,7 @@ RUN addgroup -g 1000 -S appgroup \ RUN mkdir -p /usr/src/app && mkdir -p /usr/src/app/tmp WORKDIR /usr/src/app -###################### -# DEPENDENCIES START # -###################### # Env vars needed for dependency install and asset precompilation - COPY .ruby-version Gemfile Gemfile.lock ./ # only install production dependencies, @@ -26,33 +61,47 @@ RUN gem update --system \ COPY package.json yarn.lock ./ RUN yarn --prod -#################### -# DEPENDENCIES END # -#################### +# Copy application code +COPY . . + +# Precompile assets +RUN NODE_OPTIONS=--openssl-legacy-provider bundle exec rake assets:precompile SECRET_KEY_BASE=a-real-secret-key-is-not-needed-here + +# Stage 3: Final runtime image +FROM base + +# add non-root user and group with alpine first available uid, 1000 +RUN addgroup -g 1000 -S appgroup \ +&& adduser -u 1000 -S appuser -G appgroup + +# create app directory in conventional, existing dir /usr/src +RUN mkdir -p /usr/src/app && mkdir -p /usr/src/app/tmp +WORKDIR /usr/src/app + +# Copy runtime dependencies and application code from builder stage +COPY --from=builder /usr/src/app /usr/src/app +# Set environment variables ENV RAILS_ENV production ENV NODE_ENV production ENV RAILS_SERVE_STATIC_FILES true -EXPOSE 3002 -COPY . . - -RUN NODE_OPTIONS=--openssl-legacy-provider bundle exec rake assets:precompile SECRET_KEY_BASE=a-real-secret-key-is-not-needed-here - -# tidy up installation - these are installed in the apply-base image -RUN apk del build-dependencies +# Expose port +EXPOSE 3002 -# non-root/appuser should own only what they need to +# Set ownership for non-root user RUN chown -R appuser:appgroup log tmp db -# expect ping environment variablesARG COMMIT_ID +# expect ping environment variables +ARG COMMIT_ID ARG BUILD_DATE ARG BUILD_TAG ARG APP_BRANCH + # set ping environment variables ENV BUILD_DATE=${BUILD_DATE} ENV BUILD_TAG=${BUILD_TAG} ENV APP_BRANCH=${APP_BRANCH} USER 1000 -CMD "./docker/run" +CMD ["./docker/run"]