MENTAでのインフラに関するレクチャーまとめ

MENTAにてメンターの @adachin0817さんの協力の下、アプリケーションのインフラ環境を以下のように強化致しました。個人的にインフラ面はすべてherokuを利用し、1からEC2を利用して構築した経験はありませんでした。
またDockerでの開発環境は利用していましたが、現場レベルでの使い方や設定等理解はしておらず、その一区切りとして、これまで制作してきたインフラ周辺の技術に関して、技術選定理由やその技術を用いる際の注意点をレクチャーして頂いたので、その内容を簡潔に記載致します

DockerやNginxの設定の詳細に関しましては、以下のGithubリポジトリの`docker/dev`配下にて確認できますので、気になる方はご覧ください。

https://github.com/Ub-Iwerks/Atlier/tree/master/docker/dev

![全体構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/779676/d9846daf-f502-1334-9e5d-70231197f1aa.png)


### Docker

コードベースで環境構築を管理できる点が利点。
コードの詳細に関するレクチャー。

コンテナに入る際の、自身の立ち位置を設定する。

```yml
ENV APP_ROOT /var/www/app
WORKDIR $APP_ROOT
```

リポジトリ配下にsocketsファイルを置くとmacのファイルシステムがLinuxと違うことによる速度低下に伴い、root配下に置くようにしている。

```yml
RUN mkdir -p /root/tmp
```

OSによってライブラリ管理ツールが異なる。Debian/Ubuntuでは、"apt-get"、Redhat/CentOS/Amazon Linuxでは"yum"。
最後のrmで導入したパッケージのキャッシュを削除している。
Dockerコンテナを用いた開発のベストプラクティスは、**どこまでコンテナを軽量にして不要な設定等入れないということ**、が大切であると教えて頂きました。

```yml
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のポート番号と異なるポートを開放している。

```bash
  db:
    ...
    ports:
      - '3308:3306'
```

#### volumes

自身のディレクトをマウントすることで、変更を共有する。下記の場合では、開発環境の`/var/lib/mysql`以下を、ローカルの`./mysql/db_data`にマウントしている。この`/var/lib/mysql`というディレクトリは、MySQLのデータそのものであり、MySQLのデータをローカル環境にマウントする事で、**データを永続化**させている。

```bash
  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

ファイルの圧縮・解凍を許可する。通信における負荷を低減させる目的で、バックエンドの技術者としては必ず導入しておきたい設定。

```bash
gzip  on;
```

#### log_format

ユーザーの**アクセスをログベースで管理**できる。設定できる変数は様々であるが、
ログベースでアクセスを管理できるのはrails_serverやUnicornではできない機能である為、Nginxが必須ということ。

```bash
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の設定を全てに適用し、かつ個別の設定はそれぞれのファイルで行う構成になっている。

```bash
include /etc/nginx/conf.d/*.conf;
```

### supervisor

ドッカーにおける**プロセス管理ツール**。ec2では`systemctl`コマンドを用いており、dockerでは`supervisorctl`を叩いて管理する。それぞれのツールに合わせた管理ツールを選定することが必要。

### 最後に

まだメンタの契約期間は続いていますが、控えめに言って最高でした。
レクチャーだけでなく、質問回答なども通して、全てがとても勉強になりました。
未経験の自分に対し、現場のエンジニアの方がこんなにも丁寧に説明して下さる機会は今後もないと思います。また、サーバサイドエンジニアになるためにはアプリケーションレベルからインフラも理解しないと実装等難しいことなどもフォローしていただき、感謝でしかありません。

今回のメンタの期間で得た知識の一つとしては、**何をいってもコードを書くこと**。そしてエラーが生じた際に、**ログを読むこと**。（2つじゃん）
その過程で技術力が身に付く、と。
意識はしていたつもりでしたが、甘かったです。
今後もどんどん自身の姿勢を改善し、コードを書いて技術力を身に付け、他者に貢献できるようになっていきたいです。



ちなみに、私がお世話になっているメンターさんはこの方です。気になった方は是非アプローチしてみて下さい。とても勉強になります。

https://menta.work/user/1162