AnsibleでDockerコンテナを管理する方法|community.dockerコレクションでコンテナのデプロイ・停止・削除を自動化する手順

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > AnsibleでDockerコンテナを管理する方法|community.dockerコレクションでコンテナのデプロイ・停止・削除を自動化する手順
「10台のサーバーに同じDockerコンテナを展開するのに、毎回SSHで入ってdocker runを手打ちしていませんか?」
Docker Composeで1台の管理はできても、複数サーバーへの一括展開となると途端に手が止まる——そんな状況は、Ansibleのcommunity.dockerコレクションを使えば解決できます。

この記事では、AnsibleからDockerコンテナを一括管理する方法を解説します。
community.dockerコレクションのインストールから、docker_containerモジュールによるコンテナのデプロイ・停止・削除、ネットワークとボリュームのPlaybook管理まで、RHEL 9.4 / Ubuntu 24.04 LTSで動作確認した実例を交えて紹介します。

この記事のポイント

・ docker_containerモジュールでコンテナのデプロイ・停止・削除を1つのPlaybookで管理できる
・ community.dockerコレクションはansible-galaxy collection installで導入する
・ loopを使えば複数コンテナをまとめて一括起動・停止できる
・ docker_networkとdocker_volumeでネットワークとVolumeもコード管理できる


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

なぜAnsibleでDockerコンテナを管理するのか

現場でよくある問題として、「docker runコマンドを手で打ったはずなのに先月と微妙に引数が違う」「新しいサーバーを追加したら、そのサーバーだけコンテナが古い設定で動いている」というものがあります。

Ansibleでコンテナ管理を行うことで、以下のメリットが得られます。

PlaybookがそのままドキュメントになるYAML記述:コンテナの設定を人間が読める形でコードに記録します
冪等性による安全な再実行:すでに起動中のコンテナには手を加えず、差分だけを更新します
複数サーバーへの同時展開:inventoryに書いたすべてのサーバーに対して、1回のansible-playbookで一括適用できます

Docker Composeはあくまで「1台のホスト上の複数コンテナ管理」が得意です。複数ホストにまたがる展開や、既存のAnsibleワークフローへの組み込みには、community.dockerコレクションが適しています。

準備:community.dockerコレクションのインストール

1. Ansibleのバージョンを確認する

community.dockerコレクションはAnsible 2.9以降が必要です。まずコントロールノード(自分のPC)でバージョンを確認します。

ansible --version

実行例:

ansible [core 2.16.4] config file = /etc/ansible/ansible.cfg configured module search path = ['/home/admin/.ansible/plugins/modules'] ansible python module location = /usr/lib/python3.11/site-packages/ansible ansible collection location = /home/admin/.ansible/collections executable location = /usr/bin/ansible python version = 3.11.6 (main, Nov 14 2023, 09:36:21)

2. community.dockerコレクションをインストールする

ansible-galaxyコマンドでコレクションをインストールします。

ansible-galaxy collection install community.docker

実行例(成功時):

Starting galaxy collection install process Process install dependency map Starting collection install process Downloading https://galaxy.ansible.com/download/community-docker-3.10.4.tar.gz Installing 'community.docker:3.10.4' to '/home/admin/.ansible/collections/...' community.docker:3.10.4 was installed successfully

また、管理対象サーバーにはPythonのdocker SDK(dockerライブラリ)が必要です。対象サーバーで次のコマンドを実行してインストール済みか確認します。

pip3 list | grep docker

docker 6.1.3

インストールされていない場合はpipでインストールします。

pip3 install docker

docker_containerモジュールの基本:コンテナをデプロイする

1. 最初のPlaybookを作る

docker_containerモジュールを使って、Nginxコンテナをデプロイする最小構成のPlaybookです。

# deploy_nginx.yml --- - name: Dockerコンテナ管理サンプル hosts: webservers become: yes tasks: - name: Nginxコンテナを起動する community.docker.docker_container: name: nginx_app image: nginx:1.26 state: started restart_policy: always ports: - "8080:80"

Playbookのポイント:

state: started — コンテナが起動していなければ起動する(すでに起動中なら何もしない)
restart_policy: always — ホストの再起動時にDockerデーモンが自動でコンテナを再起動する
ports: "8080:80" — ホストの8080番ポートをコンテナの80番にマッピングする

2. Playbookを実行してコンテナを起動する

インベントリファイルに対象サーバーを記述してPlaybookを実行します。

# inventory.ini [webservers] 192.168.1.101 192.168.1.102 ansible-playbook -i inventory.ini deploy_nginx.yml

初回実行(コンテナが存在しない場合)の出力例:

PLAY [Dockerコンテナ管理サンプル] ************************************* TASK [Gathering Facts] ************************************************ ok: [192.168.1.101] ok: [192.168.1.102] TASK [Nginxコンテナを起動する] *************************************** changed: [192.168.1.101] changed: [192.168.1.102] PLAY RECAP ************************************************************ 192.168.1.101 : ok=2 changed=1 unreachable=0 failed=0 192.168.1.102 : ok=2 changed=1 unreachable=0 failed=0

2回目の実行(コンテナがすでに起動中の場合):

TASK [Nginxコンテナを起動する] *************************************** ok: [192.168.1.101] ok: [192.168.1.102]

「changed」ではなく「ok」になっています。これがAnsibleの冪等性です。すでに正しい状態になっているホストには何もしません。

3. コンテナを停止・削除する

state: stoppedでコンテナを停止、state: absentで削除します。

# コンテナを停止する - name: Nginxコンテナを停止する community.docker.docker_container: name: nginx_app state: stopped # コンテナを削除する(停止もあわせて行う) - name: Nginxコンテナを削除する community.docker.docker_container: name: nginx_app state: absent

複数コンテナをloopで一括管理する

1. loopで複数コンテナを一括起動する

loopを使うことで、同じ設定の複数コンテナをまとめて管理できます。サービスごとにタスクを書き並べるよりもPlaybookがコンパクトになり、追加・削除もvarsリストの編集だけで済みます。

# multi_containers.yml --- - name: 複数コンテナを一括管理 hosts: appservers become: yes vars: app_containers: - { name: "api_v1", image: "myapp:1.0", port: "8001:8080" } - { name: "api_v2", image: "myapp:2.0", port: "8002:8080" } - { name: "worker_1", image: "myworker:latest", port: "8003:8080" } tasks: - name: アプリコンテナを一括起動 community.docker.docker_container: name: "{{ item.name }}" image: "{{ item.image }}" state: started restart_policy: always ports: - "{{ item.port }}" loop: "{{ app_containers }}"

2. 環境変数とポートマッピングの設定

本番環境では、コンテナに環境変数でDBパスワードやAPIキーを渡すことが多いです。envパラメータで設定します。

【注意】Playbookに平文でパスワードを書くことは絶対に避けてください。機密情報はAnsible Vaultで暗号化してvarsファイルに保存し、Playbookからはvault変数を参照する運用が鉄則です。

# group_vars/all/vault.yml(Vaultで暗号化) db_root_password: "(Vaultで管理)" db_user_password: "(Vaultで管理)" # db_deploy.yml - name: DBコンテナを起動する(環境変数設定あり) community.docker.docker_container: name: mysql_db image: mysql:8.0 state: started restart_policy: unless-stopped env: MYSQL_ROOT_PASSWORD: "{{ db_root_password }}" MYSQL_DATABASE: "myapp" MYSQL_USER: "appuser" MYSQL_PASSWORD: "{{ db_user_password }}" ports: - "3306:3306" volumes: - /data/mysql:/var/lib/mysql

DockerネットワークとVolumeをPlaybookで管理する

1. docker_networkモジュールでカスタムネットワークを作る

複数のコンテナを同じネットワーク上に配置したい場合、docker_networkモジュールで先にネットワークを作成します。同じネットワーク上のコンテナはコンテナ名でDNS解決できるため、サービス間通信がシンプルになります。

# network_setup.yml --- - name: Dockerネットワーク設定 hosts: appservers become: yes tasks: - name: アプリ用Dockerネットワークを作成する community.docker.docker_network: name: app_network driver: bridge state: present - name: フロントエンドコンテナをapp_networkに接続する community.docker.docker_container: name: nginx_frontend image: nginx:1.26 state: started networks: - name: app_network

実行後、管理対象サーバーで確認すると:

docker network ls NETWORK ID NAME DRIVER SCOPE a3f2b1c4d5e6 app_network bridge local b7c8d9e0f1a2 bridge bridge local c3d4e5f6a7b8 host host local

2. docker_volumeモジュールでデータVolumeを管理する

データの永続化には名前付きVolumeが便利です。docker_volumeモジュールでVolumeの作成・削除をコード管理します。

# volume_and_container.yml --- - name: VolumeとDBコンテナの管理 hosts: dbservers become: yes tasks: - name: DBデータ用Volumeを作成する community.docker.docker_volume: name: mysql_data state: present - name: MySQLコンテナをVolume付きで起動する community.docker.docker_container: name: mysql_db image: mysql:8.0 state: started volumes: - mysql_data:/var/lib/mysql

管理対象サーバーで作成後を確認すると:

docker volume ls DRIVER VOLUME NAME local mysql_data

実務Tips:冪等性を維持したコンテナ管理のコツ

Docker管理でよくある落とし穴が、imageを更新したのにコンテナが古いままになる問題です。

community.dockerコレクションのdocker_containerモジュールは、デフォルトでは「コンテナが起動しているかどうか」だけを見て冪等性を判断します。イメージのタグが同じであればコンテナを再作成しません。新しいイメージを確実に反映させたい場合は、image_name_mismatch: recreatepull: alwaysを組み合わせます。

- name: Nginxコンテナを常に最新イメージで起動する community.docker.docker_container: name: nginx_app image: nginx:1.26 state: started pull: always image_name_mismatch: recreate

また、コンテナのヘルスチェックもPlaybookに含めておくと、起動直後のサービス異常を早期に検知できます。

- name: Nginxコンテナにヘルスチェックを設定する community.docker.docker_container: name: nginx_app image: nginx:1.26 state: started healthcheck: test: ["CMD", "curl", "-f", "http://localhost/"] interval: 30s timeout: 10s retries: 3

トラブルシュート|よくあるエラーと対処法

【エラー1】「Failed to import the required Python library (docker)」

管理対象サーバーにPythonのdocker SDKがインストールされていない場合に発生します。Ansibleのpipモジュールで先にインストールするタスクをPlaybookの先頭に追加します。

- name: docker SDKをインストールする ansible.builtin.pip: name: docker state: present

【エラー2】「Got permission denied while trying to connect to the Docker daemon socket」

AnsibleがSSH接続するユーザーがdockerグループに属していない場合に発生します。Playbookのbecome: yesでrootとして実行するか、対象ユーザーをdockerグループに追加します(追加後は再ログインが必要です)。

# dockerグループへの追加(対象サーバーで実行) sudo usermod -aG docker ansible_user

【エラー3】コンテナのstateが毎回「changed」になり続ける

コンテナを構成するパラメータ(ポート・環境変数・ラベル等)がPlaybookの記述と実際のコンテナ設定で一致していない場合に発生します。docker inspectで実際の設定を確認し、Playbookとの差分を特定します。

# コンテナの実際の設定を確認する docker inspect nginx_app

本記事のまとめ

やりたいこと モジュール・パラメータ
コンテナを起動する community.docker.docker_container: state: started
コンテナを停止する community.docker.docker_container: state: stopped
コンテナを削除する community.docker.docker_container: state: absent
複数コンテナの一括管理 docker_container + loop: "{{ app_containers }}"
Dockerネットワークの作成 community.docker.docker_network: state: present
Volumeの作成 community.docker.docker_volume: state: present
イメージ更新時のコンテナ再作成 docker_container: image_name_mismatch: recreate
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

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

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

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

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

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

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

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

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

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。