このブログを検索

この記事の内容は、個人の見解、検証の範囲のものであり、誤りがある可能性があります。
個人の責任において情報活用をお願いします。


2026年9月30日水曜日

GitLab と GitLab Runner を連携させて CI/CD っぽいことをしてみる その6

今回は Docker で動かしたコンテナを CI/CD で更新してみようと思います。

まずは環境の準備から
Docker はコミュニティエディションを使いますので手順を確認してやっていきます。

docker-ceのインストール手順
https://docs.docker.com/engine/install/ubuntu/

リポジトリのセットアップ

パッケージの導入
$ sudo apt-get update
$ sudo apt-get install -y ca-certificates curl gnupg
公式GPG鍵の追加
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
$ sudo chmod a+r /etc/apt/keyrings/docker.asc
公式リポジトリの登録
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker CEのインストール

$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

このままでは、gitlab-runnerユーザーが Docker を使えません。
gitlab-runnerユーザーがdockerを使えるように権限を設定します。 # gitlab-runner ユーザーを docker グループに再追加
sudo usermod -aG docker gitlab-runner
# Docker サービスおよび GitLab Runner の再起動
sudo systemctl restart docker
sudo systemctl restart gitlab-runner
# バージョン確認(Docker Engine - Community と表示されれば成功です)
docker --version
Gitlab側では、今回用のプロジェクトを作成しておきます。
名前は docker-cicd-pj にしました。
もちろん、gitlab-runnerと連携しておきます。

これで準備はできました。

この後以下を作成してpushします。
・WEBページ用の index.html
・コンテナ作成用の Dockerfile
・gitlab-runner を動かすための .gitlab-ci.yml

docker-cicd-pj はこのような構造になる予定です。
docker-cicd-pj/
├── Dockerfile
├── index.html
└── .gitlab-ci.yml
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Docker CI/CD Demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-dark text-white">
    <div class="container py-5 text-center">
        <div class="card bg-warning text-dark p-4 shadow-lg mb-4">
            <h1 class="display-4 fw-bold">Apache Container v1</h1>
            <p class="lead">GitLab Container Registry から自動デプロイされました!</p>
        </div>
        <div class="card bg-secondary text-white p-3 text-start shadow">
            <h5>デプロイ情報</h5>
            <ul class="list-group list-group-flush text-dark">
                <li class="list-group-item"><b>ビルド日時:</b> BUILD_TIME_PLACEHOLDER</li>
                <li class="list-group-item"><b>コミットID:</b> COMMIT_REF_PLACEHOLDER</li>
            </ul>
        </div>
    </div>
</body>
</html>

Dockerfile
FROM httpd:2.4-alpine

# HTMLファイルをApacheのドキュメントルートへコピー
COPY index.html /usr/local/apache2/htdocs/index.html

EXPOSE 80
.gitlab-ci.yml
stages:
  - deploy

deploy-from-tmp:
  stage: deploy
  tags:
    - docker-cicd
  script:
    - echo "=== 1. /tmp の古いクローン領域を削除して最新コードをクローン ==="
    - rm -rf /tmp/docker-cicd-pj
    - git clone $CI_REPOSITORY_URL /tmp/docker-cicd-pj

    - echo "=== 2. クローンした領域内で index.html の動的データを書き換え ==="
    - CURRENT_TIME=$(date "+%Y-%m-%d_%H:%M:%S")
    - sed -i "s/BUILD_TIME_PLACEHOLDER/$CURRENT_TIME/g" /tmp/docker-cicd-pj/index.html
    - sed -i "s/COMMIT_REF_PLACEHOLDER/$CI_COMMIT_SHORT_SHA/g" /tmp/docker-cicd-pj/index.html

    - echo "=== 3. /tmp/docker-cicd-pj の Dockerfile からイメージをビルド ==="
    - docker build -t my-app-image:latest /tmp/docker-cicd-pj

    - echo "=== 4. 古いコンテナの停止と削除 ==="
    - docker stop my-app-container || true
    - docker rm my-app-container || true

    - echo "=== 5. ビルドしたイメージからコンテナを起動 ==="
    - docker run -d --name my-app-container -p 8080:80 my-app-image:latest

    - echo "=== 6. /tmp のクローン領域を削除(後片付け) ==="
    - rm -rf /tmp/docker-cicd-pj

    - echo 'デプロイ完了'

これを push して起動を確認します。

WEBページが確認できたので、新しいindex.htmlを作成して更新してみましょう。
更新時の動きとしては以下となる予定です。

1. Gitlab へ新しい index.html を push する
2. gitlab-runner が動いてプロジェクト(docekr-cicd-pj)を gitlab-runner のローカルにクローン
3. 古いコンテナや情報を削除して、中にある新しい index.html と Dockerfile を使用してコンテナを再作成

更新用の index.html を作成して push します。
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Docker CI/CD Demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-dark text-white">
    <div class="container py-5 text-center">
        <div class="card bg-success text-white p-4 shadow-lg mb-4"></div>
            <h1 class="display-4 fw-bold">Apache Container v2</h1>
            <h2 class="display-5 fw-bold">Docker 自動デプロイ成功!</h2>
            <p class="lead">GitLab CI/CD 経由でコンテナが正常に更新されました(Version 2.0)</p>
        </div>

        <div class="card bg-secondary text-white p-3 text-start shadow">
            <h5 class="border-bottom pb-2">ビルド&デプロイ メタ情報</h5>
            <ul class="list-group list-group-flush text-dark mt-2">
                <li class="list-group-item"><b>ステータス:</b> <span class="badge bg-success">Active</span></li>
                <li class="list-group-item"><b>デプロイ方式:</b> /tmp クローン & ローカルビルド</li>
                <li class="list-group-item"><b>更新日時:</b> BUILD_TIME_PLACEHOLDER</li>
                <li class="list-group-item"><b>コミットID:</b> COMMIT_REF_PLACEHOLDER</li>
            </ul>
        </div>
    </div>
</body>
</html>

更新されたか確認してみましょう。
更新が反映されています。
ちなみにジョブの出力結果はこちら。
Running with gitlab-runner 18.10.0 (ac71f4d8)
  on git-runner rMlHrOQJF, system ID: s_360a4d9afbdb
Preparing the "shell" executor
00:00
Using Shell (bash) executor...
Preparing environment
00:00
Running on git-runner...
Getting source from Git repository
00:01
Gitaly correlation ID: 01M1B86PGPWS7FXWRZ5AHXCSZ1
Fetching changes with git depth set to 20...
Reinitialized existing Git repository in /home/gitlab-runner/builds/rMlHrOQJF/0/docker-cicd/docker-cicd-pj/.git/
Checking out 9ccfc415 as detached HEAD (ref is main)...
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:04
$ echo "=== 1. /tmp の古いクローン領域を削除して最新コードをクローン ==="
=== 1. /tmp の古いクローン領域を削除して最新コードをクローン ===
$ rm -rf /tmp/docker-cicd-pj
$ git clone $CI_REPOSITORY_URL /tmp/docker-cicd-pj
Cloning into '/tmp/docker-cicd-pj'...
$ echo "=== 2. クローンした領域内で index.html の動的データを書き換え ==="
=== 2. クローンした領域内で index.html の動的データを書き換え ===
$ CURRENT_TIME=$(date "+%Y-%m-%d_%H:%M:%S")
$ sed -i "s/BUILD_TIME_PLACEHOLDER/$CURRENT_TIME/g" /tmp/docker-cicd-pj/index.html
$ sed -i "s/COMMIT_REF_PLACEHOLDER/$CI_COMMIT_SHORT_SHA/g" /tmp/docker-cicd-pj/index.html
$ echo "=== 3. /tmp/docker-cicd-pj の Dockerfile からイメージをビルド ==="
=== 3. /tmp/docker-cicd-pj の Dockerfile からイメージをビルド ===
$ docker build -t my-app-image:latest /tmp/docker-cicd-pj
#0 building with "default" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 195B done
#1 DONE 0.0s
#2 [internal] load metadata for docker.io/library/httpd:2.4-alpine
#2 DONE 0.9s
#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s
#4 [internal] load build context
#4 transferring context: 1.39kB done
#4 DONE 0.0s
#5 [1/2] FROM docker.io/library/httpd:2.4-alpine@sha256:1b766f17b84026429b7cb243317b142921b24432336e798bc881c43f45ed9567
#5 resolve docker.io/library/httpd:2.4-alpine@sha256:1b766f17b84026429b7cb243317b142921b24432336e798bc881c43f45ed9567 0.0s done
#5 CACHED
#6 [2/2] COPY index.html /usr/local/apache2/htdocs/index.html
#6 DONE 0.1s
#7 exporting to image
#7 exporting layers 0.1s done
#7 exporting manifest sha256:ae6b5ca41d606757d0e9fa2678270a5f24a0ec49f0a6423571e3dcdbab16da8e
#7 exporting manifest sha256:ae6b5ca41d606757d0e9fa2678270a5f24a0ec49f0a6423571e3dcdbab16da8e 0.0s done
#7 exporting config sha256:569f535352505abb5a898f1fdbc61bf19c8161a5631aad12cfaf31f6ed06a248 0.0s done
#7 exporting attestation manifest sha256:100a3a290715618a814ef240521bb9879c43f3893abc1ad21222cb5aa16e3483 0.0s done
#7 exporting manifest list sha256:8e9f66d4dbe809faac1d3d5fb73284f6778b1985e5a2a0489b56beafce6f99b3 0.0s done
#7 naming to docker.io/library/my-app-image:latest done
#7 unpacking to docker.io/library/my-app-image:latest
#7 unpacking to docker.io/library/my-app-image:latest 0.0s done
#7 DONE 0.3s
$ echo "=== 4. 古いコンテナの停止と削除 ==="
=== 4. 古いコンテナの停止と削除 ===
$ docker stop my-app-container || true
my-app-container
$ docker rm my-app-container || true
my-app-container
$ echo "=== 5. ビルドしたイメージからコンテナを起動 ==="
=== 5. ビルドしたイメージからコンテナを起動 ===
$ docker run -d --name my-app-container -p 8080:80 my-app-image:latest
142868761a25c043cea7f2f5b444336f8fef3341a0cb186b0e6113372c39a7e1
$ echo "=== 6. /tmp のクローン領域を削除(後片付け) ==="
=== 6. /tmp のクローン領域を削除(後片付け) ===
$ rm -rf /tmp/docker-cicd-pj
$ echo 'デプロイ完了'
デプロイ完了
Cleaning up project directory and file based variables
00:00
Job succeeded
という事で CI/CDを試してみる今回の連載は以上です。