はじめに
phpMyAdminをfargateで構築する流れをまとめます。
phpMyAdminで複数のRDSを管理したいため、RDSのエンドポイントを複数設定する方法も説明します。
下記のソースがそのまま使えますので、クローンしてください。
環境
- fargate
- PHP : 8.1.4
- phpMyAdmin : 5.1.3
- Nginx : 1.20
完成構築図
事前構築
- VPC,インターネットゲートウェイ,サブネット,RDSまで作成済み
ソースのディレクトリ構造
ソースをクローン後に、ディレクトリ構造を確認します。
phpmyadmin-ecs % tree -L 2
.
├── docker
│ ├── nginx
│ └── php
└── src
├── CONTRIBUTING.md
├── ChangeLog
├── LICENSE
├── README
├── RELEASE-DATE-5.1.3
├── babel.config.json
├── composer.json
├── composer.lock
├── config.sample.inc.php
├── doc
├── examples
├── favicon.ico
├── index.php
├── js
├── libraries
├── locale
├── package.json
├── print.css
├── robots.txt
├── setup
├── show_config_errors.php
├── sql
├── templates
├── themes
├── url.php
├── vendor
├── .env.example
└── yarn.lock
srcディレクトリは、phpmyadminの最新バージョンをwebからダウンロードし、ディレクトリ名をsrcに変えただけです。
(現時点2022年4月17日の最新バージョンは、5.1.3でした)
ダウンロード後、下記の2つのファイルを修正します。(Githubに乗せているソースは修正済みです)
- config.inc.php
- libraries/classes/Core.php
config.inc.php
config.sample.inc.php
をコピーし、config.inc.php
というファイル名に変更します
複数のRDSを制御するため、以下の通りに修正します。
修正前
$cfg['blowfish_secret'] = ''; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
/**
* Servers configuration
*/
$i = 0;
// First server
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
修正後
+ $cfg['blowfish_secret'] = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
/**
* Servers configuration
*/
$i = 0;
// First server
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
+ $cfg['Servers'][$i]['host'] = getenv("PMA_HOST_PROD");
+ $cfg['Servers'][$i]['verbose'] = getenv("PMA_INSTANCE_NAME_PROD");
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
// Second server
+ $i++;
+ $cfg['Servers'][$i]['auth_type'] = 'cookie';
+ $cfg['Servers'][$i]['host'] = getenv("PMA_HOST_DEV");
+ $cfg['Servers'][$i]['verbose'] = getenv("PMA_INSTANCE_NAME_DEV");
+ $cfg['Servers'][$i]['compress'] = false;
+ $cfg['Servers'][$i]['AllowNoPassword'] = false;
$cfg['blowfish_secret']
暗号化 (blowfish_secret) 用の非公開パスフレーズの設定が必要なため、$cfg['blowfish_secret']
で、32文字以上を記入しましょう。
指定したパスフレーズは内部で使用されるだけです。あとでこのフレーズを入力するような画面が出てくるわけではありません。
$cfg['Servers'][$i]['verbose']
verbose
は、rdsの名前を記載しましょう。
二つ以上のRDSのエンドポイントの設定をconfig.inc.php
に記載した場合、ログイン画面で、RDSを選択するプルダウンメニューが表示されるようになります。
例えば、$cfg['Servers'][$i]['verbose'] = 'dev'
の場合、
プルダウンの中身はdev
と表示され、管理する上でどのRDSか分かるように、名前を設定しましょう
getenv("PMA_HOST_")
getenv("PMA_HOST_PROD")
は、ECSのタスク定義で環境変数を設定しますので、その設定した値が渡されます。
PMA_HOST_PROD
とPMA_HOST_DEV
は、それぞれRDSのエンドポイントに置き換わります。
以下も同様です。
getenv("PMA_INSTANCE_NAME_PROD");
管理するRDSが3つの場合
今回は、RDS2つでしたが、3つに増やしたい場合、以下を通りに記載するとよいです。
(prod,dev,stage)
// Third server
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['host'] = getenv("PMA_HOST_STG");
$cfg['Servers'][$i]['verbose'] = getenv("PMA_INSTANCE_NAME_STG");
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
getenv("PMA_HOST_STG")
とgetenv("PMA_INSTANCE_NAME_STG")
以外は、同じですね。
libraries/classes/Core.php
Core.php
の640行辺りに、以下の通り3行を加えます。
この修正をしない場合、phpMyAdminでSQLやCSVをエクスポートすると、ブラウザ側で「失敗 ネットワークエラー」
となり、ダウンロードできないバグが発生します。
これは、PHP8系とphpMyAdmin5.1系が組み合わさった場合に、起きるバグのようです。
if (strpos($mimetype, 'gzip') !== false && $notChromeOrLessThan43) {
header('Content-Encoding: gzip');
}
+ else {
+ header_remove('Content-Encoding');
+ }
header('Content-Transfer-Encoding: binary');
if ($length <= 0) {
return;
}
処理内容を説明すると、phpMyAdminのデフォルト出力はgzipを使用しているため、CSVなどの非圧縮ファイルを出力する場合は、エンコーディングヘッダーを取り除きます。
PHP8系で起きるバグのため、
ALBを作成
ALBを以下の項目を適切に選択し、作成します。
他の項目は、全てデフォルトでよいです。
・名前:何でも
・VPC:作成したVPC
・サブネット:作成したパブリックサブネット
・セキュリティーグループ(インバウンド:0.0.0.0に対して、HTTPとHTTPSを許可
します)
・リスナー:HTTP:80
ターゲットグループ作成
Include as pending below
は、押さずに、ターゲットグループを作成
ロードパランサーの作成画面に戻り、他はデフォルトで作成。
ALBのリスナーの確認
ターゲットグループがfargateのみになっているか確認します
fargate用のセキュリティーグループを作成
elbのsgに対して、httpを許可します。
HTTP
:ソース
:albのセキュリティーグループを選択
RDSのセキュリティーグループを修正
fargateのsgに対して、MYSQL/Aurora
を許可するように修正します。
phpMyAdminで管理したい全てのRDSのsgに対して修正しましょう。
Route53を作成
Route53を作成します。
・ドメイン名:xxxx.com
・タイプ:パブリックホストゾーン
次に、独自ドメインのネームサーバー情報を変更します。
以下の4つのネームサーバー情報を貼り付けます。
ネームサーバー情報の変更方法:お名前ドットコム
ドメイン→ドメイン機能一覧→ネームサーバー設定画面
に移動し、その他
のタブから入力できます。
Route53レコードの設定
Route53を利用して独自ドメインとALBのDNS名を紐づけます。
ホストゾーンxxxx.com
のレコードを作成します
・レコード名:<空白>
・レコードタイプ:A
・エイリアス:選択します
・トラフィックのルーティング先:ALB,東京リージョン、先程作成したALBを選択
・ルーティングポリシー:シンプルルーティング
IAMユーザーの作成
ECRにDockerイメージをプッシュする際、cliを利用するため、事前にIAMユーザーを作成し、アクセスキーを発行しておきましょう。
IAMポリシーは、EC2InstanceProfileForImageBuilderECRContainerBuilds
をアタッチします。
aws configure --profile
コマンドを使用し、アクセスキーとシークレットキーを設定します。
$ aws configure --profile fargate-phpmyadmin
AWS Access Key ID [None]: ****************DMH2
AWS Secret Access Key [None]: ****************bHBU
Default region name [None]: ap-northeast-1
Default output format [None]:
// aws cli プロフィール変更
$ export AWS_DEFAULT_PROFILE=fargate-phpmyadmin
これでローカルでのcliのセットは完了です。
ECRを作成
AWSのECSのコンソール画面からECRのリポジトリをクリックします
nginx
とapp
リポジトリの2つを作成します。
・可視性設定:プライベート
・リポジトリ名:nginx
・その他はデフォルト設定のまま
・可視性設定:プライベート
・リポジトリ名:php
・その他はデフォルト設定のまま
プッシュコマンドの表示
をクリックすると以下の画面が出てきます。
この4つのコマンドの流れでECRにpushしていきます。
ソースをクローンした後、ソースのルートディレクトリに移動し、ecrのログインをします。
$ cd phpmyadmin-ecs
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
ログインできました。
ログインに失敗した場合、IAMユーザーのアクセスキーIDとシークレットアクセスキーが以下の情報と一致しているか確認してください。
一致していない場合、IAMユーザーから新たにアクセスキーを発行し、~/.aws/credentials
や~/.aws/config
ファイルを修正してください。
// profileの確認
$ cat ~/.aws/credentials
$ cat ~/.aws/config
// profileの確認
$ aws configure --profile fargate-phpmyadmin
AWS Access Key ID [None]: ****************DMH2
AWS Secret Access Key [None]: ****************bHBU
Default region name [None]: ap-northeast-1
Default output format [None]:
// aws cli プロフィール変更
$ export AWS_DEFAULT_PROFILE=fargate-phpmyadmin
ログイン後、nginxをビルドし、タグ付け後、ECRにpushします。
今回は、タグは、latest
にします。
phpmyadmin-ecs $ docker build -t nginx:latest -f ./docker/nginx/Dockerfile .
$ docker tag nginx:latest [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/nginx:latest
$ docker push [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/nginx:latest
問題なくpushできれば、ECRのリポジトリにイメージが作成されます。
同様にphp
でもビルドし、タグ付け後、ECRにpushします。
phpmyadmin-ecs $ docker build -t php:latest -f ./docker/php/Dockerfile .
$ docker tag php:latest [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/php:latest
$ docker push [アカウントエイリアス12桁].dkr.ecr.ap-northeast-1.amazonaws.com/php:latest
phpとnignxのイメージをpushできました。
エラー
以下のエラーが出た場合、dockerのアプリが起動していないため、起動させましょう。
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
クラスターを作成
ECSのコンソール画面からクラスターの作成をクリックします。
クラスター名を記入し、作成します。
container insights
は有効にします。
タスク定義を作成
ECSのコンソール画面のタスク定義タブから新しいタスク定義の作成をクリックします
・起動タイプ:Fargate
次へ
・タスク定義名:phpmyadmin
・タスクロール:なし
・ネットワークモード:awsvpc
・タスク実行ロール:ecsTaskExecutionRole
(デフォルト)
コンテナの追加php
- コンテナ名:
php
- イメージ:リポジトリの
イメージのURI
環境変数にPMA_HOST_PROD: RDSのエンドポイント
を設定すると、先程設定したconfig.inc.phpのgetenv("PMA_HOST_PROD")
に値が渡ります。
- 他はすべてデフォルトのままです
更新をクリックするとコンテナが作成されます。
コンテナの追加nginx
- コンテナ名:
nginx
- イメージ:リポジトリの
イメージのURI
- ECRのnginxをクリックすると、
イメージのURI
がありますのでコピペしましょう。
- ECRのnginxをクリックすると、
- ポート:
80
- 環境変数
- 他はすべてデフォルトのままです
更新をクリックするとコンテナが作成されます。
他はすべてデフォルトのままでタスク定義を作成します。
サービスを作成
-
サービスの設定
-
次のステップ
ターゲットグループを新規で作成する場合は、以下の設定になります。
elbからfargate(task)に対して、ポート80でアクセスし、task内のnginxのポート80に繋がります。
elbにacm(証明書)を入れている場合、プロダクションリスナーポートは、HTTPS
を選択できるようになります。
次のステップ
・autoscalingなし
サービスが作成されました!
http://xxxx.com/
にアクセスすると、phpmyadminが表示されました!
プルタブで、複数RDSの中から選択できます。
ユーザー名とパスワードは、RDSで設定したマスターユーザー名とマスターパスワードになります。
表示されない場合、以下のエラーの可能性があります。
拡張機能が無効
ログインすると、下記のメッセージがでます。
phpMyAdmin 環境保管領域が完全に設定されていないため、いくつかの拡張機能が無効になっています。
理由についてはこちらをご覧ください。
代わりにデータベースの操作タブを使って設定することもできます。
src/sql/create_tables.sql
をアップロードファイルとして選択し、インポートを実行すると、メッセージがなくなります。
エラー集
ResourceInitializationError
ResourceInitializationError:
unable to pull secrets or registry auth: execution resource retrieval failed:
unable to retrieve ecr registry auth: service call has been retried 3 time(s):
RequestError: send request failed caused by: Post https://api.ecr....
privateサブネットで起動
fargateをprivateサブネットで起動した場合、以下のエラーが出ます。publicサブネットに変更しましょう。
セキュリティーグループ
sgを確認してください。
- elbのsgは、httpで全開放(0.0.0.0/0)
- fargateのsgは、elbからのhttpで許可
- ACLとセキュリティグループが、サブネットからのポート 443 へのアウトバウンドアクセスを許可
コンテナ起動に成功しない
エラーログが下記の場合、nginxの設定ミスによるもので、default.conf
ファイル、もしくは、ヘルスチェックパス
を修正します。
2022/04/04 16:49:54 [error] 32#32: *2 directory index of "/var/www/html/" is forbidden, client: xx.x.x.xx, server: , request: "GET / HTTP/1.1", host: "xx.x.x.xxx"
default.conf修正
index index.php;
がない場合、追加してください
server {
listen 80;
root /var/www/html/public;
error_log /var/log/nginx/error.log;
+ index index.php;
ターゲットグループのヘルスチェックパス修正
ヘルスチェックパスを/
から/index.php
に変更してください。
次のステップ
fargateを運用にする上で、ポイントを下記の記事でまとめています。