はじめに
こんにちは!そしてこんばんは!
クラウドインテグレーション事業部の 大嵩 です!
最近、構築作業時にミドルウェアをインストールするのが大変で、ミスを誘発してしまうのではないかと思い始めました。。。
それをどうにか改善するために!
今回は、これまで触っていなかったAnsibleを使って、Amazon EC2にLAMP環境を構築してみましたので、その記録を紹介します!
Ansible とは
Ansibleとは、Red Hat社が開発・管理しているオープンソースの構成管理ツールです。
インストールや設定をコード化し、環境を自動で構築・管理することができます!
個人的に、最強なのでは!?と思いました。
詳しい主な特徴は以下の通りです!
エージェントレス
対象のサーバーに専用ソフトウェア(エージェント)をインストールする必要がありません!
SSH 接続さえできれば、すぐに使い始められます。
YAML で記述
「Playbook」と呼ばれる設定ファイルを YAML 形式で記述します。
非常に分かりやすく、プログラミング経験が少なくても直感的に理解できます!
冪等性 (べきとうせい) の保証
何度実行しても、システムが同じ状態になることを保証します。
例えば「Apache がインストールされている状態」という Playbook を実行すると、未インストールならインストールし、インストール済みなら何もしません。
これにより、余計な変更を防ぎ、安心して繰り返し実行できます。
LAMPとは
タイトルにあるLAMPとはなんぞや?と思った方のために、説明します。
いわゆる略語で、以下を略した言葉になります!
L: Linux
A: Apache
M: MySQL(MariaDB) ※
P: PHP
上記からLAMP といいます!
そのため、今回はAL2023に、ApacheとMariaDBとPHPを導入し、ブラウザで表示ができるか確認します!
※AL2023でもMySQLをインストール可能ですが、今回はすぐにインストールが可能なMariaDBで検証します!
実行環境
今回は、ローカル端末のMacbook Air(M2) からAnsibleを実行します!
これにより、OS違いでもちゃんと自動実行できることを検証したいと思います。
そのため、非推奨ですが、EC2インスタンス(Amazon Linux 2023)をパブリックサブネットに設置し、グローバルIPアドレスを付与します!
まずは、EC2インスタンスを作成
少しだけ余裕を持たせて、t3.medium で作成しておきます!
もちろん、SSHやHTTPのアクセスはセキュリティグループのインバウンドルールに、IP制限をかけています。
(SSHに 0.0.0.0/0 は ダメゼッタイ)
ローカル環境に、Ansible用の環境を用意する
今回の構成は以下のような形になります。
ansible-lamp/ ├── inventory # 接続対象サーバーの情報を記述 └── playbook.yml # 実行する処理を記述
Ansibleをインストール
Macにも環境を用意していきます!
まずは、Ansibleが無いので、下記コマンドでインストールします。
brew install ansible
ディレクトリを作成
インストールできたら、ディレクトリを作成します!
また、ファイルも空で作成します。
❯ pwd /Users/otake ❯ mkdir ansible-lamp ❯ cd ansible-lamp/ ❯ touch inventory playbook.yml ❯ pwd /Users/otake/ansible-lamp ❯ ls -l total 0 -rw-r--r--@ 1 otake IRET\Domain Users 0 8 24 14:20 inventory -rw-r--r--@ 1 otake IRET\Domain Users 0 8 24 14:20 playbook.yml
必要なファイルの中身を記述する
Ansibleの実行には以下が必要になります!
- 対象サーバー情報(inventory)
- タスク情報(playbook.yml)
そのため、空で準備した inventory と playbook.yml の中身をそれぞれ記述していきます。
inventory
[lamp_server] <インスタンスのグローバルIPアドレス> ansible_user=ec2-user ansible_ssh_private_key_file=<鍵ファイルのパス>
playbook.yml
--- - name: LAMP environment setup on AL2023 hosts: lamp_server become: yes tasks: - name: Install Apache, MariaDB, and PHP packages dnf: name: - httpd - mariadb105 - mariadb105-server - php - php-mysqlnd state: present - name: Start and enable httpd service systemd: name: httpd state: started enabled: yes - name: Start and enable mariadb service systemd: name: mariadb state: started enabled: yes - name: Deploy phpinfo.php for testing copy: content: "<?php phpinfo(); ?>" dest: /var/www/html/info.php owner: apache group: apache mode: '0644'
Playbookの詳細
- name: Playbook全体の名前を定義しています
- 今回は「LAMP environment setup on AL2023」
- hosts: どの処理をどのサーバーで実行するかを指定します。
- inventoryに書いた、「lamp_server」を指定します。
- become: sudoのような、管理者権限でタスクを実行するための設定です。
- 使用するユーザーはec2-userで、sudo dnf install する際に必要なので、 yesにします。
- tasks: ここからが実際に行う処理の定義です。
tasksの詳細
dnf: ここで dnf コマンドを使うことを定義します
name: インストールしたいパッケージ名のリストです
state: パッケージが「存在する」状態を定義します。未インストールならインストールする定義です。
実際に実行してみる
それでは、環境の用意ができたので、実際にplaybookを動かしてみます。
実行コマンドはこのようになります。
ansible-playbook -i inventory playbook.yml
-i の後ろで、接続対象(inventory)を指定しつつ、タスクを定義したyml(playbook)を指定します。
実行結果
❯ ansible-playbook -i inventory playbook.yml PLAY [LAMP environment setup on AL2023] ************************************************************************************************ TASK [Gathering Facts] ***************************************************************************************************************** [WARNING]: Platform linux on host XXXX is using the discovered Python interpreter at /usr/bin/python3.9, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.18/reference_appendices/interpreter_discovery.html for more information. ok: [XXXX] TASK [Install Apache, MariaDB, and PHP packages] *************************************************************************************** changed: [XXXX] TASK [Start and enable httpd service] ************************************************************************************************** changed: [XXXX] TASK [Start and enable mariadb service] ************************************************************************************************ changed: [XXXX] TASK [Deploy phpinfo.php for testing] ************************************************************************************************** changed: [XXXX] PLAY RECAP ***************************************************************************************************************************** XXXX : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
当時の私も、喜んでいます。
しっかり確認(OS内部)
じゃあほんとに入ったのか?OS内部も確認してみましょう!
[ec2-user@ip-10-0-1-245 ~]$ httpd -v Server version: Apache/2.4.64 (Amazon Linux) Server built: Jul 15 2025 00:00:00 [ec2-user@ip-10-0-1-245 ~]$ [ec2-user@ip-10-0-1-245 ~]$ php -v PHP 8.4.10 (cli) (built: Jul 2 2025 02:22:42) (NTS gcc x86_64) Copyright (c) The PHP Group Built by Amazon Linux Zend Engine v4.4.10, Copyright (c) Zend Technologies with Zend OPcache v8.4.10, Copyright (c), by Zend Technologies [ec2-user@ip-10-0-1-245 ~]$ [ec2-user@ip-10-0-1-245 ~]$ mysql --version mysql Ver 15.1 Distrib 10.5.29-MariaDB, for Linux (x86_64) using EditLine wrapper [ec2-user@ip-10-0-1-245 ~]$
ご覧の通り、しっかり入ってますね!
もっと早く使えるようになっていれば、構築作業が楽に進められたなと後悔しています。。。
ブラウザから確認
今回、パブリックIPをつけてるので、そのままベタ打ちでApacheにアクセスしてみます。
このような形で、ApacheとPHPがしっかり動いてることが確認できました!
info.phpは本来このような形で表示すべきものではないので、今回のような検証以外では推奨しません。
また、検証に当たり、アクセス元を制限しております。
こんなこともできちゃったり・・・?
ここまで、ミドルウェアのインストールを実行してみました!
ですが、実行しただけでは、初期設定のままですので、Apacheのお決まりの設定をしてみましょう。
下記のものになります。
# /etc/httpd/conf/httpd.conf Options Indexes FollowSymLinks ↓ Options FollowSymLinks
そう、ブラウザから階層移動できなくするようになるあれです。
また、「It works !」だけじゃさみしいので、AIさんにお願いして作成してもらった、おしゃれなウェルカムページも設定してみます!
じゃあどうやるの?ってところなのですが、playbookを下記のような形に変えてみます。
--- - name: LAMP environment setup on AL2023 hosts: lamp_server become: yes tasks: - name: Install Apache, MariaDB, and PHP packages dnf: name: - httpd - mariadb105-server - php - php-mysqlnd state: present - name: Start and enable httpd service systemd: name: httpd state: started enabled: yes - name: Start and enable mariadb service systemd: name: mariadb state: started enabled: yes # index.html の設置 - name: Deploy index.html to document root copy: src: index.html dest: /var/www/html/index.html owner: apache group: apache mode: '0644' # httpd.confの修正 - name: Remove "Indexes" from Directory Options in httpd.conf lineinfile: path: /etc/httpd/conf/httpd.conf regexp: '^( Options) Indexes (FollowSymLinks)$' # confファイルのインデントを考慮 line: '\1 \2' backrefs: yes notify: Restart httpd # 変更があった場合に handler "Restart httpd" を呼び出す # httpd.conf 修正のため、サービスを再起動させる handlers: - name: Restart httpd systemd: name: httpd state: restarted
この記述を追記するだけで、設定ファイル変更とファイル設置までできるとか、どれだけ便利なんでしょうか。。
おまけで、おしゃれな index.html も記載します!
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Welcome!</title> <style> @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;500&display=swap'); :root { --primary-color: #1a73e8; --background-color: #f0f2f5; --card-background: #ffffff; --text-color: #333; --subtle-text-color: #5f6368; --border-color: #dfe1e5; --shadow-color: rgba(0, 0, 0, 0.1); } body { font-family: 'Poppins', 'Hiragino Kaku Gothic ProN', 'Meiryo', sans-serif; background-color: var(--background-color); margin: 0; padding: 20px; display: flex; justify-content: center; align-items: center; min-height: 100vh; color: var(--text-color); } .container { background-color: var(--card-background); padding: 40px 50px; border-radius: 12px; box-shadow: 0 4px 12px var(--shadow-color); text-align: center; max-width: 600px; width: 100%; border-top: 5px solid var(--primary-color); animation: fadeIn 0.8s ease-out; } .icon { color: var(--primary-color); font-size: 50px; animation: popIn 0.5s 0.2s ease-out backwards; } h1 { margin: 20px 0 10px; font-weight: 500; font-size: 2em; } p { color: var(--subtle-text-color); line-height: 1.6; margin-bottom: 30px; } .stack { display: flex; justify-content: center; gap: 15px; list-style: none; padding: 0; margin: 0; } .stack-item { background-color: var(--background-color); padding: 8px 15px; border-radius: 20px; font-size: 0.9em; font-weight: 500; color: var(--primary-color); transition: transform 0.2s ease, box-shadow 0.2s ease; } .stack-item:hover { transform: translateY(-3px); box-shadow: 0 2px 5px var(--shadow-color); } footer { margin-top: 30px; font-size: 0.8em; color: #999; } @keyframes fadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } @keyframes popIn { from { opacity: 0; transform: scale(0.5); } to { opacity: 1; transform: scale(1); } } </style> </head> <body> <div class="container"> <div class="icon">✓</div> <h1>セットアップ完了!</h1> <p>Webサーバーは Ansible によって正常に構築されました。</p> <ul class="stack"> <li class="stack-item">Apache</li> <li class="stack-item">MariaDB</li> <li class="stack-item">PHP</li> </ul> <footer> Powered by Ansible </footer> </div> </body> </html>
再度実行してみる
それでは、新しいplaybookができたので、再度実行してみます
❯ ansible-playbook -i inventory playbook.yml PLAY [LAMP environment setup on AL2023] ************************************************************************************************ TASK [Gathering Facts] ***************************************************************************************************************** [WARNING]: Platform linux on host XXXX is using the discovered Python interpreter at /usr/bin/python3.9, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.18/reference_appendices/interpreter_discovery.html for more information. ok: [XXXX] TASK [Install Apache, MariaDB, and PHP packages] *************************************************************************************** ok: [XXXX] TASK [Start and enable httpd service] ************************************************************************************************** ok: [XXXX] TASK [Start and enable mariadb service] ************************************************************************************************ ok: [XXXX] TASK [Deploy index.html to document root] ********************************************************************************************** changed: [XXXX] TASK [Remove "Indexes" from Directory Options in httpd.conf] *************************************************************************** changed: [XXXX] RUNNING HANDLER [Restart httpd] ******************************************************************************************************** changed: [XXXX] PLAY RECAP ***************************************************************************************************************************** XXXX : ok=7 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ほんとにconf変更とファイル設置できたのか?
ほんとにできたんでしょうか・・・?確認してみましょう!
[ec2-user@ip-10-0-1-245 conf]$ sudo diff -u httpd.conf.old httpd.conf --- httpd.conf.old 2025-08-24 05:40:04.845070329 +0000 +++ httpd.conf 2025-08-24 05:51:08.816115856 +0000 @@ -146,7 +146,7 @@ # http://httpd.apache.org/docs/2.4/mod/core.html#options # for more information. # - Options Indexes FollowSymLinks + Options FollowSymLinks # # AllowOverride controls what directives may be placed in .htaccess files. [ec2-user@ip-10-0-1-245 conf]$
すごい。。ほんとうに変更できましたね!
感謝です。(?)
ブラウザからも確認
では、ブラウザからウェルカムページも確認してみます
ちゃんと設置されて表示されてますね!
AIさんって優秀ですね。。。なんでも作れちゃいます。
以上でAnsibleを使った、LAMP環境構築になります!
まとめ
今回は、Ansibleを使って、EC2にLAMP環境を自動構築する流れを紹介しました。
手作業によるミスの削減や作業効率の向上に繋がる、構成管理ツールの便利な活用法を学べる内容となっていると思います!
主な内容は以下になります
- Ansibleの基本を解説
- エージェントレスで動作し、YAMLで直感的に記述できる構成管理ツールの特徴とメリットを紹介しました
- LAMP環境の自動構築
- EC2インスタンスに対し、Apache、MariaDB、PHPといったミドルウェアをインストールするPlaybookの具体的な記述方法と実行手順を記載しました。
- 設定変更とコンテンツ配置の自動化
- インストールだけでなく、Apacheの設定ファイル(httpd.conf)の変更や、カスタムHTMLファイルのデプロイも自動で行う方法を実演しました。
この記事がどなたかの参考となり、運用改善・品質向上につながりますと幸いです!