Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: use a base image for Docker builds #6515

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 53 additions & 32 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,49 +1,76 @@
FROM node:20-alpine AS builder
# A three-stage docker build, based on
# https://calvinf.com/blog/2023/11/10/node-js-20-yarn-4-and-next-js-on-docker/

############################
# Stage 1: Base Node Alpine image for both the builder and runner stages
FROM node:20-alpine AS base

# Latest Git commit hash
ARG COMMIT_ID
ENV COMMIT_ID=$COMMIT_ID
ENV SENTRY_RELEASE=$COMMIT_ID

# GitHub branch name
ARG GITHUB_REF_NAME
ENV GITHUB_REF_NAME=$GITHUB_REF_NAME

# Panoptes API: staging | production (default)
ARG PANOPTES_ENV=production
ENV PANOPTES_ENV=$PANOPTES_ENV

# Webpack build mode: development | production (default)
# https://webpack.js.org/configuration/mode/
ARG NODE_ENV=production
ENV NODE_ENV=$NODE_ENV

# container deployment environment: development | branch | staging | production (default)
ARG APP_ENV=production
ENV APP_ENV=$APP_ENV

# disable Next.js telemetry
# https://nextjs.org/telemetry
ENV NEXT_TELEMETRY_DISABLED=1

ARG CONTENTFUL_ACCESS_TOKEN

ARG CONTENTFUL_SPACE_ID

ARG SENTRY_AUTH_TOKEN

# Install everything into /usr/src.
RUN mkdir -p /usr/src

WORKDIR /usr/src/

ADD package.json /usr/src/
# Change the user and group from root to node.
RUN chown -R node:node .

# Copy the package file, lock file, Yarn config, and lerna config
# into any image built from this image.
ONBUILD COPY --chown=node:node package.json yarn.lock lerna.json .yarnrc /usr/src/

COPY .yarn /usr/src/.yarn
# Copy the .yarn directory into any image built from this image.
ONBUILD COPY --chown=node:node .yarn /usr/src/.yarn

ADD .yarnrc /usr/src/
# Run all commands as the node user, in any image built from this image.
ONBUILD USER node

ADD lerna.json /usr/src/
#########################
# Stage 2: Builder stage
FROM base AS builder

COPY ./packages /usr/src/packages
# Add build secrets.
# NB. GitHub warns that ARG should not be used for sensitive data.
ARG CONTENTFUL_ACCESS_TOKEN

ADD yarn.lock /usr/src/
ARG CONTENTFUL_SPACE_ID

RUN chown -R node:node .
ARG SENTRY_AUTH_TOKEN

Comment on lines +56 to +62
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

USER node
# Copy the source packages into the image.
COPY --chown=node:node ./packages /usr/src/packages

# Install dependencies and bootstrap the Next.js apps.
# The monorepo packages depend on each other,
# so must be built in a specific order.
# Set YARN_CACHE_FOLDER=/home/node/.yarn.
# Cache the Yarn cache as fem-builder-yarn across builds.
# (Why is this repeated for every layer?)
# https://classic.yarnpkg.com/lang/en/docs/cli/cache/#toc-change-the-cache-path-for-yarn
RUN --mount=type=cache,id=fem-builder-yarn,uid=1000,gid=1000,target=/home/node/.yarn YARN_CACHE_FOLDER=/home/node/.yarn yarn install --production=false --frozen-lockfile --ignore-scripts
RUN --mount=type=cache,id=fem-builder-yarn,uid=1000,gid=1000,target=/home/node/.yarn YARN_CACHE_FOLDER=/home/node/.yarn yarn workspace @zooniverse/react-components build:es6
RUN --mount=type=cache,id=fem-builder-yarn,uid=1000,gid=1000,target=/home/node/.yarn YARN_CACHE_FOLDER=/home/node/.yarn yarn workspace @zooniverse/subject-viewers build:es6
Expand All @@ -55,27 +82,21 @@ RUN --mount=type=cache,id=fem-builder-yarn,uid=1000,gid=1000,target=/home/node/.
RUN echo $COMMIT_ID > /usr/src/packages/app-root/public/commit_id.txt
RUN --mount=type=cache,id=fem-builder-yarn,uid=1000,gid=1000,target=/home/node/.yarn YARN_CACHE_FOLDER=/home/node/.yarn yarn workspace @zooniverse/fe-root build

FROM node:20-alpine AS runner

ARG NODE_ENV=production
ENV NODE_ENV=$NODE_ENV

RUN mkdir -p /usr/src

WORKDIR /usr/src/

COPY --from=builder /usr/src/package.json /usr/src/package.json

COPY --from=builder /usr/src/.yarn /usr/src/.yarn

COPY --from=builder /usr/src/.yarnrc /usr/src/.yarnrc

COPY --from=builder /usr/src/packages ./packages
#########################
# Stage 3: Runner stage
# This image is deployed to Kubernetes.
FROM base AS runner

COPY --from=builder /usr/src/yarn.lock /usr/src/yarn.lock
# Copy the built packages into the image.
COPY --from=builder --chown=node:node /usr/src/packages ./packages

# Install only production dependencies.
# Cache the Yarn cache as fem-runner-yarn across builds.
RUN --mount=type=cache,id=fem-runner-yarn,uid=1000,gid=1000,target=/home/node/.yarn YARN_CACHE_FOLDER=/home/node/.yarn yarn install --production --frozen-lockfile --ignore-scripts --prefer-offline

# Remove all the source code.
# Any other files that aren't needed to run the Next.js apps
# should be removed here too.
RUN rm -rf /usr/src/packages/lib-react-components/src
RUN rm -rf /usr/src/packages/lib-content/src
RUN rm -rf /usr/src/packages/lib-classifier/src
Expand Down
Loading