更新日:2025年6月11日
4分で読めます
GitLabを活用して堅牢な継続的デプロイパイプラインを構築する方法をご紹介します。具体的な手順や例、ベストプラクティスを通して段階的にプロセスを理解できます。
継続的デプロイは、チームがより迅速かつ高い信頼性で価値を生み出せる画期的な手法です。しかし、GitOpsやKubernetesを用いたコンテナオーケストレーション、動的環境などの高度なデプロイワークフローに取り組むのは、継続的デプロイの導入を始めたばかりのチームにとってはハードルが高いと感じられるかもしれません。
GitLabでは、シームレスかつスケーラブルなデリバリーを実現することに注力しています。チームが基本に集中できるようにすることで、時間をかけてより複雑な戦略へと発展できる、強固な基盤を構築できます。このガイドでは、GitLabを活用した継続的デプロイの導入に必要な基本的なステップを紹介し、長期的な成功のための土台作りをサポートします。
技術的な実装に入る前に、デプロイワークフローをしっかりと設計する時間を取りましょう。成功の鍵は、慎重な計画と体系的なアプローチにあります。
継続的デプロイにおいて、アーティファクトとは、ビルドプロセスによって生成されるパッケージ化された成果物を指し、保存、バージョン管理、デプロイが必要です。アーティファクトには、次のようなものが含まれます。
各アーティファクトは、デプロイプロセスにおいて特定の役割を果たします。たとえば、一般的なWebアプリケーションでは、次のようなアーティファクトが生成されることがあります。
アーティファクトの適切な管理はデプロイを成功させる鍵となります。ここからは、アーティファクト管理のアプローチについて詳しく見ていきましょう。
クリーンで整理された構造を保つためのベストプラクティスとして、アーティファクトの明確なバージョニング戦略を確立することが重要です。リリース作成時のポイントは以下のとおりです。
myapp:1.2.3
の場合myapp:latest
(自動デプロイ用)myapp:1.2.3-abc123f
(デバッグ用)myapp:feature-user-auth
(新機能テスト用)明確な保持ルールを実装しましょう。
適切なアクセス制御でアーティファクトのセキュリティを確保しましょう。
環境設計はデプロイパイプライン全体の構成に影響を与えるため、早い段階で検討しましょう。
どこに、どのようにデプロイするのかを慎重に検討しましょう。これらの決定は重要であり、それぞれのメリットとデメリットを考慮する必要があります。
これで戦略が定まり、基盤となる決定が完了したので、これらの計画を実際に動作するパイプラインに落とし込んでいきます。それでは、実際に機能する例を作ることで概念を深掘りしていきましょう。まずはシンプルなアプリケーションから始め、徐々にデプロイの機能を追加していきます。
Webアプリケーション向けの基本的な継続的デプロイ(CD)パイプラインの実装手順を順を追って説明します。例としてシンプルなHTMLアプリケーションを使用しますが、ここで紹介する原則はどのタイプのアプリケーションにも応用できます。今回は、アプリケーションをDockerイメージとしてパッケージ化し、シンプルな仮想マシン上にデプロイします。これにより、最小限の依存関係を持つ厳選されたイメージを活用し、環境依存の要件が意図せず混入するのを防ぐことができます。また、仮想マシン上で動作させることで、GitLabのネイティブなインテグレーション機能を活用しない設定となります。複雑で本格的な環境ではなく、理解しやすい簡易的な環境から始めてみましょう。
この例では、クラウドプロバイダーの仮想マシン上で実行するアプリケーションをコンテナ化することを目指します。また、ローカル環境でもこのアプリケーションをテストします。以下の前提条件は、このシナリオにおいてのみ必要なものです。
GITLAB_KEY
という変数を作成しますSTAGING_TARGET
:ステージング環境のサーバーIPまたはドメインPRODUCTION_TARGET
:本番環境のサーバーIPまたはドメインdocker login registry.gitlab.com
# パーソナルアクセストークンを使用する場合のユーザー名はgitlab-ci-tokenです
# Password:(ここにアクセストークンを入力)
基本的なWebアプリケーションから始めましょう。今回の例では、シンプルなHTMLページを使用します。
<!|||UNTRANSLATED_CONTENT_START|||-- index.html -->
<html>
<head>
<style>
body {
background-color: #171321; /* GitLab dark */
}
</style>
</head>
<body>
<!|||UNTRANSLATED_CONTENT_END|||-- ここにコンテンツを追加 -->
</body>
</html>
アプリケーションをパッケージ化するために、Dockerfileを作成します:
FROM nginx:1.26.2
COPY index.html /usr/share/nginx/html/index.html
このDockerfileは
GitLabのパイプラインステージを定義するために、.gitlab-ci.yml
ファイル を作成します:
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHA
stages:
- publish
- deploy
解説:
TAG_LATEST
は、次の3つの要素で構成されています:
$CI_REGISTRY_IMAGE
:GitLabのプロジェクトのコンテナレジストリのパス例:registry.gitlab.com/your-group/your-project
$CI_COMMIT_REF_NAME
:ブランチ名またはタグ名例:ブランチの場合は/main
、フィーチャーブランチの場合は/feature-login
:latest
:固定のサフィックスこれにより、mainブランチのTAG_LATEST
は次のようになります:registry.gitlab.com/your-group/your-project/main:latest
TAG_COMMIT
はTAG_LATEST
とほぼ同じですが、:latest
の代わりにコミット識別子の$CI_COMMIT_SHA
を使います。例::abc123def456
したがって、同じmainブランチでのTAG_COMMIT
は次のようになります: registry.gitlab.com/your-group/your-project/main:abc123def456
両方のタグを使用する理由は、TAG_LATEST
が常に最新バージョンを取得しやすくするのに対し、TAG_COMMIT
は必要に応じて特定のバージョンに戻れるようにするためです。
パイプラインに公開ジョブを追加します:
publish:
stage: publish
image: docker:latest
services:
- docker:dind
script:
- docker build -t $TAG_LATEST -t $TAG_COMMIT .
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push $TAG_LATEST
- docker push $TAG_COMMIT
このジョブは
これで、コンテナイメージが安全にレジストリに保存されました。次は、ターゲット環境へのデプロイを進めていきます。本番環境へ移行する前に、まずローカル環境でテストを行い、設定が正しく機能していることを確認しましょう。
本番環境にデプロイする前に、ローカル環境でテストできます。先ほどGitLabレジストリにイメージを公開したので、それをローカル環境でプルしてテストします。コンテナイメージのパスが分からない場合は、GitLabのデプロイ > コンテナレジストリに移動し、該当のコンテナイメージの行末にあるアイコンをクリックすると、パスをコピーできます。
docker login registry.gitlab.com
docker run -p 80:80 registry.gitlab.com/your-project-path/main:latest
これにより、Webブラウザからlocalhostにアクセスし、ローカル環境でアプリケーションを確認できるようになります。
それでは、パイプラインにデプロイジョブを追加しましょう:
deploy:
stage: deploy
image: alpine:latest
script:
- chmod 400 $GITLAB_KEY
- apk add openssh-client
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- ssh -i $GITLAB_KEY -o StrictHostKeyChecking=no $USER@$TARGET_SERVER
docker pull $TAG_COMMIT &&
docker rm -f myapp || true &&
docker run -d -p 80:80 --name myapp $TAG_COMMIT
このジョブは
環境設定を追加してデプロイの追跡を有効にします:
deploy:
environment:
name: production
url: https://your-application-url.com
これにより、GitLabのオペレーション > 環境セクションに環境オブジェクトが作成され、以下の情報が提供されます:
単一の環境向けのパイプラインは、最初のステップとしては有効ですが、ほとんどのチームでは適切なテストやステージングを行うために複数の環境を管理する必要があります。このより実践的なシナリオに対応するために、パイプラインを拡張していきましょう。
より堅牢なパイプラインを構築するために、ステージング環境と本番環境のデプロイを設定します:
stages:
- publish
- staging
- release
- version
- production
staging:
stage: staging
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_COMMIT_TAG == null
environment:
name: staging
url: https://staging.your-app.com
# デプロイスクリプトを記述
production:
stage: production
rules:
- if: $CI_COMMIT_TAG
environment:
name: production
url: https://your-app.com
# デプロイスクリプトを記述
この設定は
このステップと次のステップでは、GitLabの非常に便利な機能であるタグを活用しています。GitLabのコード > タグセクションで手動でタグを作成すると、'$ CI_COMMMIT_TAG `変数が設定され、本番環境へのデプロイジョブが適切にトリガーされるようになります。
CI/CDパイプラインを通じてGitLabのリリース機能を使用します。まず、.gitlab-ci.yml
のstagesを更新 します:
stages:
- publish
- staging
- release # New stage for releases
- version
- production
次に、リリースジョブを追加します:
release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG # タグが作成された場合のみ実行する
script:
- echo "Creating release for $CI_COMMIT_TAG"
release: # リリース設定
name: 'Release $CI_COMMIT_TAG'
description: 'Release created from $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG' # タグを作成する
ref: '$CI_COMMIT_TAG' # リリースのベースとなるタグ
コンテナイメージのリンクを追加することで、さらに内容を充実させることができます:
release:
name: 'Release $CI_COMMIT_TAG'
description: 'Release created from $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
ref: '$CI_COMMIT_TAG'
assets:
links:
- name: 'Container Image'
url: '$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG'
link_type: 'image'
コミットメッセージに基づいて自動リリースノートを生成する場合は次のようにします:
release:
name: 'Release $CI_COMMIT_TAG'
description: 'Release notes for version $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
ref: '$CI_COMMIT_TAG'
auto_generate_release_notes: true # Enables automatic notes
自動リリースノートを充実させるには
デプロイ時の情報をリリースノートに記載したい場合は、以下のように設定できます:
release_job:
script:
- |
DEPLOY_TIME=$(date '+%Y-%m-%d %H:%M:%S')
CHANGES=$(git log $(git describe --tags --abbrev=0 @^)..@ --pretty=format:"- %s")
cat > release_notes.md << EOF
## デプロイ情報
- デプロイ日時: $DEPLOY_TIME
- 環境: 本番環境
- バージョン: $CI_COMMIT_TAG
## 変更内容
$CHANGES
## アーティファクト
- コンテナイメージ: \`$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\`
EOF
release:
description: './release_notes.md'
この設定を行うと、Gitタグの作成時に自動でリリースが作成されるようになります。作成されたリリースは、GitLabのデプロイ > リリースで確認できます。
最終的なYAMLファイルは以下のようになります:
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHA
STAGING_TARGET: $STAGING_TARGET # CI/CD変数で設定
PRODUCTION_TARGET: $PRODUCTION_TARGET # CI/CD変数で設定
stages:
- publish
- staging
- release
- version
- production
# ビルドとレジストリへの公開
publish:
stage: publish
image: docker:latest
services:
- docker:dind
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_COMMIT_TAG == null
script:
- docker build -t $TAG_LATEST -t $TAG_COMMIT .
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push $TAG_LATEST
- docker push $TAG_COMMIT
# stagingへデプロイ
staging:
stage: staging
image: alpine:latest
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_COMMIT_TAG == null
script:
- chmod 400 $GITLAB_KEY
- apk add openssh-client
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- ssh -i $GITLAB_KEY -o StrictHostKeyChecking=no $USER@$STAGING_TARGET "
docker pull $TAG_COMMIT &&
docker rm -f myapp || true &&
docker run -d -p 80:80 --name myapp $TAG_COMMIT"
environment:
name: staging
url: http://$STAGING_TARGET
# リリースの作成
release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG
script:
- |
DEPLOY_TIME=$(date '+%Y-%m-%d %H:%M:%S')
CHANGES=$(git log $(git describe --tags --abbrev=0 @^)..@ --pretty=format:"- %s")
cat > release_notes.md << EOF
## デプロイ情報
- デプロイ日時:$DEPLOY_TIME
- 環境:本番環境
- バージョン:$CI_COMMIT_TAG
## 変更内容
$CHANGES
## アーティファクト
- コンテナイメージ:\`$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\`
EOF
release:
name: 'Release $CI_COMMIT_TAG'
description: './release_notes.md'
tag_name: '$CI_COMMIT_TAG'
ref: '$CI_COMMIT_TAG'
assets:
links:
- name: 'コンテナイメージ'
url: '$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG'
link_type: 'image'
# リリースタグ付きのバージョンを作成
version_job:
stage: version
image: docker:latest
services:
- docker:dind
rules:
- if: $CI_COMMIT_TAG
script:
- docker pull $TAG_COMMIT
- docker tag $TAG_COMMIT $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG
# 本番環境へデプロイ
production:
stage: production
image: alpine:latest
rules:
- if: $CI_COMMIT_TAG
script:
- chmod 400 $GITLAB_KEY
- apk add openssh-client
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- ssh -i $GITLAB_KEY -o StrictHostKeyChecking=no $USER@$PRODUCTION_TARGET "
docker pull $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG &&
docker rm -f myapp || true &&
docker run -d -p 80:80 --name myapp $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG"
environment:
name: production
url: http://$PRODUCTION_TARGET
完成したパイプラインは
主なメリット:
実装の際は、以下の原則を守りましょう:
次は何をすべきでしょうか?ここでは、継続的デプロイ戦略をさらに成熟させるために、検討すべきポイントを紹介します。
以下の方法でセキュリティを強化しましょう:
以下のような高度なデプロイ戦略を実装しましょう。
強固なモニタリング体制を確立しましょう:
GitLabの継続的デプロイ機能は、現代のデプロイワークフローに最適です。GitLabは、コンテナレジストリ、環境管理、デプロイ追跡などの機能が1つのインターフェースに集約されており、コードから本番環境へのプロセスを効率化します。また、環境ごとの変数、デプロイ承認ゲート、ロールバック機能を備えており、本番環境へのデプロイ時に求められるセキュリティと管理を実現します。さらに、Review Apps(レビューアプリ)や機能フラグを活用することで、段階的なデリバリー(プログレッシブデリバリー)戦略も可能です。GitLabのDevSecOpsプラットフォームの一部として、これらのCD機能はソフトウェアライフサイクル全体とシームレスに連携します。
継続的デプロイへの道のりは、革命ではなく進化のプロセスです。まずは基本を押さえ、しっかりとした基盤を築き、チームの成長に応じて徐々に高度な機能を取り入れていきましょう。GitLabは、最初の自動デプロイから、複数環境にまたがる複雑なデリバリーパイプラインまで、あらゆる段階でサポートするためのツールと柔軟性を提供します。
GitLab Ultimateの60日間無料トライアルで、今日から継続的デプロイメントを始めましょう。
監修:川瀬 洋平 @ykawase
(GitLab合同会社 カスタマーサクセス本部 シニアカスタマーサクセスマネージャー)