Changes based on feedback

Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
Andre Wanlin
2024-09-11 07:23:50 -05:00
parent ad8ffa148a
commit 08273aa725
5 changed files with 56 additions and 35 deletions
+35 -17
View File
@@ -40,14 +40,14 @@ package with `yarn build:backend`.
In a CI workflow it might look something like this, from the root:
```bash
yarn install --frozen-lockfile
yarn install --immutable
# tsc outputs type definitions to dist-types/ in the repo root, which are then consumed by the build
yarn tsc
# Build the backend, which bundles it all up into the packages/backend/dist folder.
# The configuration files here should match the one you use inside the Dockerfile below.
yarn build:backend --config ../../app-config.yaml
yarn build:backend --config ../../app-config.yaml --config ../../app-config.production.yaml
```
Once the host build is complete, we are ready to build our image. The following
@@ -56,30 +56,36 @@ Once the host build is complete, we are ready to build our image. The following
```dockerfile
FROM node:18-bookworm-slim
# Set Python interpreter for `node-gyp` to use
ENV PYTHON=/usr/bin/python3
# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends python3 g++ build-essential && \
yarn config set python /usr/bin/python3
rm -rf /var/lib/apt/lists/*
# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends libsqlite3-dev
apt-get install -y --no-install-recommends libsqlite3-dev && \
rm -rf /var/lib/apt/lists/*
# From here on we use the least-privileged `node` user to run the backend.
USER node
# This should create the app dir as `node`.
# If it is instead created as `root` then the `tar` command below will
# fail: `can't create directory 'packages/': Permission denied`.
# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`)
# so the app dir is correctly created as `node`.
# If it is instead created as `root` then the `tar` command below will fail: `can't create directory 'packages/': Permission denied`.
# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`) so the app dir is correctly created as `node`.
WORKDIR /app
# Copy files needed by Yarn
COPY --chown=node:node .yarn ./.yarn
COPY --chown=node:node .yarnrc.yml ./
# This switches many Node.js dependencies to production mode.
ENV NODE_ENV=production
@@ -90,7 +96,7 @@ COPY --chown=node:node yarn.lock package.json packages/backend/dist/skeleton.tar
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
yarn install --frozen-lockfile --production --network-timeout 300000
yarn workspaces focus --all --production && rm -rf "$(yarn cache clean)"
# This will include the examples, if you don't need these simply remove this line
COPY --chown=node:node examples ./examples
@@ -173,6 +179,8 @@ FROM node:18-bookworm-slim AS packages
WORKDIR /app
COPY package.json yarn.lock ./
COPY .yarn ./.yarn
COPY .yarnrc.yml ./
COPY packages packages
@@ -184,34 +192,38 @@ RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf {
# Stage 2 - Install dependencies and build packages
FROM node:18-bookworm-slim AS build
# Set Python interpreter for `node-gyp` to use
ENV PYTHON=/usr/bin/python3
# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends python3 g++ build-essential && \
yarn config set python /usr/bin/python3
rm -rf /var/lib/apt/lists/*
# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends libsqlite3-dev
apt-get install -y --no-install-recommends libsqlite3-dev && \
rm -rf /var/lib/apt/lists/*
USER node
WORKDIR /app
COPY --from=packages --chown=node:node /app .
COPY --from=packages --chown=node:node /app/.yarn ./.yarn
COPY --from=packages --chown=node:node /app/.yarnrc.yml ./
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
yarn install --frozen-lockfile --network-timeout 600000
yarn install --immutable
COPY --chown=node:node . .
RUN yarn tsc
RUN yarn --cwd packages/backend build
# If you have not yet migrated to package roles, use the following command instead:
# RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies
RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \
&& tar xzf packages/backend/dist/skeleton.tar.gz -C packages/backend/dist/skeleton \
@@ -220,19 +232,23 @@ RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \
# Stage 3 - Build the actual backend image and install production dependencies
FROM node:18-bookworm-slim
# Set Python interpreter for `node-gyp` to use
ENV PYTHON=/usr/bin/python3
# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends python3 g++ build-essential && \
yarn config set python /usr/bin/python3
rm -rf /var/lib/apt/lists/*
# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends libsqlite3-dev
apt-get install -y --no-install-recommends libsqlite3-dev && \
rm -rf /var/lib/apt/lists/*
# From here on we use the least-privileged `node` user to run the backend.
USER node
@@ -245,13 +261,15 @@ USER node
WORKDIR /app
# Copy the install dependencies from the build stage and context
COPY --from=build --chown=node:node /app/.yarn ./.yarn
COPY --from=build --chown=node:node /app/.yarnrc.yml ./
COPY --from=build --chown=node:node /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton/ ./
# Note: The skeleton bundle only includes package.json files -- if your app has
# plugins that define a `bin` export, the bin files need to be copied as well to
# be linked in node_modules/.bin during yarn install.
RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
yarn install --frozen-lockfile --production --network-timeout 600000
yarn workspaces focus --all --production && rm -rf "$(yarn cache clean)"
# Copy the built packages from the build stage
COPY --from=build --chown=node:node /app/packages/backend/dist/bundle/ ./
+1 -1
View File
@@ -126,7 +126,7 @@ heroku stack:set container -a <your-app>
Locally run the [host build commands](https://backstage.io/docs/deployment/docker/#host-build), they must be run whenever you are going to publish a new image:
```shell
yarn install --frozen-lockfile
yarn install --immutable
yarn tsc
yarn build:backend --config ../../app-config.yaml --config ../../app-config.production.yaml
```
+16 -14
View File
@@ -1,12 +1,10 @@
---
id: yarn-migration
title: Migration to Yarn 3
description: Guide for how to migrate a Backstage project to use Yarn 3
title: Migration to Yarn 4
description: Guide for how to migrate a Backstage project to use Yarn 4
---
While Backstage projects created with `@backstage/create-app` use [Yarn 1](https://classic.yarnpkg.com/) by default, it
is possible to switch them to instead use [Yarn 3](https://yarnpkg.com/). Tools like `yarn backstage-cli versions:bump` will
still work, as they recognize both lockfile formats.
Backstage projects created with `@backstage/create-app` now use [Yarn 4](https://yarnpkg.com/), you may have a previous version of Backstage that is still using [Yarn 1](https://classic.yarnpkg.com/) that you'll want to migrate, this tutorial will help you with this task.
## Migration
@@ -19,7 +17,7 @@ First off, be sure to have the updated ignore entries in your app. These are inc
Add the following to `.gitignore`:
```gitignore
# Yarn 3 files
# Yarn files
.pnp.*
.yarn/*
!.yarn/patches
@@ -38,12 +36,18 @@ And this to `.dockerignore`:
### Installation
Let's move on to the actual installation. We'd recommend making separate Git commits of most of these steps, in case you need to go back and debug anything. To install Yarn 3, run the following command in the project root:
Let's move on to the actual installation. We'd recommend making separate Git commits of most of these steps, in case you need to go back and debug anything. To install Yarn 4, run the following command in the project root:
```bash
yarn set version 3.x
yarn set version 4.x
```
:::note
If the above command doesn't work then you may need to run `yarn set version latest` but use this with caution as it may take you to a version beyond Yarn 4
:::
We'll need the Yarn workspace tools plugin later on, so let's install that too:
```bash
@@ -56,23 +60,23 @@ In case you had a `.yarnrc` you can delete it now, but be sure to migrate over a
### Migrate Usage
At this point you'll be all set up with Yarn 3! What remains is to migrate any usage of Yarn according to their [migration guide](https://yarnpkg.com/getting-started/migration). For example, any `yarn install --frozen-lockfile` commands should be replaced with `yarn install --immutable`.
At this point you'll be all set up with Yarn 4! What remains is to migrate any usage of Yarn according to their [migration guide](https://yarnpkg.com/getting-started/migration). For example, any `yarn install --frozen-lockfile` commands should be replaced with `yarn install --immutable`.
You'll also need to update any `Dockerfile`s to add instructions to copy in your Yarn 3 installation into the image:
You'll also need to update any `Dockerfile`s to add instructions to copy in your Yarn 4 installation into the image:
```Dockerfile
COPY .yarn ./.yarn
COPY .yarnrc.yml ./
```
In a multi-stage `Dockerfile`, each stage that runs a `yarn` command will also need the Yarn 3 installation. For example, in the final stage you may need to add the following:
In a multi-stage `Dockerfile`, each stage that runs a `yarn` command will also need the Yarn 4 installation. For example, in the final stage you may need to add the following:
```Dockerfile
COPY --from=build --chown=node:node /app/.yarn ./.yarn
COPY --from=build --chown=node:node /app/.yarnrc.yml ./
```
The `--production` flag to `yarn install` has been removed in Yarn 3, instead you need to use `yarn workspaces focus --all --production` to avoid installing development dependencies in your production deployment. A tradeoff of this is that `yarn workspaces focus` does not support the `--immutable` flag.
The `--production` flag to `yarn install` has been removed in Yarn 4, instead you need to use `yarn workspaces focus --all --production` to avoid installing development dependencies in your production deployment. A tradeoff of this is that `yarn workspaces focus` does not support the `--immutable` flag.
```Dockerfile
RUN yarn workspaces focus --all --production && rm -rf "$(yarn cache clean)"
@@ -81,8 +85,6 @@ RUN yarn workspaces focus --all --production && rm -rf "$(yarn cache clean)"
Additionally, `yarn config` has been reworked from being able to store any arbitrary key-value pairs to only supporting a handful of predefined pairs. Previously, we would set our preferred `python3` interpreter to work around [any issues related to node-gyp](https://github.com/backstage/backstage/issues/11583) so we need to provide an appropriate substitute.
```Dockerfile
FROM node:16-bullseye-slim
# highlight-add-start
# Set Python interpreter for `node-gyp` to use
ENV PYTHON=/usr/bin/python3
@@ -15,7 +15,7 @@ coverage
# Dependencies
node_modules/
# Yarn 3 files
# Yarn files
.pnp.*
.yarn/*
!.yarn/patches
@@ -3,7 +3,7 @@
#
# Before building this image, be sure to have run the following commands in the repo root:
#
# yarn install
# yarn install --immutable
# yarn tsc
# yarn build:backend
#
@@ -26,7 +26,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install -y --no-install-recommends libsqlite3-dev
apt-get install -y --no-install-recommends libsqlite3-dev && \
rm -rf /var/lib/apt/lists/*
# From here on we use the least-privileged `node` user to run the backend.
USER node