MENTAにてメンターの @adachin0817さんの協力の下、アプリケーションのインフラ環境を以下のように強化致しました。個人的にインフラ面はすべてherokuを利用し、1からEC2を利用して構築した経験はありませんでした。
またDockerでの開発環境は利用していましたが、現場レベルでの使い方や設定等理解はしておらず、その一区切りとして、これまで制作してきたインフラ周辺の技術に関して、技術選定理由やその技術を用いる際の注意点をレクチャーして頂いたので、その内容を簡潔に記載致します
DockerやNginxの設定の詳細に関しましては、以下のGithubリポジトリのdocker/dev
配下にて確認できますので、気になる方はご覧ください。
Docker
コードベースで環境構築を管理できる点が利点。
コードの詳細に関するレクチャー。
コンテナに入る際の、自身の立ち位置を設定する。
ENV APP_ROOT /var/www/app
WORKDIR $APP_ROOT
リポジトリ配下にsocketsファイルを置くとmacのファイルシステムがLinuxと違うことによる速度低下に伴い、root配下に置くようにしている。
RUN mkdir -p /root/tmp
OSによってライブラリ管理ツールが異なる。Debian/Ubuntuでは、"apt-get"、Redhat/CentOS/Amazon Linuxでは"yum"。
最後のrmで導入したパッケージのキャッシュを削除している。
Dockerコンテナを用いた開発のベストプラクティスは、どこまでコンテナを軽量にして不要な設定等入れないということ、が大切であると教えて頂きました。
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
yarn \
...
rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/*
docker compose
それぞれのコンテナの関係性を管理できる技術。
コードの詳細に関するレクチャー。
ports 自分のパソコンのポート:コンテナのポート
ポート番号を介することで、コンテナとやり取りを行うことができるようになる。3306はMySQLのポート番号。それに対し、自身のポート番号の数字を3308にしている理由について。これは、他に並行して開発を行っている場合、ポート番号を重複させない為に(ポートが占有されている場合接続できない)、個人開発ではMySQLのポート番号と異なるポートを開放している。
db:
...
ports:
- '3308:3306'
volumes
自身のディレクトをマウントすることで、変更を共有する。下記の場合では、開発環境の/var/lib/mysql
以下を、ローカルの./mysql/db_data
にマウントしている。この/var/lib/mysql
というディレクトリは、MySQLのデータそのものであり、MySQLのデータをローカル環境にマウントする事で、データを永続化させている。
db:
...
volumes:
- ./mysql/db_data:/var/lib/mysql
Amazon ECS
Amazon Elastic Container Service (Amazon ECS) は完全マネージド型コンテナオーケストレーションサービスであり、コンテナ化されたアプリケーションを簡単にデプロイ、管理、スケールするのに役立ちます。
ECSはコンテナを用いて、環境を構成するAWSサービス(あんまり知らない)。
コンテナ化できることの利点は、その構築環境をコードで管理できる。
今回EC2で本番環境を構築しましたが、アプリケーション以外のコードはgitで管理しなかった。となると、変更を加えてもその変化を共有することができず、環境構築が属人化してしまう。その対応としては、EC2でもAnsibleなどを利用すれば属人化は防げる。
コンテナで環境構築→コードで管理→状態を共有できる、という利点に繋がる。
Amazon EC2
Amazon Elastic Compute Cloud (Amazon EC2) は、安全でサイズ変更可能なコンピューティング性能をクラウド内で提供するウェブサービスです。
今回の本番環境の構成はコストを抑えて、ALBやRDSなどは利用しない構成になっています。EC2を用いて環境構築をして分かったことは、Linuxに関する知識が大変乏しい、ということ。またEC2を採用したのは、Linuxの知識を学ぶ意味を込めて選定して頂いた。(確かに、めちゃくちゃ大変だった。)コンテナで環境構築をする前に、まずはLinuxの知識を補おうね、という話。
Nginx
Nginxをチューニングする為のおおもとのファイル。
以下はnginx.conf
のコードのレクチャー。
gzip on
ファイルの圧縮・解凍を許可する。通信における負荷を低減させる目的で、バックエンドの技術者としては必ず導入しておきたい設定。
gzip on;
log_format
ユーザーのアクセスをログベースで管理できる。設定できる変数は様々であるが、
ログベースでアクセスを管理できるのはrails_serverやUnicornではできない機能である為、Nginxが必須ということ。
log_format main '[nginx]\t'
'time:$time_iso8601\t'
'server_addr:$server_addr\t'
'host:$remote_addr\t'
...
access_log /var/log/nginx/access.log main;
include
nginxではバーチャルホストという概念が存在し、一つのサーバーで複数のドメインをnginxで管理することができる。そのために、それぞれのサーバーの管理ファイルを/etc/nginx/conf.d
で配置し、それらにnginxの設定を全てに適用し、かつ個別の設定はそれぞれのファイルで行う構成になっている。
include /etc/nginx/conf.d/*.conf;
supervisor
ドッカーにおけるプロセス管理ツール。ec2ではsystemctl
コマンドを用いており、dockerではsupervisorctl
を叩いて管理する。それぞれのツールに合わせた管理ツールを選定することが必要。
最後に
まだメンタの契約期間は続いていますが、控えめに言って最高でした。
レクチャーだけでなく、質問回答なども通して、全てがとても勉強になりました。
未経験の自分に対し、現場のエンジニアの方がこんなにも丁寧に説明して下さる機会は今後もないと思います。また、サーバサイドエンジニアになるためにはアプリケーションレベルからインフラも理解しないと実装等難しいことなどもフォローしていただき、感謝でしかありません。
今回のメンタの期間で得た知識の一つとしては、何をいってもコードを書くこと。そしてエラーが生じた際に、ログを読むこと。(2つじゃん)
その過程で技術力が身に付く、と。
意識はしていたつもりでしたが、甘かったです。
今後もどんどん自身の姿勢を改善し、コードを書いて技術力を身に付け、他者に貢献できるようになっていきたいです。
ちなみに、私がお世話になっているメンターさんはこの方です。気になった方は是非アプローチしてみて下さい。とても勉強になります。