Skip to content

antony@notes:~/ops-automation$ cat "Build-backstage-Container-Image.md"

Build backstage Container Image

2023-10-10· ops-automation ·Backstage

Build backstage Container Image

Preface

本篇文章會主要會介紹如何,透過 Podman 工具設計並製作 Backstage 的 Container Image

可以透過點擊以下目錄,選擇想看的內容,跳轉至特定章節

:::warning

:::spoiler {state=“open”} 目錄

[TOC]

:::

Prerequisites

Hareware Requisites

  • MEM: 8 Gi
  • CPU: 4 Core
  • Disk: 100 GB

System Requisites

  • 須能上網
  • 作業系統
    • Ubuntu Server 22.04 LTS
    • Alpine 3.18
  • 可以執行 sudo 的使用者帳號
  • 以下套件須先安裝
    • Podman (Version: 4.6.2+)

系統環境準備

安裝 Podman 4

Step 1: Add Necessary Repository

使用 root 權限執行以下 shell Script

echo $'#!/bin/sh

ubuntu_version='22.04'
key_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key"
sources_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}"

echo "deb $sources_url/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list
curl -fsSL $key_url | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_unstable.gpg > /dev/null' | sudo sh

Step 2: Install Podman

$ sudo apt install podman

Step 3: 檢查 Podman 版本

$ podman -v

螢幕輸出 :

podman version 4.6.2

撰寫 Backstage-Backend Container file

建立工作目錄

$ mkdir -p ~/backstage/build-image/ && cd ~/backstage/build-image/

建置過程分為兩個不同階段 :

  • 第一階段
    • 安裝所有 package.json 檔案,以便快取安裝所有依賴項的初始 yarn install
  • 第二階段
    • 將所有內容打包成最終映像,與主機建置的 Dockerfile 類似。

建立 Container file

$ nano Containerfile.backend

以下是 Container file 的內容

# Stage 1 - Download and Install Backstage Backend App as a base Layer
FROM docker.io/library/ubuntu:latest AS Base

ENV HOME=/root \
    NODE_VERSION=v18.17.1

# Install required packages for Backstage
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends make python3 g++ build-essential git-all curl && \

    ## Setup Time Zone
    TZ=Asia/Taipei && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone && \
    dpkg-reconfigure -f noninteractive tzdata && \

    ## Using nvm install node.js (LTS)
    curl -so - https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash && \
    export NVM_DIR="$HOME/.nvm"  && \
    [ -s "$NVM_DIR/nvm.sh" ] && \
    . "$NVM_DIR/nvm.sh" && \
    nvm install $NODE_VERSION && \
    nvm use $NODE_VERSION && \

    ## Install yarn and npx
    npm install --global yarn && \

    ## Configure yarn use python3
    yarn config set python /usr/bin/python3 && \

    ## Create Backstage App
    echo backstage | npx -y @backstage/create-app@latest

ENV NVM_DIR="$HOME/.nvm" \
    NODE_PATH=$NVM_DIR/$NODE_VERSION/lib/node_modules \
    PATH=$NVM_DIR/$NODE_VERSION/bin:$PATH

WORKDIR backstage/

# Setup Git
RUN git init && \
    git config --global user.email "bobo@backstage.com" && \
    git config --global user.name "bobo" && \
    git add . && \
    git commit -m "Initial commit"

# build Backstage Backend
RUN . "$NVM_DIR/nvm.sh" && \
    yarn install --frozen-lockfile --network-timeout 600000 && \
    yarn tsc && \
    yarn --cwd packages/backend build

RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \
    && tar xzf packages/backend/dist/skeleton.tar.gz -C packages/backend/dist/skeleton \
    && tar xzf packages/backend/dist/bundle.tar.gz -C packages/backend/dist/bundle

# Stage 2 - Build the actual backend image and install production dependencies
FROM node:18-bookworm-slim

# Install isolate-vm dependencies, these are needed by the @backstage/plugin-scaffolder-backend.
RUN apt-get update && \
    apt-get install -y --no-install-recommends python3 g++ build-essential && \
    yarn config set python /usr/bin/python3

# 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`.
WORKDIR /app

# Copy the install dependencies from the build stage and context
COPY --from=Base --chown=node:node /backstage/yarn.lock /backstage/package.json /backstage/packages/backend/dist/skeleton/ ./

RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \
    yarn install --frozen-lockfile --production --network-timeout 600000

# Copy the built packages from the build stage
COPY --from=Base --chown=node:node /backstage/packages/backend/dist/bundle/ ./

# Copy any other files that we need at runtime
COPY --from=Base --chown=node:node /backstage/app-config.yaml ./

# This switches many Node.js dependencies to production mode.
ENV NODE_ENV production

CMD ["node", "packages/backend", "--config", "app-config.yaml"]

Build Backstage-Backend Container Image

$ sudo podman build --no-cache -t backstage-backend:v1 -f Containerfile.backend

撰寫 Backstage-Backend Podman Pod Yaml File

$ nano ~/backstage/podman-pod/backstage-backend.yaml

檔案內容如下

apiVersion: v1
kind: Pod
metadata:
  name: backstage
spec:
  containers:
  - name: backstage-backend
    image: localhost/backstage-backend:v1
    volumeMounts:
    - name: app-config
      mountPath: /app/app-config.yaml
      subPath: app-config.yaml
  - name: backstage-frontend
    image: localhost/backstage-frontend:v1
  volumes:
  - name: app-config
    hostPath:
      path: ~/backstage/backstage/app-config.yaml

建立並測試 Backstage-Backend Pod

$ sudo podman run -it -d --mount type=bind,source=app-config.yaml,destination=/app/app-config.yaml localhost/backstage-backend:v1 bash