Ansibleのgitモジュールでアプリケーションデプロイを自動化する方法|ブランチ指定と環境ごとの展開設計

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Ansible > Ansibleのgitモジュールでアプリケーションデプロイを自動化する方法|ブランチ指定と環境ごとの展開設計
「デプロイするたびにサーバーへSSHして`git pull`を実行している」という運用を続けていませんか。
1台なら問題なく回せますが、staging環境とproduction環境に複数台が並ぶ構成になると、手順のズレや抜け漏れが起きやすくなります。

この記事では、Ansibleの`ansible.builtin.git`モジュールを使ってGitリポジトリからのアプリケーションデプロイを自動化する設計を解説します。RHEL 9系/Ubuntu 24.04 LTSを想定環境として説明します。ブランチ・タグ・コミットハッシュによる環境ごとの切り替え設計から、handlerとの組み合わせ、SSH鍵エラーやknown_hosts登録のトラブル対処まで整理します。

この記事のポイント

・ansible.builtin.gitモジュールでGit操作をPlaybookに組み込める
・versionパラメータでブランチ・タグ・コミットハッシュを切り替える
・group_varsでstaging/production環境ごとのブランチを分離するのが基本設計
・SSH鍵とホスト鍵の扱いが最初のつまずきになりやすい


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

手動git pullによるデプロイの限界

複数サーバーへのデプロイをシェルスクリプトのSSHループで自動化している場合、よく見られる構造は次のようなものです。

# よくある手動デプロイスクリプトの構造例 for host in web01 web02 web03; do ssh deploy@${host} "cd /opt/myapp && git pull origin main && systemctl restart myapp" done

このアプローチには3つの弱点があります。

・冪等性がない:すでに最新のコードが配置済みでも`git pull`が走り、不要なサービス再起動が発生する
・失敗時の制御が弱い:1台でgit pullが失敗しても、forループが次のホストへ進んでしまう可能性がある
・環境ごとの管理が煩雑になる:stagingとproductionで使うブランチが異なる場合、条件分岐がスクリプト内に積み重なっていく

Ansibleのgitモジュールを使うと、これらを設計として解決できます。

ansible.builtin.gitモジュールの概要

`ansible.builtin.git`は、リモートGitリポジトリをターゲットホストの指定パスにclone・checkoutするモジュールです。Ansibleの標準コレクション(ansible.builtin)に含まれるため、追加インストール不要で使えます。

設計上の重要な特徴は3点あります。

・冪等性:指定したブランチ・タグのコードがすでに配置済みであれば`changed=false`を返す。コードが変わっていなければhandlerが動かず、サービス再起動も発生しない
・再現性:versionパラメータにコミットハッシュを指定すれば、同じコミットのコードをいつでも再配置できる。タグ指定でリリース管理ができる
・SSH対応:SSH URLのリポジトリに対して、デプロイユーザーの鍵を通した認証が可能

gitモジュールの基本構文と主要パラメータ

1. 最小構成のタスク

- name: アプリケーションをデプロイする ansible.builtin.git: repo: git@github.com:myorg/myapp.git dest: /opt/myapp version: main accept_hostkey: true

・repo:リポジトリのURL。SSH URL(git@~)もHTTPS URL(https://~)も使える
・dest:チェックアウト先のディレクトリパス
・version:ブランチ名、タグ名、コミットハッシュのいずれかを文字列で指定。省略時はHEAD
・accept_hostkey:`true`にすると初回SSHホスト鍵を自動承認する(開発・stagingでは便利だが本番では後述の方法を推奨)

2. 主要パラメータ一覧

パラメータ 型 説明
repo string リポジトリURL(必須)
dest path チェックアウト先パス(必須)
version string ブランチ名・タグ名・コミットハッシュ(省略時はHEAD)
accept_hostkey bool 初回SSHホスト鍵を自動承認
key_file path SSH秘密鍵のパス(デフォルト鍵以外を使う場合)
force bool ローカルの変更を破棄してリモートに合わせる(デフォルト: false)
depth int shallow cloneの深さ(リポジトリ容量を抑えたい場合)
recursive bool submoduleを再帰的に初期化するか(デフォルト: true)
update bool リモートからの更新を行うか(falseにするとcloneのみ)

3. デプロイ専用ユーザーとSSH鍵を組み合わせる

本番環境ではデプロイ専用ユーザー(例: `deploy`)でgit操作を行い、そのユーザーの鍵を`key_file`で指定するのが一般的な設計です。

- name: 専用デプロイ鍵でアプリをクローンする ansible.builtin.git: repo: git@github.com:myorg/myapp.git dest: /opt/myapp version: "{{ app_version }}" key_file: /home/deploy/.ssh/deploy_rsa accept_hostkey: false become: true become_user: deploy

`become_user: deploy`でgit操作を行うユーザーを切り替え、`key_file`でそのユーザーが使う鍵パスを明示します。

環境ごとのブランチ・タグ指定設計

1. group_varsでversionを分離する

staging環境ではdevelopブランチ、production環境ではタグ(v1.2.3等)を使う構成を、Ansibleのgroup_varsで表現します。インベントリを環境ごとに分離し、それぞれのgroup_varsにapp_versionを定義します。

# inventories/staging/group_vars/webservers.yml app_version: develop app_repo: git@github.com:myorg/myapp.git app_dest: /opt/myapp # inventories/production/group_vars/webservers.yml app_version: v1.2.3 app_repo: git@github.com:myorg/myapp.git app_dest: /opt/myapp

Playbook側のgitタスクはversionを変数にするだけです。

- name: アプリケーションをデプロイする ansible.builtin.git: repo: "{{ app_repo }}" dest: "{{ app_dest }}" version: "{{ app_version }}" key_file: /home/deploy/.ssh/deploy_rsa accept_hostkey: false become: true become_user: deploy

環境の切り替えは`-i inventories/staging`または`-i inventories/production`でインベントリを指定するだけです。PlaybookのYAMLファイル自体は変更しません。

2. コミットハッシュでリリースを再現可能にする

本番環境では「どのコミットを配信したか」を後から追跡できることが重要です。タグの代わりにコミットハッシュ(SHA1の先頭7文字以上)をversionに指定すると、同じコードを何度でも正確に再現できます。

# inventories/production/group_vars/webservers.yml app_version: a3f8c12d # リリース当日のコミットハッシュを記録

コミットハッシュをgroup_varsに書き、Playbookそのものはリリースごとに変えません。ロールバックが必要になった場合も、group_varsのapp_versionを前のハッシュに戻してPlaybookを再実行するだけです。

AnsibleによるLinuxサーバー自動構成をより体系的に学びたい方は、Ansible入門コースも参考にしてください。

handlerと組み合わせた冪等なデプロイ設計

gitモジュールが`changed=true`を返した場合(コードが更新された場合)だけサービスを再起動するには、handlerを使います。`notify`にhandler名を指定することで、コードが変わらなければ再起動は発生しません。

# roles/deploy/tasks/main.yml - name: アプリケーションをデプロイする ansible.builtin.git: repo: "{{ app_repo }}" dest: "{{ app_dest }}" version: "{{ app_version }}" key_file: /home/deploy/.ssh/deploy_rsa accept_hostkey: false become: true become_user: deploy notify: アプリを再起動する # roles/deploy/handlers/main.yml - name: アプリを再起動する ansible.builtin.systemd: name: myapp state: restarted daemon_reload: true become: true

handlerはPlaybook全体の最後に1回だけ実行されます。同じPlaybook内で複数のタスクが同じhandlerをnotifyしても、再起動は1回で済みます。

また、デプロイ後にデータベースのマイグレーションコマンドを実行する場合も、gitモジュールのchanged結果を`register`で受け取り、`when: git_result.changed`で条件付き実行できます。

- name: アプリケーションをデプロイする ansible.builtin.git: repo: "{{ app_repo }}" dest: "{{ app_dest }}" version: "{{ app_version }}" key_file: /home/deploy/.ssh/deploy_rsa become: true become_user: deploy register: git_result - name: DBマイグレーションを実行する(コード更新時のみ) ansible.builtin.command: cmd: /opt/myapp/bin/migrate chdir: /opt/myapp become: true become_user: deploy when: git_result.changed

トラブルシュート

1. 「Host key verification failed」が出る

初回cloneでSSHホスト鍵が`known_hosts`に登録されていない場合に発生します。`accept_hostkey: true`で回避できますが、これは中間者攻撃(MITM)のリスクを受け入れることになります。production環境では、`ansible.builtin.known_hosts`モジュールで事前にホスト鍵を登録する方法が推奨です。

# GitHubのホスト鍵をknown_hostsに事前登録する例(出力例(環境により異なります)) - name: GitHubのホスト鍵をknown_hostsに登録する ansible.builtin.known_hosts: name: github.com key: "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG..." state: present become: true become_user: deploy

GitHubの公開ホスト鍵は`ssh-keyscan github.com`で取得できます。この値をVault変数で管理し、Playbook実行時に登録するとより安全な設計になります。

2. submoduleが更新されない

gitモジュールはデフォルトで`recursive: true`ですが、submoduleのリポジトリにデプロイ鍵のアクセス権がない場合、更新が失敗または静かにスキップされることがあります。確認すべき点は次の2つです。

・submoduleのリポジトリにデプロイ鍵の読み取り権限が設定されているか
・submoduleのURLをSSHからHTTPS(トークン認証)に変更できるか(CI/CD環境ではHTTPSの方が管理しやすい場合がある)

submoduleを使わない設計の場合は`recursive: false`を明示することで、意図しないsubmodule初期化を防げます。

3. 「pathspec did not match any file(s)」が出る

versionに指定したブランチ名やタグ名がリモートに存在しない場合に発生します。タイポや削除済みブランチへの参照が原因の多くを占めます。

versionをPlaybook実行時に`-e app_version=release/1.5`のように渡す運用にすると、タイポをCIでチェックしやすくなります。タグ名はソースリポジトリの命名規則(`v1.x.x`や`release/x.x`)をチームで統一することが先決です。

4. force: trueの危険性

`dest`に手動でファイルを置いていた場合や、過去の実行で設定ファイルが管理外で変更されていた場合、gitモジュールはデフォルトでエラーを返します。`force: true`を設定するとローカルの変更を問答無用で破棄してリモートに合わせますが、本番環境での`force: true`は「意図しない変更が消える事故」につながります。

本番環境では`force: true`を使わず、`dest`に手動ファイルを置く運用を禁止するルールをチームで定めるのが正しいアプローチです。設定ファイルの配布はgitモジュールではなく`ansible.builtin.template`モジュールで行い、それぞれの責務を分けると管理が明確になります。

本記事のまとめ

やりたいこと 設計・パラメータ
特定ブランチを環境ごとに切り替える ansible.builtin.git version: "{{ app_version }}"とgroup_varsの組み合わせ
リリースを完全再現可能にする versionにコミットハッシュを指定してgroup_varsに記録
コード更新時だけサービスを再起動する gitタスクにnotify + handlersでansible.builtin.systemdを再起動
コード更新時だけマイグレーションを実行する registerとwhen: git_result.changedで条件付き実行
SSH鍵をデプロイ専用に分離する key_file + become_user: deployの組み合わせ
production環境のSSHホスト鍵を安全に登録する ansible.builtin.known_hostsで事前登録(accept_hostkeyを使わない)
Ansibleのgitモジュールを使うと、`git pull`を手動で回す作業を設計として排除できます。group_varsでversionを管理することで、stagingとproductionのブランチ・タグ切り替えが1つのPlaybookで完結します。handlerとの組み合わせで、コードが変わった時だけ後続処理が動く冪等なデプロイパイプラインが構成できます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、
Linuxを体系的に学べる無料マニュアル(PDF)を用意しています。メルマガ登録で今すぐ受け取れます。
>> 無料マニュアルを受け取る

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。