前置き
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)はローカルでしか接続できないように設定する。
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
を利用する。
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
は割と書きすぎてる気がするのでこれいらんよ、とかあったら教えて欲しいです。未熟者の記事ですが読んでいただいてありがとうございます。