コンテンツにスキップ

[4/5] GiteaでCI/CDパイプラインを構築する ビルド編

はじめに

この記事はGiteaを使ったCI/CDパイプラインの構築方法を展開する連載の一つである。

連載の各記事へは以下からジャンプできる。

  1. Giteaインストール編
  2. アプリケーション構築編
  3. テスト編
  4. ビルド編
  5. デプロイ編

CI/CDパイプラインでビルドを実行する

この記事では以下の赤枠部である、ビルドの自動実行をやってみよう。

Packagesを読み書きするためのアクセストークンを発行する

GiteaにはPackagesという機能があり、そこにDockerイメージを登録することができる。

Act Runnerはアクセストークンを使えばPackagesを読み書きできる。

アクセストークンを発行するために、以下のように画面右上のSettingsを選択する。

以下のように左にあるメニューからApplicationsを選択する。

Token Nameに任意の名前を入力し、packagerepositoryの読み書きを有効にした上でGenerate Tokenボタンを押下する。

以下のように画面上にトークンが表示されるのでコピーする。

リポジトリのSettingsに移動して、左のメニューにあるActions-Secretsを選択する。

Add secretのボタンを押下する。

以下のようにダイアログが表示されるので、NamePERSONAL_ACCESS_TOKENValueに先ほどコピーしたアクセストークンを貼り付け、Confirmのボタンを押下する。

Dockerイメージをビルドできるようにする

アプリケーションのDockerfileを作成する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.
├── Dockerfile
├── README.md
├── package-lock.json
├── package.json
├── src
│   ├── app.test.ts
│   ├── app.ts
│   ├── index.ts
│   ├── sum.test.ts
│   └── sum.ts
├── tsconfig.json
└── vitest.config.ts
Dockerfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# ビルドステージ
FROM node:24.14.1 AS build
WORKDIR /app

# 依存関係をインストールする
COPY package.json package-lock.json ./
RUN npm ci

# ソースコードをコピーしてビルドする
COPY . .
RUN npm run build

# プロダクションステージ
FROM node:24.14.1-slim AS production
ENV NODE_ENV=production
WORKDIR /app

# 本番用の依存関係のみインストールする
COPY package.json package-lock.json ./
RUN npm ci --omit=dev

# ビルド成果物をコピーする
COPY --from=build /app/dist ./dist

# アプリケーションを起動する
CMD ["node", "dist/index.js"]

手元でイメージをビルドし、動作を確認しておく。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Dockerイメージをビルドする
$ docker build -t $(node -p "require('./package.json').name"):$(node -p "require('./package.json').version") .
[+] Building 8.1s (18/18) FINISHED
 => [internal] load build definition from Dockerfile
 => => transferring dockerfile: 793B
 => [internal] load metadata for docker.io/library/node:24.14.1-slim
 => [internal] load metadata for docker.io/library/node:24.14.1
# 以下略

# Dockerイメージの一覧を確認する
$ docker images
IMAGE              ID             DISK USAGE   CONTENT SIZE   EXTRA
cicd-example:1.0.0 2fa08a2e94f6        227MB             0B

# Dockerコンテナを起動する
$ docker run -p 3030:3000 cicd-example:1.0.0
Server is running on http://localhost:3000

Webブラウザでhttp://localhost:3030にアクセスしたとき、以下のように1+1の結果が返ってきたらDockerイメージは正常に動作している。

Workflowにビルドのジョブを追加する

.gitea/workflows/workflow.ymlbuildのジョブを追加する。

このジョブはDockerfileのビルドを行い、イメージをPackagesへプッシュする。

.gitea/workflows/workflow.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
name: Workflow
on:
  push:
    branches:
      - main # mainブランチに対して実行する
env:
  NODE_VERSION: "24.14.1" # 使用するNode.jsのバージョンを定義する
jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - name: Install dependencies
        run: npm ci
      - name: Run typecheck
        run: npm run typecheck
  test:
    needs: typecheck # typecheckが通ったら実行する
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - name: Install dependencies
        run: npm ci
      - name: Run test
        run: npm run test
  build:
    runs-on: ubuntu-latest
    needs: [typecheck, test] # typecheckとtestが通ったら実行する
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      # Docker BuildxにHTTPのコンテナレジストリへのpushを許可する
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          buildkitd-config-inline: |
            [registry."${{ vars.REGISTRY_ENDPOINT }}"]
              http = true
              insecure = true
      # コンテナレジストリへの認証情報を設定する
      - name: Log in to Gitea container registry
        run: |
          mkdir -p ~/.docker
          AUTH=$(echo -n "${{ gitea.actor }}:${{ secrets.PERSONAL_ACCESS_TOKEN }}" | base64 -w 0)
          echo "{\"auths\":{\"${{ vars.REGISTRY_ENDPOINT }}\":{\"auth\":\"$AUTH\"}}}" > ~/.docker/config.json
      - name: Build and push
        run: |
          IMAGE_NAME=$(node -p "require('./package.json').name")
          TAG_NAME=$(node -p "require('./package.json').version")
          docker buildx build \
            --platform linux/amd64,linux/arm64 \
            --tag ${{ vars.REGISTRY_ENDPOINT }}/${{ gitea.repository_owner }}/$IMAGE_NAME:$TAG_NAME \
            --tag ${{ vars.REGISTRY_ENDPOINT }}/${{ gitea.repository_owner }}/$IMAGE_NAME:latest \
            --cache-from type=registry,ref=${{ vars.REGISTRY_ENDPOINT }}/${{ gitea.repository_owner }}/$IMAGE_NAME:buildcache \
            --cache-to type=registry,ref=${{ vars.REGISTRY_ENDPOINT }}/${{ gitea.repository_owner }}/$IMAGE_NAME:buildcache,mode=max \
            --provenance=false \
            --push \
            .

buildのジョブでは以下のことを行っている。

  • リポジトリをチェックアウトする
  • Node.js環境を用意する
  • Dockerイメージをマルチアーキテクチャでビルドし、Gitea Packagesにプッシュする

以下のようにリポジトリのSettingsにあるActions-Variablesにアクセスし、Add Variableのボタンを押下する。

登録先レジストリとしてGiteaのホストを追加する。(xxx.xxx.xxx.xxx:yyyyの形式で指定する)

リポジトリに変更内容をプッシュする。

1
2
3
$ git add -A
$ git commit -m "buildのジョブを定義した"
$ git push

CI/CDパイプラインが動作することを確認する。

ビルドしたイメージをリポジトリのPackagesに紐づける

CI/CDパイプラインからDockerイメージをプッシュしても以下の通りリポジトリのPackagesの画面には表示されない。

Dockerイメージを初めてプッシュしたときは、リポジトリのPackagesにDockerイメージを紐づける手順が必要となる。(2回目以降は要らない)

上の画面のpackage settingsのリンクを押下し、イメージ名を選択する。

以下の画面右下にあるSettingsを選択する。

以下の通りLink this package to a repositoryの欄にリポジトリ名を入力し、Update Repository Linkのボタンを押下する。

再度リポジトリのPackagesへアクセスし、Dockerイメージが登録されていることを確認する。

Dockerイメージを実行する

ローカル環境でDockerイメージを取得し、コンテナとして実行してみる。${Giteaホスト}にはxxx.xxx.xxx.xxx:yyyyの形式でGiteaのホストを指定する。

1
$ docker run -p 3030:3000 ${Giteaホスト}/kkawaharanet/cicd-example:latest

Dockerはデフォルトの設定ではHTTPのレジストリと通信しようとするとエラーになる。

1
2
3
4
5
$ docker run -p 3030:3000 xxx.xxx.xxx.xxx:yyyy/kkawaharanet/cicd-example:latest
Unable to find image 'xxx.xxx.xxx.xxx:yyyy/kkawaharanet/cicd-example:latest' locally
docker: Error response from daemon: Get "https://xxx.xxx.xxx.xxx:yyyy/v2/": http: server gave HTTP response to HTTPS client

Run 'docker run --help' for more information

この場合/etc/docker/daemon.jsonに以下の設定をマージする。

/etc/docker/daemon.json
1
2
3
{
  "insecure-registries": ["xxx.xxx.xxx.xxx:yyyy"]
}

Dockerデーモンを再起動する。

1
sudo systemctl restart docker.service docker.socket

再度コンテナの起動を試す。

1
2
$ docker run -p 3030:3000 xxx.xxx.xxx.xxx:yyyy/kkawaharanet/cicd-example:latest
Server is running on http://localhost:3000

Webブラウザでhttp://xxx.xxx.xxx.xxx:yyyy/sumにアクセスしたとき、1+1の結果が返ってきたら、GiteaのPackagesからDockerイメージを取得することに成功している。

振り返り

  • Docker Composeを使ってAct Runnerを構築することができた
  • Gitea ActionsのCI/CDパイプラインでDockerイメージをビルドしPackagesに登録することができた
  • Packagesに登録したDockerイメージをコンテナとして実行することができた

次回

次回はCI/CDパイプライン上でデプロイを行う。

[5/5] GiteaでCI/CDパイプラインを構築する デプロイ編