こんにちは。
KENと申します。
簡単な自己紹介
2020年4月から渋谷のとある企業でWebエンジニアをしてます、エンジニア一年生です。
エンジニアの研修でDockerを使用して開発環境を構築し、それをAWSの各種サービスを使用してコンテナデプロイをしました。
初めての経験で、コンテナデプロイ関連の記事も少なかったため、今回は自分の頭の整理を兼ねて記事を書くことにしました。
概要
今回の記事では、Laravelが動く環境をdockerで作成し、簡単なアプリを制作し、それをAWSのECR, ECS, RDS等のサービスを使用してデプロイするまでの流れについて書いていきます。
対象読者
Docker, AWSで何かアプリを制作、デプロイしてみたい人。
Dockerコンテナをデプロイしてみたい人。
環境
Docker version 19.03.8
docker-compose version 1.25.4
DockerでLaravelが動く環境を作る
基本的にこのフェーズはこの記事を参考にさせて頂きましたので、この記事を参考に進めてください。
【初心者向け】20分でLaravel開発環境を爆速構築するDockerハンズオン
一部ファイル構成、docker-compose.ymlの記述が上記サイトと異なる部分がありますので、その点について説明します。
今回の最終的なディレクトリ構成は以下です。
.
├── README.md
├── docker
│ ├── mysql
│ │ └── my.cnf
│ ├── nginx
| | |__ Dockerfile
│ │ └── default.conf
│ └── php
│ ├── Dockerfile
│ └── php.ini
├── docker-compose.yml
├── logs
│ ├── access.log
│ ├── error.log
│ ├── mysql-error.log
│ ├── mysql-query.log
│ ├── mysql-slow.log
│ └── php-error.log
└── src(アプリケーションのルートディレクトリ)
└── readme.md
docker-compose.yml
version: "3"
services:
app:
build:
context: .
dockerfile: ./docker/php/Dockerfile
args:
- TZ=${TZ}
ports:
- ${APP_PORT}:8000
volumes:
- ./src:/work
- ./logs:/var/log/php
- ./docker/php/php.ini:/usr/local/etc/php/php.ini
working_dir: /work
environment:
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_DATABASE=${DB_NAME:-homestead}
- DB_USERNAME=${DB_USER:-homestead}
- DB_PASSWORD=${DB_PASS:-secret}
- TZ=${TZ:-Asia/Tokyo}
web:
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
depends_on:
- app
ports:
- ${WEB_PORT:-80}:80
volumes:
- ./src:/work
- ./logs:/var/log/nginx
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
environment:
- TZ=${TZ:-Asia/Tokyo}
db:
image: mysql:8.0
volumes:
- db-store:/var/lib/mysql
- ./logs:/var/log/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
environment:
- MYSQL_DATABASE=${DB_NAME:-homestead}
- MYSQL_USER=${DB_USER:-homestead}
- MYSQL_PASSWORD=${DB_PASS:-secret}
- MYSQL_ROOT_PASSWORD=${DB_PASS:-secret}
- TZ=${TZ:-Asia/Tokyo}
ports:
- ${DB_PORT:-13306}:3306
volumes:
db-store:
docker/php/Dockerfile
FROM php:7.4-fpm-alpine
COPY ./src /work
COPY ./docker/php/php.ini /usr/local/etc/php/php.ini
LABEL maintainer="ucan-lab <info@u-can.tech>"
SHELL ["/bin/ash", "-oeux", "pipefail", "-c"]
# tinker(psysh)
ARG PSYSH_DIR=/usr/local/share/psysh
ARG PSYSH_PHP_MANUAL=$PSYSH_DIR/php_manual.sqlite
ARG PHP_MANUAL_URL=http://psysh.org/manual/ja/php_manual.sqlite
# timezone
ARG TZ=Asia/Tokyo
# composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
RUN apk update && \
apk add --update --no-cache --virtual=.build-dependencies \
autoconf=~2.69 \
gcc=~9.2 \
g++=~9.2 \
make=~4.2 \
tzdata=2020a-r0 \
git=~2.24 && \
apk add --update --no-cache \
icu-dev=~64.2 \
libzip-dev=~1.5 \
oniguruma-dev=~6.9 && \
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
echo ${TZ} > /etc/timezone && \
pecl install xdebug && \
git clone https://github.com/phpredis/phpredis.git /usr/src/php/ext/redis && \
apk del .build-dependencies && \
docker-php-ext-install intl pdo_mysql mbstring zip bcmath redis && \
docker-php-ext-enable xdebug && \
mkdir $PSYSH_DIR && curl $PHP_MANUAL_URL -o $PSYSH_PHP_MANUAL && \
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && \
composer config -g process-timeout 3600 && \
composer config -g repos.packagist composer https://packagist.jp && \
composer global require hirak/prestissimo
docker/nginx/Dockerfile
FROM nginx:1.17-alpine
COPY ./docker/nginx/default.conf /etc/nginx/conf.d/default.conf
COPY ./src /work
EXPOSE 80
docker/nginx/default.conf
server {
listen 80;
root /work/public;
index index.php;
charset utf-8;
error_log /var/log/nginx/error_test.log;
location / {
root /work/public;
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
ECRのリポジトリを作成
AWSのコンソール画面にログインして、次の画像の画面にアクセスしてください。
ここで2つのリポジトリを作ります。
nginxのイメージを保存するリポジトリとphp-fpmのイメージを保存するリポジトリの二つです。
ECRにDockerイメージをPushする
次にそれぞれのリポジトリにDockerイメージをPushしていきます。
下の画像のように、プッシュコマンドの表示というボタンがあるので、それを押して出てきたコマンドに従って進めてください。
AWS CLI
がインストールされていることが前提です。
ECSのタスク定義を作成
次にタスク定義を作成します。
タスク定義とは、アプリケーションを構成する 1 つ以上(最大 10 個)のコンテナを記述するJSON形式のテキストファイルです。
アプリケーションの設計図のようなものです。
下の画像のようにappコンテナとwebコンテナ
を作成してください。
まずはappコンテナの定義です。
コマンドの蘭に、コンテナ起動時に実行したいコマンド
を入力しておきます。
あとは環境変数も指定します。私は本番環境では.env.productionを使用しているので、APP_Env=production
と指定しています。
Webコンテナのネットワーク設定のリンクにはapp(appコンテナのこと)と記述しましょう。
docker/nginx/default.confでfastcgi_pass app:9000;
という記述があるので、ここと合わせるためappと記述します。
これでタスク定義を作成してください!
ECSのクラスターを作成
次にクラスターを作成します。
今回はEC2Linux + ネットワーキング
を選択して作成します。
EC2インスタンスタイプはt2.micro
、後はご自身のキーペアを選択してください。
これでクラスターを作成します。
タスクの起動
先ほど作成したタスク定義の画面に行ってください。
そこからアクションをクリックして、タスクの実行
をクリックします。
次の画面でタスク定義とクラスターをそれぞれご自身が先ほど作成したものを選択し、実行をクリックします。
(すみません、この画像ではタスク定義とクラスター名がsample-appになっていません。この記事の流れではこの二つは本来sample-appという名前になります。)
続いてクラスターの画面に行き、先ほど実行したタスクのステータスがRUNNING
になっていることを確認してください。
これでEC2インスタンスのパブリックIPアドレス
にアクセスすれば/srcディレクトリ以下に作成したアプリのトップページが表示されるはずです。
RDSの作成
データベースを使用するアプリの場合はRDS
を作成しましょう。
RDSの画面を開いたらデータベースの作成をクリックします。
標準作成
で今回はMySQL
を使用します。(Dockerの開発環境もMySQlを使用しているので)
無料利用枠
で、マスターユーザー名
とマスターパスワード
を決めます。
追加設定でアプリに利用するデータベースも作成しておきましょう。
今回はsample_app
という名前でデータベースを作成しておきます。
これで作成をクリックしてください!
作成されたデータベースは、RDSダッシュボードの「データベース」で確認できます。
RDSの設定
EC2インスタンスからDBインスタンスにアクセスするために、
「セキュリティグループのルール」から使用中のセキュリティーグループをクリックし、インバウンドの編集でアドレス入力の箇所にEC2のプライベートIPアドレス/32
を入力してください。
RDSで構築したMySQLは、日本語の保存ができないそうです。
日本語で保存できるように設定を変更します。パラメータグループの設定を、日本語データを保存できるように変更する必要があるみたいです!
詳しくはググってみてください。ここでは割愛します。
PHPのコンテナ内でマイグレーション
では最後です。
/srcディレクトリの下に、env.production
を作成します。
ECSのタスク定義で、appコンテナ、webコンテナ両方にAPP_ENV=productionという記述をしたので、本番環境ではこの.env.productionが参照されます。
記述は.envの内容とほとんど同じで大丈夫ですが、一部変更します。
下記を参考に記述してください。
DB_CONNECTION=mysql
DB_HOST=RDSのエンドポイントを記述
DB_PORT=3306
DB_DATABASE=sample_app(RDSの追加設定で作成したデータベース名)
DB_USERNAME=root
DB_PASSWORD=RDS作成の際に設定したマスターパスワード
ではsshでEC2インスタンスに接続してください。
ssh接続するには、EC2インスタンスのセキュリティーグループのインバウンドで22番ポート
のアクセスを受け入れる設定ができている必要があります。
下記手順で進めていってください。
sshが機能するには、キーが公開されていないことが必要なので、キーペアのアクセス権を変更する。
chmod 400 xxx.pem(ご自身のキーペア)
sshでEC2インスタンスのパブリックDNSに接続する
ssh -i "xxx.pem" ec2-user@ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com
EC2インスタンスに接続できたら、MySQLのソフトウェアをインストールする。
sudo yum -y install mysql
MySQLに接続する(rootは今回のマスターユーザー名、xxxの所にはエンドポイントを記述する)
mysql -u root -p -h XXX.xxx.ap-northeast-1.rds.amazonaws.com
MySQLへ接続できたことが確認できたら、:qで接続を終了します。
次にdocker ps
で今起動しているコンテナのIDを確認し、下記のコマンドでapp(phpが動いているコンテナ)の内部に入りましょう。
docker exec -i -t コンテナID
そして下記コマンドでマイグレーションを実行します。
php artisan migrate
無事マイグレーションが完了し、テーブルが作成されていることが確認できたら、EC2インスタンスのパブリックIPアドレスにアクセスしてみましょう。
トップページが表示されるだけでなく、新規登録機能など、DBが絡む機能も動くようになっているはずです。
以上が、LaravelアプリをECR, ECS, RDSを使用してデプロイする手順です。
最後までお付き合いくださりありがとうございました!!
補足
説明が至らない所、私の認識が間違っていて、おかしな説明がされている所があるかもしれません。
何かありましたらコメント等で教えて頂きますと幸いです。