AWS EC2 に Docker Compose で nginx + certbot (Let's Encript) + Redmine + MySQL 入れてみた（1/5 はじめに）

# はじめに

標題のものは先人の記事が色々とあるのですが、（進化の早い分野のため）現状と即してなかったり、微妙に自分の欲している環境と異なったりしていたので、その点などを踏まえて記事にしてみました。

## おことわり

* 記事が長いです。ごめんなさい。
* 初掲載なので、至らない点があるかもですが、ご容赦ください。 
* 当方、広く浅くのエンジニアなので、もし間違いありましたら、こっそり・やさしく教えてください（笑）
* 間違いや訂正は、こっそりやることがあります。
* 記事の内容はあくまで参考とし、各自で構築する際は自己責任にてお願いします。
 * 不具合や障害が発生しても、責任は持つことはできませんし、サポートもできません。
* 記事にはしてませんが、実運用ではこれ以外に色々考慮すべき点があります。
 * バックアップやセキュリティ対策、監視、ログなどなど。たとえ個人使用であっても、漏洩や破損時の対策をしないと、あとで悲しい（大変な）思いをすることになります。

## 経緯

もともと某社の VPS サービスに Redmine を構築・運用してたのですが、以下の問題や不具合が発生してきました。

* 経年劣化。
 * Redmine のバージョンが古い、
 * OS はバージョンのサポート切れ。
* たまに起動すると（一時的ではあるものの）かなり動作がモッサリする。（おそらく Passenger の影響）
* （途中で相乗りさせた Web アプリの影響などで）応答しなくなったりなど。

また Docker などを介さずに、Redmine をはじめとする Web アプリを複数ベタ載せしてることもあり、バージョンアップは至難と判断。
今後のメンテナンス性も踏まえて、一念発起した次第。

## Docker, Docker Compose を採用した理由

### Docker

ズバリ、メンテナンス性の向上です。
各ミドルウェアのバージョンアップなどにおいて、容易にするための手段として Docker を採用しています。

スケール調整だけであればクラウドの設定で何とかなるものの、ミドルウェアを個別 Docker イメージにしておけば、バージョンアップする際に楽になる可能性[^1]を目論んでます。

[^1]: イメージ差替だけで済むという、あくまで「可能性」の話。バージョンアップの内容によっては、それでは対応できない場合も、実際にはあるとは思う。でもそれでも Docker を介さずに直接インストールされているよりは、分離レベルにおいてメリットがあると思う。

### Docker Compose

Docker と同じ理由。可読性を保った状態で、イメージのパラメータ等を記述できるのは便利。

## 注意しなくてはならないこと

Docker は、セキュリティ面での注意は、絶対に必要です。
構築や設定については、必ず内容を理解したうえで、設定する必要があります。

また、公開されているいるイメージを使用する場合、イメージそのものにセキュリティ上の「穴」が含まれている可能性もあります[^2]。
ミドルウェアの開発元が公式配布しているものを利用し、アップデートも小まめに実行する必要があります。

クラウド環境を利用する場合は、セキュリティグループやフィルタリングなどの設定を厳重に行うべきです。

[^2]: Docker ビルド（環境構築）を最初に行う都合上、どうしても root 権限が必要となる場合が多い。そのためイメージによっては、root 権限のままアプリケーションを動作させているものがある。公式が配布しているものは、実行においては非ルートユーザを作成し、それで実行するように配慮されたイメージが多いので、それを確認したうえで採用するのが良いと思う。

## 方針

* EC2 インスタンス１つに全部乗せします[^3]。
 * リスクよりも費用を取りました。

[^3]: 費用面やレスポンスを踏まえながら MySQL を RDS などの AWS のクラウドサービスに移行するなど可能性も考えられます。ただし自分のこの環境にかぎっては、当分の間は個人運用に留まりそうなので、そこまでの必要はなさそう。

## 環境

* Amazon AWS EC2
 * t2.micro インスタンス[^4]（1 vCPU、6 CPU クレジット/時間、1 GiB、ネットワークパフォーマンス低～中） 
 * EBS 8GB
 * Amazon Linux 2 AMI (HVM), SSD Volume Type

いわゆる「無料枠に全部乗せ」からのスタートです。
ここに標題の環境をすべて乗せます。

[^4]: 無料枠が終了した時点で t2.nano（0.5 vCPU、3 CPU クレジット/時間、0.5 GiB、ネットワークパフォーマンス低）にスケールダウンする可能性あり。ただし Docker イメージの起動が上手くいかない（一度に起動できない、不安定になるなどの）可能性があるため、無料化枠終了後に検討。

## Docker イメージについて

### 導入するイメージ一覧

#### Certbot

SSL 証明書（Let's Encript）の取得・更新に使用します。

#### Nginx

上記 certbot にて SSL 証明書を取得するためと、Redmine に https 強制接続させる＆リバースプロキシとして使用します[^5]。

[^5]: Redmine イメージだけで稼働させることも可能だが、https 強制などの SSL まわりを施すために、Nginx を導入している

#### Redmine

今回の主目的。

#### MySQL

Redmine にて利用することができるデータベースは幾つかありますが、今回は MySQL を採用します。しかも 8.x 系の最新[^6]。

[^6]: データ移行前に使用しているデータベースと同じ系列のものに揃えた。

### バージョン選択

可能な限り、以下を採用します。

* ミドルウェア提供元が提示・推奨している、公式イメージ。
* 最新メジャーバージョン。latest は使わない（certbot を除く[^7]）。
* 通常版。alpine 版は不可[^8]。

[^7]: certbot は他のパッケージに比べて仕様（certbotの方針？）が変わる頻度が高く、変更時の影響が生じやすい可能性がある。しかしながら SSL 証明書取得・更新という、セキュリティ上において重要なパッケージのため、常に最新版を導入。

[^8]: alpine 版のほうがイメージのサイズが小さいなどのメリットが謳われているが、チューニングによるデメリット（依存パッケージ等不足など不具合）の可能性も考えられる。現状、ディスクの逼迫を考慮する必要があるほどではないので、そのためなるべく素に近い形のバージョンを採用する。

https://kaki-note-02.netlify.app/2020/06/13/

### データの永続化（バインドマウントか、ボリュームか）

適材適所でよいとは思いますが、できるだけ「名前付きボリューム」を使用します。

Docker の歴史的に「バインドマウント」を利用している記事が多く、またその方が便利かつ立ち上げも簡単なのでよく使われているようです。
「バインドマウント」のほうが設定ファイルの調整など利便性が高いのですが、コンテナ－ホスト間でのディレクトリ・ファイル共有はセキュリティ上のリスクも伴います。
そして今回の場合、コンテナ間で共有するディレクトリ・ファイルはありますが、ホスト－コンテナ間で共有するディレクトリ・ファイルがありません。

そのため設定ファイルなど、導入やチューニング時における利便性はやや劣りますが、「名前付きボリューム」に拘ってみました[^9]。

[^9]: Docker 初心者や開発関係など、利便性や理解しやすい「バインドマウント」を利用したほうがよい場合も多々あります。そう言った点から見ても、適材適所は、よく見極めたほうが良いかと。

## その他、構築前のメモとかルールとか

参考記事を調べて構築する際、いつも途中でゴチャゴチャになる点についての備忘。
（この記事の主旨とも少しズレた内容もありますが、気にしないでください。）

### サービス起動について（service か、systemctl か）

OSバージョンなどによって、混同しやすい箇所です。
service, chkconfig などのサービス系コマンドは、トレンドの変化に合わせて systemctl に統一します。

https://qiita.com/shotaTsuge/items/9f337bad9f73c3953af1

### certbot について

SSL証明書の取得・更新には、いずれも、certbot の Docker イメージを用いて行います[^8] 。

[^8]: Let's Encript（SSL証明書）の取得には certbot-auto が今では非推奨のため、certbot を利用する。そして certbot 本体も、以前は公式サイトからダウンロード（github から clone など）して利用する記事が沢山あったが、現在は certbot そのものの提供方法が刷新されてしまい、現状これら記事に倣った手順では certbot が入手できない。普通に certbot を導入したい場合、公式からは snap（snapd）というパッケージ管理システムを利用してインストールすることを推奨している。

### セキュリティについて

* パッケージやイメージのバージョンは、できるだけ最新に保つ。
* SSH 接続できる IP アドレスは、セキュリティグループ等の設定で必ず絞り込む。
* SSH 接続について、パスワード認証ではなく、鍵認証を必ず用いる。
* Redmine への接続は、ALBのリスナールールや Nginx の設定ファイルなどを用いて、接続可能な IP アドレスを制限する。

これ以外にも、セキュリティ上で必要・可能な設定やルールは沢山あります。
記事内には含めてませんが、セキュリティグループや Nginx の設定については、極めてシビア（厳しめ）に設定することを心がけましょう。


長くなりましたので、[次の記事](https://qiita.com/ax_kazz/items/816fe535aa3cf402d004 "2/5 Docker, Docker Compose")に続きます。

__↓ 2/5 Docker, Docker Compose など基盤構築__

https://qiita.com/ax_kazz/items/816fe535aa3cf402d004

__↓ 3/5 Nginx, Certbot 導入と SSL 証明書の取得・更新__

https://qiita.com/ax_kazz/items/f837e237e968db3d3ab3

__↓ 4/5 MySQL, Redmine の構築__

https://qiita.com/ax_kazz/items/1285534b46aeb307d7e0

__↓ 5/5 引用・謝辞__

https://qiita.com/ax_kazz/items/be1e491910b9546bc8c1