Skip to content

Instantly share code, notes, and snippets.

@Addono
Created March 9, 2023 18:37
Show Gist options
  • Save Addono/1ca9b570491c6d461fd7e27ca4d7a8b1 to your computer and use it in GitHub Desktop.
Save Addono/1ca9b570491c6d461fd7e27ca4d7a8b1 to your computer and use it in GitHub Desktop.
Turborepo multi-stage Dockerfile
##############################################################
##### Full dependencies #####
##############################################################
FROM docker.io/library/node:18.14.2-alpine3.16@sha256:72c0b366821377f04d816cd0287360e372cc55782d045e557e2640cb8040d3ea as fulldeps
# Install additional packages
# - libc6-compat for Turbo >1.5.5. See https://github.com/vercel/turbo/issues/2198
# - rsync for efficiently copying a subset of our files into this container
RUN apk add --no-cache libc6-compat rsync
WORKDIR /workspace-install
COPY package-lock.json turbo.json ./
# Copying files using rsync, as the COPY command in Dockerfiles
# have no support for copying files using wildcard-patterns while
# preserving the original folder structure.
#
# We use buidkit to prepare all files that are necessary for install
# and that will be used to invalidate docker cache.
#
# Files are copied with rsync:
#
# - All package.json present in the host (root, apps/*, packages/*)
#
RUN --mount=type=bind,target=/docker-context \
rsync -amv --delete \
--exclude='node_modules' \
--exclude='*/node_modules' \
--include='package.json' \
--include='.npmrc' \
--include='*/' \
--exclude='*' \
/docker-context/ /workspace-install/;
# Install all dependencies
#
# To speed up installations, we override the default yarn cache folder
# and mount it as a buildkit cache mount (builkit will rotate it if needed)
# This strategy allows to exclude the yarn cache in subsequent docker
# layers (size benefit) and reduce packages fetches.
#
# PS:
# 1. Cache mounts can be used in CI (github actions)
# 2. To manually clear the cache
# > docker builder prune --filter type=exec.cachemount
#
# Does not play well with buildkit on CI
# https://github.com/moby/buildkit/issues/1673
RUN npm ci
##############################################################
##### Build the application #####
##############################################################
FROM docker.io/library/node:18.14.2@sha256:b7483c70b94e9fbb68e91d64456ee147d120488f876d69efeae815ba164e8b54 as builder
ENV NODE_ENV production
WORKDIR /app
# Include all source code and dependencies
COPY . .
COPY --from=fulldeps /workspace-install ./
RUN npm run build
##############################################################
##### Optimize our builder artifacts for production #####
##############################################################
FROM builder as builder-production
# Remove all dev dependencies
RUN npm ci --production
##############################################################
##### Create base layer with all packages in production #####
##############################################################
FROM docker.io/library/node:18.14.2-alpine3.16@sha256:72c0b366821377f04d816cd0287360e372cc55782d045e557e2640cb8040d3ea as runner
WORKDIR /app
ENV NODE_ENV production
# Add required source-code and build-artifacts
COPY package.json ./
COPY --from=builder-production /app/node_modules/ ./node_modules/
COPY --from=builder-production /app/packages/ ./packages/
# Expose the same port for all applications, as it will at least
# be used for reporting ready and liveness status.
ARG PORT
ENV PORT=${PORT:-4000}
EXPOSE $PORT
##############################################################
##### Create layer to run web app #####
##############################################################
FROM runner as web
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 app
## Apps
### web
COPY ./apps/web/package.json ./apps/web/
COPY --from=builder-production --chown=app:nodejs /app/apps/web/.next/ ./apps/web/.next/
USER app
# Set the CMD to our handler
ENTRYPOINT ["npm", "run", "--workspace", "web"]
CMD ["start"]
##############################################################
##### Create layer to run docs app #####
##############################################################
FROM runner as docs
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 app
## Apps
### docs
COPY ./apps/docs/package.json ./apps/docs/
COPY --from=builder-production --chown=app:nodejs /app/apps/docs/.next/ ./apps/docs/.next/
USER app
# Set the CMD to our handler
ENTRYPOINT ["npm", "run", "--workspace", "docs"]
CMD ["start"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment