まずは環境の準備から
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 --versionGitlab側では、今回用のプロジェクトを作成しておきます。
名前は 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.ymlindex.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を試してみる今回の連載は以上です。

