CI/CD パイプライン: 自分だけのデプロイロボットを設計する

自動化は見知らぬものではない

前回、私は 10 分のダウンタイムと顛末書を通して痛い教訓を得た。デプロイとは魔法ではなく、「Git, 記録 – Test, 検証 – Build, 梱包 – Deploy, 配達」と続く厳格な安全装置の連続でなければならない、ということだ。

これで目標ははっきりした。この複雑で面倒な安全装置を毎回自分の手で確認し続けるわけにはいかない。私が退勤したあとでも、あるいは休暇に行ったときでも代わりに働いてくれる「真面目なロボット」が必要だ。

「自動化って、ちょっと大げさすぎない?」

最初は身構えてしまったが、よく考えてみると、私はすでに似たようなものを経験していた。前のシリーズで扱った「Docker」だ。

私たちが Dockerfile に「Ubuntu を入れて、Java を入れて、コードをコピーして」と書いておけば、Docker はそれを読み取って勝手にサーバー環境を構築してくれた。おかげで、手でコマンドを打ち続ける単純作業から解放された。

「CI/CD パイプライン」もまったく同じだ。Docker が「サーバー設定」を自動化したものだとすれば、パイプラインは「デプロイプロセス全体」を自動化するものだ。ただその舞台が、自分のパソコンの中から「GitLab と本番サーバー」というもっと大きな世界へ広がっただけだ。

Dockerfile がサーバー組み立て説明書なら、パイプラインは工場稼働の説明書だ。

CI/CD: 自動化されたコンベヤーベルト

では、私たちの「デジタル物流センター」に「自動化ライン」を敷いてみよう。大げさに見えるが、原理は単純だ。

1. CI (Continuous Integration, 継続的インテグレーション)

  • 意味: 「開発者たちのコードを絶えず一つに統合し、検査する。」
  • 役割: [ビルド + テスト]。私がコードを上げた瞬間に、機械が「これ、文法は合ってますか?」「既存の機能は壊れていませんか?」と確認してくれる段階だ。不良品はここで弾かれる。

2. CD (Continuous Delivery/Deployment, 継続的デリバリー/デプロイ)

  • 意味: 「検査を終えたコードを顧客に届ける。」
  • 役割: [イメージ生成 + サーバーデプロイ]。検査を通過した正常な製品 (Docker Image) をトラックに積んで本番サーバーへ送り、実行までさせる段階だ。

パイプラインの設計図: .gitlab-ci.yml

「じゃあ、そのロボットにはどうやって仕事をさせるの?」 GitLab では、プロジェクトの最上位に .gitlab-ci.yml というファイルを一つ作るだけでいい。これがロボットに渡す「作業指示書」だ。

前回、私が味わった手動デプロイの痛みを覚えているだろうか。その工程をそのままコードに移してみよう。まるで Dockerfile を書くように、一行ずつ書き下していけばいい。

# .gitlab-ci.yml(作業指示書)

stages:          # 1. 全体の作業順序を定義する
  - test         #   (1段階:検査)
  - build        #   (2段階:パッケージング)
  - deploy       #   (3段階:配送)

# [1段階] テスト:マシンよ、コードが大丈夫か確認してくれ(CI)
unit_test_job:
  stage: test
  image: openjdk:17-alpine # Javaが入っている環境で実行する
  script:
    - ./gradlew test       # "テストコードを回せ!" (前回のミスを防ぐ)

# [2段階] ビルド:テストが通ったらイメージを作って(CI)
build_image_job:
  stage: build
  image: docker:latest     # Dockerが入っている環境で実行する
  script:
    - docker build -t my-app:v1 .  # "イメージを焼け!"
    - docker push my-regisry/my-app:v1 # "レジストリに上げろ!" (ロールバック用タグ必須)

# [3段階] デプロイ:本番サーバーへ届けて(CD)
deploy_job:
  stage: deploy
  script:
    - ssh user@server "docker service update my-app" # "サーバーをアップデートしろ!"

必要なのはこのファイル一つだけだ。私が git push をした瞬間、つまり Trigger の瞬間に、GitLab はこの指示書を読み取り、「GitLab Runner」という作業ロボットを起こして仕事をさせる。

[Check] 私たちが備えるべき安全装置

このパイプラインの中には、前回痛感した「3 つの安全装置」がすべて組み込まれている。

  1. Git (Trigger):
    • 私がローカルでコードを push する行為そのものが、パイプラインの「スタートボタン」になる。記録 (Commit) が残らなければ、デプロイも始まらない。
  2. Unit Test (Quality Gate):
    • unit_test_job でテストが失敗したら? パイプラインは即座に「停止 (Fail)」する。不良品が次の段階(ビルド/デプロイ)へ進むことを根本から遮断するのだ。(これでもう、忙しいからといってテストを省くことはできない!)
  3. Docker Image (Artifact):
    • ビルド段階で生成されたイメージは Docker Hub に安全に保存される。後でサーバーが吹っ飛んでも、このイメージさえあれば 1 秒で復旧できる。
テストに合格できなかったコードは、絶対にデプロイトラックに積み込まれてはならない。

実務アドバイス: パイプラインは生き物だ

最初から完璧なパイプラインを書こうとしてはいけない。私も最初は build と deploy の 2 段階だけ作り、事故を起こしてからようやく前段に test を追加した。

  • 初期: ビルド -> デプロイ(まずは自動化できたこと自体に意義を置く)
  • 中期: テスト -> ビルド -> デプロイ(安全装置を追加)
  • 高度化: テスト -> 静的解析 (SonarQube) -> ビルド -> 開発サーバーへデプロイ -> (承認) -> 本番サーバーへデプロイ

パイプラインは、私たちのチームの成長速度に合わせて進化し続ける「生きているシステム」だ。

おわりに: 指示書は書いた。でも、実際に働くのは誰?

これで完璧な設計図、.gitlab-ci.yml、が完成した。だが、紙に書かれた指示書が勝手に動くわけではない。Dockerfile があっても Docker デーモンが入っていなければ動かないのと同じように、パイプラインの指示書にも実際に汗を流してコードをビルドし実行する「現場ロボット」が必要だ。

このロボットの名前は「GitLab Runner」だ。工場長、つまり GitLab Server、は指示を出すだけで、実際の作業はこの Runner が行う。

次回は、自分のパソコンや別のサーバーにこの Runner をインストールし、GitLab と連携させて実際にパイプラインを動かしてみよう。ついに自動化の最初のボタンがはめ込まれる瞬間だ。

コメントする