BackstageのDockerイメージをビルドしてみる
はじめに
BackstageのDockerイメージをビルドする方法について紹介していきたいと思います。
Backstageについては、以下の記事を参照してください。
【CNCF】Backstage触ってみた(Software Catalog)
はじめに CNCF プロジェクトの一つである、Backstage についてざっくり紹介して、メイ
BackstageのDockerイメージ
BackendのDockerイメージのビルド方法は大きく分けて以下の3つが用意されています。
- Docker外でアプリをビルドしてからイメージをビルド
- Dockerでマルチステージビルド
- フロントエンドとバックエンドを分けてビルド
Building a Docker image | Backstage Software Catalog and Developer Platform
How to build a Backstage Docker image for deployment
@backstage/create-app
で作成したプロジェクトの場合、デフォルトでは@backstage/plugin-app-backend
というプラグインによってフロントエンドがバックエンドに統合されているため、生成されるイメージは1つになり、1つのコンテナでフロントエンドとバックエンドが動作するようになっています。
紹介する3つの方法は、@backstage/create-app
で作成したプロジェクトを想定しています。
1npx @backstage/create-app@latest
Docker外でアプリをビルドしてからイメージをビルド
まずは、Docker外でアプリをビルドしてからイメージをビルドする方法です。
app-config.production.yamlを更新
app-config.production.yaml
を更新します。今回は、とりあえず動かしたいだけなので、下記のようにしています。
1app:
2 baseUrl: http://localhost:7007
3
4backend:
5 baseUrl: http://localhost:7007
6 listen:
7 port: 7007
8 auth:
9 keys:
10 - secret: xxxxxxx
11
12auth:
13 providers:
14 guest:
15 dangerouslyAllowOutsideDevelopment: true
アプリをビルド
下記のコマンドで、最初にアプリをビルドします。
1yarn install --frozen-lockfile
2yarn tsc
3yarn build:backend --config ../../app-config.yaml --config ../../app-config.production.yaml
Dockerイメージをビルド
packages/backend/Dockerfile
を作成します。
1FROM node:18-bookworm-slim
2
3# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
4RUN 5 \
6 apt-get update && \
7 apt-get install -y --no-install-recommends python3 g++ build-essential && \
8 yarn config set python /usr/bin/python3
9
10# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
11# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
12RUN 13 \
14 apt-get update && \
15 apt-get install -y --no-install-recommends libsqlite3-dev
16
17# From here on we use the least-privileged `node` user to run the backend.
18USER node
19
20# This should create the app dir as `node`.
21# If it is instead created as `root` then the `tar` command below will
22# fail: `can't create directory 'packages/': Permission denied`.
23# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`)
24# so the app dir is correctly created as `node`.
25WORKDIR /app
26
27# This switches many Node.js dependencies to production mode.
28ENV NODE_ENV production
29
30# Copy repo skeleton first, to avoid unnecessary docker cache invalidation.
31# The skeleton contains the package.json of each package in the monorepo,
32# and along with yarn.lock and the root package.json, that's enough to run yarn install.
33COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./
34RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
35
36RUN \
37 yarn install --frozen-lockfile --production --network-timeout 300000
38
39# Then copy the rest of the backend bundle, along with any other files we might want.
40COPY packages/backend/dist/bundle.tar.gz app-config*.yaml ./
41RUN tar xzf bundle.tar.gz && rm bundle.tar.gz
42
43CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
.dockerignore
も作成しておきます。
1.git
2.yarn/cache
3.yarn/install-state.gz
4node_modules
5packages/*/src
6packages/*/node_modules
7plugins
8*.local.yaml
必要なファイルが揃ったので、イメージをビルドします。
1docker image build . -f packages/backend/Dockerfile -t backstage:hostbuild
Dockerで起動
イメージが作成できたら、起動します。
1docker run -it -p 7007:7007 backstage:hostbuild
Dockerでマルチステージビルド
次に、Dockerでマルチステージビルドする方法です。
app-config.production.yamlを更新
app-config.production.yaml
を更新します。中身については、上記のやり方と同じ内容になっています。
1app:
2 baseUrl: http://localhost:7007
3
4backend:
5 baseUrl: http://localhost:7007
6 listen:
7 port: 7007
8 auth:
9 keys:
10 - secret: xxxxxxx
11
12auth:
13 providers:
14 guest:
15 dangerouslyAllowOutsideDevelopment: true
Dockerイメージをビルド
packages/backend/Dockerfile
を作成します。上記のやり方と異なり、マルチステージでアプリのビルドからイメージの作成までを行います。
1# Stage 1 - Create yarn install skeleton layer
2FROM node:18-bookworm-slim AS packages
3
4WORKDIR /app
5COPY package.json yarn.lock ./
6
7COPY packages packages
8
9# Comment this out if you don't have any internal plugins
10COPY plugins plugins
11
12RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf {} \+
13
14# Stage 2 - Install dependencies and build packages
15FROM node:18-bookworm-slim AS build
16
17# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
18RUN 19 \
20 apt-get update && \
21 apt-get install -y --no-install-recommends python3 g++ build-essential && \
22 yarn config set python /usr/bin/python3
23
24# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
25# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
26RUN 27 \
28 apt-get update && \
29 apt-get install -y --no-install-recommends libsqlite3-dev
30
31USER node
32WORKDIR /app
33
34COPY /app .
35
36RUN \
37 yarn install --frozen-lockfile --network-timeout 600000
38
39COPY . .
40
41RUN yarn tsc
42RUN yarn --cwd packages/backend build
43# If you have not yet migrated to package roles, use the following command instead:
44# RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies
45
46RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \
47 && tar xzf packages/backend/dist/skeleton.tar.gz -C packages/backend/dist/skeleton \
48 && tar xzf packages/backend/dist/bundle.tar.gz -C packages/backend/dist/bundle
49
50# Stage 3 - Build the actual backend image and install production dependencies
51FROM node:18-bookworm-slim
52
53# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
54RUN 55 \
56 apt-get update && \
57 apt-get install -y --no-install-recommends python3 g++ build-essential && \
58 yarn config set python /usr/bin/python3
59
60# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
61# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
62RUN 63 \
64 apt-get update && \
65 apt-get install -y --no-install-recommends libsqlite3-dev
66
67# From here on we use the least-privileged `node` user to run the backend.
68USER node
69
70# This should create the app dir as `node`.
71# If it is instead created as `root` then the `tar` command below will
72# fail: `can't create directory 'packages/': Permission denied`.
73# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`)
74# so the app dir is correctly created as `node`.
75WORKDIR /app
76
77# Copy the install dependencies from the build stage and context
78COPY /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton/ ./
79
80RUN \
81 yarn install --frozen-lockfile --production --network-timeout 600000
82
83# Copy the built packages from the build stage
84COPY /app/packages/backend/dist/bundle/ ./
85
86# Copy any other files that we need at runtime
87COPY app-config.yaml ./
88COPY app-config.production.yaml ./
89
90# This switches many Node.js dependencies to production mode.
91ENV NODE_ENV production
92
93CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
.dockerignore
も作成しておきます。
1dist-types
2node_modules
3packages/*/dist
4packages/*/node_modules
5plugins/*/dist
6plugins/*/node_modules
イメージをビルドします。
1docker image build . -f packages/backend/Dockerfile -t backstage:multistage
Dockerで起動
イメージが作成できたら、起動します。
1docker run -it -p 7007:7007 backstage:multistage
フロントエンドとバックエンドを分けてビルド
最後に、フロントエンドとバックエンドを分けてビルドする方法です。
バックエンドのプラグインの修正
まずは、@backstage/plugin-app-backend
の設定を削除します。
packages/backend/src/index.ts
から@backstage/plugin-app-backend
の設定を削除します。
1import { createBackend } from '@backstage/backend-defaults';
2
3const backend = createBackend();
4
5// backend.add(import('@backstage/plugin-app-backend/alpha')); ここを削除します
6backend.add(import('@backstage/plugin-proxy-backend/alpha'));
7backend.add(import('@backstage/plugin-scaffolder-backend/alpha'));
8backend.add(import('@backstage/plugin-techdocs-backend/alpha'));
9
10// auth plugin
11backend.add(import('@backstage/plugin-auth-backend'));
12// See https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin
13backend.add(import('@backstage/plugin-auth-backend-module-guest-provider'));
14// See https://github.com/backstage/backstage/blob/master/docs/auth/guest/provider.md
15
16// catalog plugin
17backend.add(import('@backstage/plugin-catalog-backend/alpha'));
18backend.add(
19 import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'),
20);
21
22// permission plugin
23backend.add(import('@backstage/plugin-permission-backend/alpha'));
24backend.add(
25 import('@backstage/plugin-permission-backend-module-allow-all-policy'),
26);
27
28// search plugin
29backend.add(import('@backstage/plugin-search-backend/alpha'));
30backend.add(import('@backstage/plugin-search-backend-module-catalog/alpha'));
31backend.add(import('@backstage/plugin-search-backend-module-techdocs/alpha'));
32
33backend.start();
プラグインはもう必要ないので、packages/backend/package.json
からも@backstage/plugin-app-backend
を削除します。
バックエンドのDockerfileを作成
バックエンド用のpackages/backend/Dockerfile
を作成します。内容としては、マルチステージビルドと同じになりますが、@backstage/plugin-app-backend
の設定を削除しているので、フロントエンドは統合されてないようになります。
1# Stage 1 - Create yarn install skeleton layer
2FROM node:18-bookworm-slim AS packages
3
4WORKDIR /app
5COPY package.json yarn.lock ./
6
7COPY packages packages
8
9# Comment this out if you don't have any internal plugins
10COPY plugins plugins
11
12RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf {} \+
13
14# Stage 2 - Install dependencies and build packages
15FROM node:18-bookworm-slim AS build
16
17# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
18RUN 19 \
20 apt-get update && \
21 apt-get install -y --no-install-recommends python3 g++ build-essential && \
22 yarn config set python /usr/bin/python3
23
24# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
25# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
26RUN 27 \
28 apt-get update && \
29 apt-get install -y --no-install-recommends libsqlite3-dev
30
31USER node
32WORKDIR /app
33
34COPY /app .
35
36RUN \
37 yarn install --frozen-lockfile --network-timeout 600000
38
39COPY . .
40
41RUN yarn tsc
42RUN yarn --cwd packages/backend build
43# If you have not yet migrated to package roles, use the following command instead:
44# RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies
45
46RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \
47 && tar xzf packages/backend/dist/skeleton.tar.gz -C packages/backend/dist/skeleton \
48 && tar xzf packages/backend/dist/bundle.tar.gz -C packages/backend/dist/bundle
49
50# Stage 3 - Build the actual backend image and install production dependencies
51FROM node:18-bookworm-slim
52
53# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
54RUN 55 \
56 apt-get update && \
57 apt-get install -y --no-install-recommends python3 g++ build-essential && \
58 yarn config set python /usr/bin/python3
59
60# Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image,
61# in which case you should also move better-sqlite3 to "devDependencies" in package.json.
62RUN 63 \
64 apt-get update && \
65 apt-get install -y --no-install-recommends libsqlite3-dev
66
67# From here on we use the least-privileged `node` user to run the backend.
68USER node
69
70# This should create the app dir as `node`.
71# If it is instead created as `root` then the `tar` command below will
72# fail: `can't create directory 'packages/': Permission denied`.
73# If this occurs, then ensure BuildKit is enabled (`DOCKER_BUILDKIT=1`)
74# so the app dir is correctly created as `node`.
75WORKDIR /app
76
77# Copy the install dependencies from the build stage and context
78COPY /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton/ ./
79
80RUN \
81 yarn install --frozen-lockfile --production --network-timeout 600000
82
83# Copy the built packages from the build stage
84COPY /app/packages/backend/dist/bundle/ ./
85
86# Copy any other files that we need at runtime
87COPY app-config.yaml ./
88COPY app-config.production.yaml ./
89
90# This switches many Node.js dependencies to production mode.
91ENV NODE_ENV production
92
93CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
フロントエンドのDockerfileを作成
フロントエンド用のpackages/app/Dockerfile
を作成します。内容としては、アプリのビルドをしてから、それをNginxで配信するようになっています。
1FROM node:18-bookworm-slim AS build
2
3RUN mkdir /app
4COPY . /app
5WORKDIR /app
6
7RUN yarn install
8COPY app-config.yaml ./
9COPY app-config.production.yaml ./
10RUN yarn workspace app build --config ../../app-config.yaml --config ../../app-config.production.yaml
11
12
13FROM nginx:mainline
14
15RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
16
17COPY /app/packages/app/dist /usr/share/nginx/html
18COPY packages/app/docker/default.conf.template /etc/nginx/templates/default.conf.template
19
20COPY packages/app/docker/inject-config.sh /docker-entrypoint.d/40-inject-config.sh
21
22ENV PORT 80
app-config.production.yamlを更新
最後に、app-config.production.yaml
を更新します。
フロントエンドとバックエンドは別々に動かすため、異なるbaseUrl
を設定します。また、CORSの設定も必要になります。ここでは、Docker Composeで動かす場合にポートフォーワードするlocalhost:8080
を許可しています。
1app:
2 baseUrl: http://localhost:7001
3
4backend:
5 baseUrl: http://backstage-sample-backstage-backend-1:7002
6 listen:
7 port: 7002
8 auth:
9 keys:
10 - secret: xxxxxxx
11 cors:
12 origin: http://localhost:8080
13 methods: [GET, HEAD, PATCH, POST, PUT, DELETE]
14 credentials: true
15
16auth:
17 providers:
18 guest:
19 dangerouslyAllowOutsideDevelopment: true
イメージのビルド
必要なファイルが用意できたら、イメージをビルドします。
1docker image build . -f packages/backend/Dockerfile -t backstage:backend
2docker image build . -f packages/app/Dockerfile -t backstage:frontend
Docker composeで起動
イメージが作成できたら、下記のようなdocker-compose.yml
を作成して、起動します。
1version: '3'
2services:
3 backstage-frontend:
4 image: backstage/frontend:latest
5 ports:
6 - 8080:80
7
8 backstage-backend:
9 image: backstage/backend:latest
10 ports:
11 - 7002:7002
1docker-compose up -d
まとめ
BackstageのDockerイメージをビルドする方法について紹介しました。
簡単に試すのであれば、フロントエンドとバックエンドを一緒にしたコンテナでも良さそうですが、本番環境などで運用する場合は、フロントエンドとバックエンドを分けた方が良いかもしれません。
下記のリポジトリで、Backstageの実装をいろいろ試していきたいと思います。
GitHub - monda00/backstage-sample
Contribute to monda00/backstage-sample development by creating an account on GitHub.
参考
- Building a Docker image | Backstage Software Catalog and Developer Platform
- backstage/contrib/docker/frontend-with-nginx at master · backstage/backstage
- backstage/docs/tutorials/auth-service-migration.md at 96b23786f648ea28c2ab81d4888c46ab8bbd907b · backstage/backstage
- backstage/docs/auth/service-to-service-auth.md at 96b23786f648ea28c2ab81d4888c46ab8bbd907b · backstage/backstage