前置き
terraformで構成しようとしたが、まずはAWSを理解するためコンソールから構築 本記事は私自身が少し悩んだ、ネットワークの構成やトラブルシューティングについて重点的に記載されております。ハンズオン形式の記事はQiita等にも多くございますのでそちらを参照しつつ、こちらの記事でより理解を深めていただければな、と思います。
使用技術 |
---|
Laravel6.x |
AWS ECS(Fargate), RDS, ElasticCache |
Docker, docker-compose |
ネットワーク構成
VPCは10.1.0.0/16を利用。 サブネットの利用感は下記みたいな感じ
サブネット | 用途 |
---|---|
10.1.0.0/24, 10.1.1.0/24 | Publicサブネット。LBに使うサブネット |
10.1.2.0/24, 10.1.3.0/24 | Privateサブネット。LBからECSに行くサブネット |
10.1.4.0/24, 10.1.5.0/24 | ECS~RDS間のサブネット。ECSからDBに接続するサブネット |
10.1.6.0/24 | EC2~RDS間のサブネット。EC2からDBに接続するサブネット |
migrationはDockerfileには置かないのでDB接続用のEC2インスタンスを用意する。 (userのデータとかも取得できるので)
ルートテーブルでInternetGatewayと接続するのはLBとDB接続用のEC2インスタンスのみ。 appサーバーとDBサーバー(RDS)はローカルでしか接続できないように設定する。
※ネットワークの軽い知識があれば上記のサブネットや、CIDRを理解できます。 30分とかで理解できると思うのでYouTubeとかでおさらいしておいてください。
Fargateタイプにおいてのコンテナ間通信について
webコンテナはNginx
(読み方はエンジンエックスっていうらしい、最近までエヌジンクスって読んでた)を利用していてappコンテナはPHP
でフレームワークはLaravel
。
そのためwebコンテナからappコンテナへの通信が必要。
ローカル内では下記のように.conf
ファイルを記述する。
ポートはwebはHTTP通信のため80
、appは9000
。
(docker-compose.ymlで名前をそれぞれweb
とapp
で指定しておく)
01:server { 02: listen 80; 03: root /work/public; 04: index index.php; 05: charset utf-8; 06: 07: location / { 08: root /work/public; 09: try_files $uri $uri/ /index.php$is_args$args; 10: } 11: 12: location ~ \.php$ { 13: fastcgi_split_path_info ^(.+\.php)(/.+)$; 14: fastcgi_pass app:9000; 15: fastcgi_index index.php; 16: include fastcgi_params; 17: fastcgi_param SCRIPT_FILENAME /work/public/index.php; 18: fastcgi_param PATH_INFO $fastcgi_path_info; 19: } 20:}
上記のような設定だとAWS ECSのFargate起動タイプだとヘルスチェックで
Taskが実行できません。
というエラーが出ます。そこで14行目
を下記のように変更します。
14: fastcgi_pass localhost:9000;
上記のようにする理由としては、Fargate起動タイプは同じローカルネットワーク内でtaskが実行されるためlocalhostは共有している。そのためコンテナ間通信はlocalhost:ポート番号
で指定する。
トラブルシューティング
ヘルスチェックが通らない。
ECSを起動する際に、ヘルスチェックが通らず、taskが実行できなかったとき。
Dockerfileへの知見が甘かったため、
待つポート番号やコピーするディレクトリを間違えていたりした。
Dockerfileの最後の行にEXPOSE <ポート番号>
を指定すること。
また、ローカルでコンテナを起動し期待するディレクトリにソースが入っているかを確認するといい。
ヘルスチェックは通るがLBのDNSに接続してもログインページが表示されない
ECS起動後にヘルスチェックが通るがログインページは表示されない場合。
ヘルスチェックは通っている ↓ ローカル内での通信はできている ↓ ネットワークの構成を確認し、落ちているところを確認
主に原因はネットワーク。 SGのインバウンドルールは適切か。ルートテーブルは適切か。再度確認する。 この過程が割と大事でCloudFomationとかで構成すると割と曖昧になりがちなネットワーク構成を理解できる。私の場合は、LBのターゲットグループを複数作成しており、利用したいターゲットグループの優先順位が一番ではなかったため、ログインページが表示されていなかった。
セッションの共有
可用性のために、複数のタスクを実行し、AutoScallingをオンにしていると思うので
セッションの共有をしておかなければいけない。
Laravel
のセッションはデフォルトでfile
を選択しておりProject/storage/sessions
に保存されている。実行されるタスクが複数でセッションの保存先がfile
の場合、それぞれのappコンテナの中に保存されてしまうので、セッションの共有をしなければいけない。
今回は、AWSのマネージドサービスであるElasticCache
を利用する。
※実装の工数上、現状(2020/09/06)では未構築のため後日追記する。 その際には上記のネットワーク構成にも修正を加える予定。
Dockerfileとdocker-compose.yml
いや、GitHub載せろよ。って思うよね。
僕的に、Qiita見ながらコピペできるのが理想なのでDockerfile
とdocker-compose.yml
はここに書きます。default.conf
は上記に記載済み。Fargate起動タイプの時はlocalhost
指定してください。
ディレクトリ構成も載せておきます。
| ├── docker | | │ ├── nginx | | ├── Dockerfile │ │ └── default.conf │ └── php │ ├── Dockerfile │ └── php.ini ├── docker-compose.yml | ├── .env | ├── .gitignore | └── live
version: "3" services: app: build: context: . dockerfile: ./docker/php/Dockerfile args: - TZ=${TZ} ports: - ${APP_PORT}:9000 volumes: - ./live:/work - ./logs:/var/log/php - ./docker/php/php.ini:/usr/local/etc/php/php.ini working_dir: /work environment: # ここは要設定 - DB_CONNECTION={DB_CONNECTION} - DB_HOST=${DB_HOST} - DB_DATABASE=${DB_DATABASE} - DB_USERNAME=${DB_USERNAME} - DB_PASSWORD=${DB_PASSWORD} - TZ=${TZ:-Asia/Tokyo} web: build: context: . dockerfile: ./docker/nginx/Dockerfile depends_on: - app ports: - ${WEB_PORT:-80}:80 volumes: - ./live:/work - ./logs:/var/log/nginx - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf environment: - TZ=${TZ:-Asia/Tokyo} volumes: db-store:
FROM nginx:1.19-alpine COPY ./docker/nginx/default.conf /etc/nginx/conf.d/default.conf EXPOSE 80
FROM php:7.4-fpm-alpine ARG PSYSH_DIR=/usr/local/share/psysh ARG PHP_MANUAL_URL=http://psysh.org/manual/ja/php_manual.sqlite ARG TZ ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer RUN set -eux && \ apk update && \ apk add --update --no-cache --virtual=.build-dependencies \ autoconf \ gcc \ g++ \ make \ tzdata && \ apk add --update --no-cache \ icu-dev \ oniguruma-dev \ libzip-dev && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo ${TZ} > /etc/timezone && \ pecl install xdebug && \ apk del .build-dependencies && \ docker-php-ext-install intl pdo_mysql mbstring zip bcmath && \ docker-php-ext-enable xdebug && \ mkdir $PSYSH_DIR && wget $PHP_MANUAL_URL -P $PSYSH_DIR && \ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && \ composer config -g repos.packagist composer https://packagist.jp && \ composer global require hirak/prestissimo RUN apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev && \ docker-php-ext-configure gd \ --with-jpeg=/usr/include/ \ --with-freetype=/usr/include/ && \ NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ docker-php-ext-install -j${NPROC} gd && \ apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev RUN chmod -R 777 /work/storage \ /work/bootstrap/cache RUN php artisan key:generate RUN php artisan config:clear RUN php artisan config:cache # RUN php artisan migrate # RUN php artisan db:seed EXPOSE 9000
php.iniは自分で検索してください。笑
.env
ファイルがないと起動できないので各々の用途に合わせて記述してください。
一応下記に書いておきます。
TZ=Asia/Tokyo APP_PORT=9000 DB_CONNECTION=mysql DB_HOST=<RDSのエンドポイント> DB_PORT=3306 DB_DATABASE=<DB名> DB_USERNAME=<username, rootでもいい> DB_PASSWORD=<セキュアなやつにしてね>
以上です。
まだ、CI/CDとかできていないので別記事にでも書こうと思っております。
AWS第一弾でした。
docker/php/Dockerfile
は割と書きすぎてる気がするのでこれいらんよ、とかあったら教えて欲しいです。未熟者の記事ですが読んでいただいてありがとうございます。