
Ansibleを使用して、Ubuntu上で効率的なミドルウェア構成管理を行う方法を紹介します。
本記事では、Ansibleの基本的な概念から、実際にPlaybookを作成してDockerやTerraformのインストールを自動化する手順までを網羅します。
エージェントレスで簡単にインフラ管理を行うAnsibleの魅力と、実際の運用に役立つポイントを実例を交えて解説しています。
これからAnsibleを導入したい方や、Ubuntu環境での自動化に関心のある方に向けた内容となっています。
ubntuのバージョンや設定は以前の投稿の内容となりますので、参考にしていただければ幸いです。
Ansibleのインストールと動作確認
ubntuに以下のコマンドを実行してpython3とansibleをインストールする。
sudo apt update
sudo apt install -y python3 python3-pip
sudo apt install -y ansible
ansibleのバージョンを確認する。
ubntu@ubntu:~$ ansible --version
ansible [core 2.16.3]
config file = None
configured module search path = ['/home/ubntu/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/ubntu/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True
Ansible の ping モジュールを使って、ローカルのホストにアクセスできるか確認する。
警告が出ているものの、イベントリを明示的に指定することでこの警告は消える。疎通自体は問題ない。pongと返ってきたら成功だ。
ubntu@ubntu:~$ ansible localhost -m ping --connection=local
[WARNING]: No inventory was parsed, only implicit localhost is available
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
イベントリファイルの作成も行う。
echo "localhost ansible_connection=local" > hosts
シンプルな Playbook を作って、パッケージのインストールができるか確認する。
- name: Test Playbook
hosts: localhost
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
- name: Install tree
apt:
name: tree
state: present
playbookの実行を行う。-iでイベントリファイルの指定と--connectionの指定をすることで警告が出なくなる。
ubntu@ubntu:~$ sudo ansible-playbook -i localhost, test.yml
PLAY [Test Playbook] ***********************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Update apt cache] ********************************************************
changed: [localhost]
TASK [Install tree] ************************************************************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
playbookによりtreeがインストールされていることを確認する。
ubntu@ubntu:~$ tree --version
tree v2.1.1 © 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro
DockerとterraformをAnsibleでインストール
DockerとterraformをインストールするPlaybookの作成を行う。
新しいPlaybookファイル「install_docker_terraform.yml」を作成する。
---
- name: Install Docker and Terraform
hosts: localhost
become: yes # root 権限で実行
tasks:
- name: Install required packages
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- software-properties-common
state: present
update_cache: yes
# Docker のインストール
- name: Add Docker GPG key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Install Docker
apt:
name: docker-ce
state: present
update_cache: yes
- name: Start and enable Docker service
systemd:
name: docker
enabled: yes
state: started
- name: Add current user to Docker group
user:
name: "{{ ansible_user_id }}"
groups: docker
append: yes
# Terraform のインストール
- name: Add HashiCorp GPG key
apt_key:
url: https://apt.releases.hashicorp.com/gpg
state: present
- name: Add HashiCorp repository
apt_repository:
repo: "deb [arch=amd64] https://apt.releases.hashicorp.com {{ ansible_distribution_release }} main"
state: present
- name: Install Terraform
apt:
name: terraform
state: present
update_cache: yes
作成したカレントディレクトリ内で以下のコマンドを実行する。
カレントディレクトリに「install_docker_terraform.yml」が存在することを確認する。
ubntu@ubntu:~$ ls -la install_docker_terraform.yml
-rw------- 1 ubntu ubntu 1601 3月 6 10:08 install_docker_terraform.yml
Playbookを実行する。
sudo ansible-playbook install_docker_terraform.yml
実行結果
ubntu@ubntu:~$ sudo ansible-playbook install_docker_terraform.yml
[sudo] ubntu のパスワード:
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'
PLAY [Install Docker and Terraform] ********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Install required packages] ***********************************************
changed: [localhost]
TASK [Add Docker GPG key] ******************************************************
changed: [localhost]
TASK [Add Docker repository] ***************************************************
changed: [localhost]
TASK [Install Docker] **********************************************************
changed: [localhost]
TASK [Start and enable Docker service] *****************************************
ok: [localhost]
TASK [Add current user to Docker group] ****************************************
changed: [localhost]
TASK [Add HashiCorp GPG key] ***************************************************
changed: [localhost]
TASK [Add HashiCorp repository] ************************************************
changed: [localhost]
TASK [Install Terraform] *******************************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=10 changed=8 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

警告は出ているが-i "localhost," --connection=localが入ってないからだろう。
-i "localhost," --connection=localを付けたところ警告が消えてすでに適応済みのためオールOKの結果となった。
ubntu@ubntu:~$ sudo ansible-playbook -i "localhost," --connection=local install_docker_terraform.yml
PLAY [Install Docker and Terraform] ********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Install required packages] ***********************************************
ok: [localhost]
TASK [Add Docker GPG key] ******************************************************
ok: [localhost]
TASK [Add Docker repository] ***************************************************
ok: [localhost]
TASK [Install Docker] **********************************************************
ok: [localhost]
TASK [Start and enable Docker service] *****************************************
ok: [localhost]
TASK [Add current user to Docker group] ****************************************
ok: [localhost]
TASK [Add HashiCorp GPG key] ***************************************************
ok: [localhost]
TASK [Add HashiCorp repository] ************************************************
ok: [localhost]
TASK [Install Terraform] *******************************************************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=10 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Playbook実行後の確認
dockerインストールの確認を行う。
ubntu@ubntu:~$ docker --version
Docker version 28.0.1, build 068a01e
ubntu@ubntu:~$ sudo systemctl status docker
[sudo] ubntu のパスワード:
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-03-06 10:16:01 JST; 4h 7min ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 9292 (dockerd)
Tasks: 9
Memory: 20.7M (peak: 21.5M)
CPU: 2.603s
CGroup: /system.slice/docker.service
└─9292 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
3月 06 10:16:00 ubntu dockerd[9292]: time="2025-03-06T10:16:00.837570637+09:00" level=info msg="OTEL tracing is not configured, using no-op tracer provider"
3月 06 10:16:00 ubntu dockerd[9292]: time="2025-03-06T10:16:00.837742144+09:00" level=info msg="detected 127.0.0.53 nameserver, assuming systemd-resolved, >
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:00.997428634+09:00" level=info msg="Loading containers: start."
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:01.752933785+09:00" level=info msg="Loading containers: done."
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:01.830289688+09:00" level=info msg="Docker daemon" commit=bbd0a17 containerd-snapshotter=false >
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:01.830704688+09:00" level=info msg="Initializing buildkit"
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:01.904111672+09:00" level=info msg="Completed buildkit initialization"
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:01.914128754+09:00" level=info msg="Daemon has completed initialization"
3月 06 10:16:01 ubntu dockerd[9292]: time="2025-03-06T10:16:01.914247463+09:00" level=info msg="API listen on /run/docker.sock"
3月 06 10:16:01 ubntu systemd[1]: Started docker.service - Docker Application Container Engine.

dockerはversion 28.0.1でインストールされて現在動いている状態のようだ。自動起動も有効になっている。
terraformのインストールの確認も行う。
ubntu@ubntu:~$ terraform version
Terraform v1.11.1
on linux_amd64
terraformも無事インストールされていることが確認できた。
Playbook解説
install_docker_terraform.ymlの中身を見ていきたい。
Install required packages
- name: Install required packages
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- software-properties-common
state: present
update_cache: yes
この処理はDockerやTerraformをインストールする前に必要なパッケージを準備するものとなる。
各パッケージの役割
パッケージ名 | 役割 |
---|---|
apt-transport-https | apt で HTTPS を利用できるようにする |
ca-certificates | 信頼された SSL/TLS 証明書を提供 |
curl | HTTP リクエストを送るツール(GPGキー取得などに必要) |
software-properties-common | apt-add-repositoryコマンドを提供 |
これらのパッケージがないと、リポジトリの追加や HTTPS でのダウンロードができないため、事前にインストールしておく。
httpsを使うことで、通信を暗号化し中間者攻撃のリスクを回避する。
{{ ansible_user_id }}
- name: Add current user to Docker group
user:
name: "{{ ansible_user_id }}"
groups: docker
append: yes
{{ ansible_user_id }}の意味は何か。
この変数はAnsibleのsetupモジュールで自動取得され、このPlaybookを実行したログイン名(実行ユーザ)を{{ ansible_user_id }}で取得し、そのユーザをdockerグループに追加している。
/etc/groupを確認したところrootがdockerグループに所属している。sudoによりrootで実行したためだ。
ubntu@ubntu:~$ cat /etc/group | grep docker
docker:x:986:root
🔹 何をしているのか?
- Docker は root または docker グループのユーザーしか操作できないため、実行ユーザーを docker グループに追加。
- append: yes により、既存のグループに影響を与えずに docker グループを追加。
🔹 どこから取得しているのか?
- Ansible の setup モジュールで取得(Playbook 実行時に自動で取得される)
- 環境変数 whoami のようなもの
append: yes
append: yesを書かないとどうなるか。
もしappend: yesを書かないとgroupで指定したグループ以外の所属が消えてしまう可能性がある。
例えば、以下のように実行した場合にはubntuユーザの既存グループはdockerだけになってしまう。具体的な挙動例については後述するので確認してほしい。
- name: Add user to docker group (without append)
user:
name: "ubntu"
groups: docker
例1append no
ユーザーの元のグループ
$ groups ubntu
ubntu : ubntu sudo developers
append: no(デフォルト)で docker グループを設定
- name: Add user to docker group (without append)
user:
name: "ubntu"
groups: docker # append: yes がない
実行後のグループ
$ groups ubntu
ubntu : docker # 他のグループが消えてしまった!
例2 append yes
ユーザーの元のグループ
$ groups ubntu
ubntu : ubntu sudo developers
append: yes で docker グループを追加
- name: Add user to docker group
user:
name: "ubntu"
groups: docker
append: yes
実行後
$ groups ubntu
ubntu : ubntu sudo developers docker
GPG キー & リポジトリ追加
- name: Add Docker GPG key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
GPGキー追加
https://download.docker.com/linux/ubuntu/gpg を取得し、信頼する鍵として登録
🔹 GPG キーとは?
- 各パッケージ(Docker や Terraform)の提供元が 信頼できる ことを保証するための 署名キー
- これを登録しないと、apt でのインストール時に「信頼できないリポジトリ」と見なされ、エラーが発生する
リポジトリ追加
- deb [arch=amd64] https://download.docker.com/linux/ubuntu noble stable のようなリポジトリを /etc/apt/sources.list.d/ に追加
- {{ ansible_distribution_release }} は、Ubuntu の バージョン名(例: focal, jammy, noble) を自動取得して設定
{{ ansible_distribution_release }}はAnsibleの組み込み変数で、現在の Ubuntu のコードネーム(例: focal, jammy, noble)が格納される。
この変数を利用することで、Ubntuのバージョン毎に異なるリポジトリを指定することができ、どのUbntuからでもPlaybookが本用的に動作する。(ハードコーディング不要)
🔹リポジトリ追加とは?
- Ubuntu の apt は デフォルトのリポジトリ に含まれていないソフトウェアを扱えない
- 公式リポジトリを追加することで、Docker や Terraform の最新バージョンを apt install で取得可能になる。
インストールされるミドルウェアのバージョンについて
🔹 実行時の最新バージョン
apt:
name: docker-ce
state: present
update_cache: yes
- state: present の場合 → 実行時点で利用可能な 最新バージョン がインストールされる
- update_cache: yes で apt update を事前に実行し、最新リストを取得
バージョンを固定する場合には、特定のバージョンを指定すると、Playbook実行時に指定したバージョン以降の更新はされない。
例
apt:
name: docker-ce=5:24.0.5-1~ubuntu.22.04~jammy
state: present
バージョン管理
今後のバージョンアップの方針としては以下となる。
- 手動アップグレード: sudo apt update && sudo apt upgrade
- Ansible で管理: state: latest にすると毎回最新バージョンにアップデート可能
ただし、state: latest は予期しないバージョン変更が発生するため、慎重に運用すること!
state: latest と state: present + update_cache: yes の違い
state: latest の動作
- name: Install the latest version of a package
apt:
name: docker.io
state: latest
何が起きるのか?
- docker.io パッケージを 最新バージョン にアップグレードする
- すでに最新バージョンなら何もしない
- バージョンの更新 (apt update) を自動で実行する
🔹 ポイント
- 明示的に update_cache: yes を書かなくてもOK
- 既にインストールされている場合でも、より新しいバージョンがあればアップグレード される
state: present + update_cache: yes の動作
何が起きるのか?
- apt updateを実行し、パッケージリストを最新化する
- docker.io が インストールされていなければインストールする
- しかし、すでにインストール済みなら何もしない(アップグレードはしない)
🔹 ポイント
- アップグレードはしない(古いバージョンがあってもそのまま)
- update_cache: yesを指定しないと、リポジトリ情報が古い可能性がある
state: latest vs state: present + update_cache: yes
方法 | apt update | apt upgrade の実行 | 具体的な挙動 |
---|---|---|---|
state: latest | ✅ 自動 | ✅ 新バージョンがあればアップグレード | 既存パッケージも最新化 |
state: present + update_cache: yes | ✅ 明示的に実行 | ❌ アップグレードなし | 古いバージョンのまま |
Ansibleは昔使っていたことはありましたが、だいぶ忘れていたので、いい勉強になりました。