LoginSignup
3
4

More than 1 year has passed since last update.

phpMyAdmin を ECS on Fargateで構築

Last updated at Posted at 2022-04-17

はじめに

phpMyAdminをfargateで構築する流れをまとめます。
phpMyAdminで複数のRDSを管理したいため、RDSのエンドポイントを複数設定する方法も説明します。

下記のように複数のRDSを1つのタスクで制御できます
スクリーンショット 2022-04-17 15.42.00.png

下記のソースがそのまま使えますので、クローンしてください。

環境

  • fargate
  • PHP : 8.1.4
  • phpMyAdmin : 5.1.3
  • Nginx : 1.20

完成構築図

スクリーンショット 2022-04-17 12.48.38.png

事前構築

スクリーンショット 2022-04-17 12.52.31.png

  • 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を制御するため、以下の通りに修正します。

修正前

.src/config.inc.php
$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;

修正後

.src/config.inc.php
+ $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か分かるように、名前を設定しましょう
スクリーンショット 2022-04-17 14.29.28.png

getenv("PMA_HOST_")

getenv("PMA_HOST_PROD")は、ECSのタスク定義で環境変数を設定しますので、その設定した値が渡されます。
PMA_HOST_PRODPMA_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系が組み合わさった場合に、起きるバグのようです。

スクリーンショット 2022-04-17 16.18.53.png

.src/libraries/classes/Core.php
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

ターゲットグループ作成

  • ターゲットタイプ:インスタンス
  • ターゲットグループ名:何でも
  • Choose a target type:IP addresses
  • HTTP:80
  • Health check path:HTTP/
    スクリーンショット 2022-04-17 14.50.57.png
    スクリーンショット 2022-04-02 10.40.16.png

Include as pending belowは、押さずに、ターゲットグループを作成

ロードパランサーの作成画面に戻り、他はデフォルトで作成。

ALBのリスナーの確認

ターゲットグループがfargateのみになっているか確認します
スクリーンショット 2022-04-17 14.51.56.png

fargate用のセキュリティーグループを作成

elbのsgに対して、httpを許可します。
HTTP:ソースalbのセキュリティーグループを選択
スクリーンショット 2022-04-10 10.44.10.png

RDSのセキュリティーグループを修正

fargateのsgに対して、MYSQL/Auroraを許可するように修正します。
phpMyAdminで管理したい全てのRDSのsgに対して修正しましょう。
スクリーンショット 2022-04-02 18.16.57.png

Route53を作成

Route53を作成します。
 ・ドメイン名:xxxx.com
 ・タイプ:パブリックホストゾーン

次に、独自ドメインのネームサーバー情報を変更します。
以下の4つのネームサーバー情報を貼り付けます。

ネームサーバー情報の変更方法:お名前ドットコム

ドメイン→ドメイン機能一覧→ネームサーバー設定画面に移動し、その他のタブから入力できます。

Route53レコードの設定

Route53を利用して独自ドメインとALBのDNS名を紐づけます。
ホストゾーンxxxx.comのレコードを作成します
 ・レコード名:<空白>
 ・レコードタイプ:A
 ・エイリアス:選択します
 ・トラフィックのルーティング先:ALB,東京リージョン、先程作成したALBを選択
 ・ルーティングポリシー:シンプルルーティング

スクリーンショット 2022-04-17 14.53.07.png

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のリポジトリをクリックします
nginxappリポジトリの2つを作成します。
 ・可視性設定:プライベート
 ・リポジトリ名:nginx
 ・その他はデフォルト設定のまま

 ・可視性設定:プライベート
 ・リポジトリ名:php
 ・その他はデフォルト設定のまま

プッシュコマンドの表示をクリックすると以下の画面が出てきます。
スクリーンショット 2022-04-02 11.41.07.png

この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のリポジトリにイメージが作成されます。
スクリーンショット 2022-04-03 9.22.41.png

同様に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

スクリーンショット 2022-04-03 9.23.03.png

phpとnignxのイメージをpushできました。

エラー

以下のエラーが出た場合、dockerのアプリが起動していないため、起動させましょう。

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

クラスターを作成

ECSのコンソール画面からクラスターの作成をクリックします。

ネットワーキングのみを選択し、次のステップ

クラスター名を記入し、作成します。

スクリーンショット 2022-04-17 15.08.11.png

container insightsは有効にします。

タスク定義を作成

ECSのコンソール画面のタスク定義タブから新しいタスク定義の作成をクリックします
 ・起動タイプ:Fargate
次へ
 ・タスク定義名:phpmyadmin
 ・タスクロール:なし
 ・ネットワークモード:awsvpc
 ・タスク実行ロール:ecsTaskExecutionRole(デフォルト)

スクリーンショット 2022-04-17 15.09.24.png

コンテナの追加php

  • コンテナ名:php
  • イメージ:リポジトリのイメージのURI
    • ECRのphpをクリックすると、イメージのURIがありますのでコピペしましょう。
    • スクリーンショット 2022-04-02 17.34.27.png
    • 環境変数
      • PMA_HOST_PROD: RDSのエンドポイント
      • PMA_HOST_DEV: RDSのエンドポイント
      • PMA_INSTANCE_NAME_PROD: RDSのインスタンス名(今回は、rds-prod
      • PMA_INSTANCE_NAME_DEV: RDSのインスタンス名(今回は、rds-dev
        スクリーンショット 2022-07-20 23.48.09.png

環境変数にPMA_HOST_PROD: RDSのエンドポイントを設定すると、先程設定したconfig.inc.phpのgetenv("PMA_HOST_PROD")に値が渡ります。

  • 他はすべてデフォルトのままです

更新をクリックするとコンテナが作成されます。

コンテナの追加nginx

  • コンテナ名:nginx
  • イメージ:リポジトリのイメージのURI
    • ECRのnginxをクリックすると、イメージのURIがありますのでコピペしましょう。
  • ポート:80
  • 環境変数
    • PMA_HOST_PROD: RDSのエンドポイント
    • PMA_HOST_DEV: RDSのエンドポイント
    • PMA_INSTANCE_NAME_PROD: RDSのインスタンス名(今回は、rds-prod
    • PMA_INSTANCE_NAME_DEV: RDSのインスタンス名(今回は、rds-dev
      スクリーンショット 2022-07-20 23.48.09.png
  • 他はすべてデフォルトのままです

更新をクリックするとコンテナが作成されます。

他はすべてデフォルトのままでタスク定義を作成します。

サービスを作成

クラスターからサービスを作成します。
スクリーンショット 2022-04-17 15.26.54.png

  • サービスの設定

    • 起動タイプ:FARGATE
    • タスク定義 ファミリー:phpmyadmin
    • タスク定義 リビジョン:1(latest)
    • プラットフォームのバージョン:1.4.0
    • クラスター:phpmyadmin
    • サービス名:phpmyadmin
    • タスク数の数:1
      スクリーンショット 2022-04-17 15.29.11.png
  • 次のステップ

    • クラスター VPC:適切なvpc
    • サブネット:パブリックサブネット
    • セキュリティーグループ:既存のセキュリティーグループを選択先程作成したsgを選択します
    • ロードバランシング
      • Application Load Balancer
      • ロードバランサー名:ロードバランサー選択
      • プロダクションリスナーポート:80:HTTP
      • ターゲットグループ名:先程作成したターゲットを選択
      • ターゲットグループのプロトコル:HTTP
      • パスパターン:/
      • 評価順:default
      • ヘルスチェックパス:/
        スクリーンショット 2022-04-17 16.12.19.png

ターゲットグループを新規で作成する場合は、以下の設定になります。

スクリーンショット 2022-04-17 15.27.15.png

elbからfargate(task)に対して、ポート80でアクセスし、task内のnginxのポート80に繋がります。

elbにacm(証明書)を入れている場合、プロダクションリスナーポートは、HTTPSを選択できるようになります。

次のステップ
 ・autoscalingなし

サービスが作成されました!

http://xxxx.com/にアクセスすると、phpmyadminが表示されました!

プルタブで、複数RDSの中から選択できます。
ユーザー名とパスワードは、RDSで設定したマスターユーザー名とマスターパスワードになります。

スクリーンショット 2022-04-17 15.42.00.png

表示されない場合、以下のエラーの可能性があります。

拡張機能が無効

ログインすると、下記のメッセージがでます。

phpMyAdmin 環境保管領域が完全に設定されていないため、いくつかの拡張機能が無効になっています。
理由についてはこちらをご覧ください。
代わりにデータベースの操作タブを使って設定することもできます。

スクリーンショット 2022-04-17 16.14.14.png

src/sql/create_tables.sqlをアップロードファイルとして選択し、インポートを実行すると、メッセージがなくなります。
スクリーンショット 2022-04-17 16.15.27.png

スクリーンショット 2022-04-17 16.15.50.png

エラー集

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....

スクリーンショット 2022-04-02 18.26.45.png

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;がない場合、追加してください

docker/nginx/default.conf
server {
  listen 80;
  root /var/www/html/public;
  error_log /var/log/nginx/error.log;
+  index index.php;

ターゲットグループのヘルスチェックパス修正

ヘルスチェックパスを/から/index.phpに変更してください。

次のステップ

fargateを運用にする上で、ポイントを下記の記事でまとめています。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4