【AWS】EC2を起動してDockerアプリをdocker-composeで立ち上げてみた

#はじめに
ローカルで開発したDockerアプリケーションをEC2にホストしたいと思い、試してみました。

#前提条件
- [AWSアカウント](https://aws.amazon.com/jp/)を持っている
- [Docker Hub](https://hub.docker.com/)のアカウントを持っている
- [Github](https://github.com/)を持っていて、ソースをアップ済み


#手順
- AWSコンソールでEC2起動（無料枠のものを選択）
- EC2にログイン(ssh接続)して、Dockerインストール
- EC2でGithubからリポジトリをクローンする
- Docker Hubに保存したimageを使ってdocker-composeでコンテナ起動


#EC2の起動
##インスタンスを起動
AWSコンソールを開き、EC2ページに遷移後、インスタンス起動。
![スクリーンショット 2021-05-24 10.07.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/ae3bbf35-28f6-05f8-9720-aca836683279.png)

##インスタンスの選択
今回はテスト利用なので、`Amazon Linux 2`の無料利用枠の対象インスタンスを選択しました。
![スクリーンショット 2021-05-24 10.10.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/f2a8f4b8-106d-79d4-8874-e888ed6b0fb3.png)

##インスタンスタイプの選択
無料利用枠の対象の`t2.micro`を選択。
`1vCPU, 2.5GHz, 1GiBメモリ, EBSのみ`
![スクリーンショット 2021-05-24 10.10.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/7c08cd63-fd48-f0a6-bd13-867784349d34.png)

##セキュリティーグループの選択
セキュリティグループのインバウンドルールは、`SSH`だけでなく`HTTP/HTTPS`接続も可能にするために追加しました。
![スクリーンショット 2021-05-24 10.12.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/68712a38-aa87-7cd4-fad4-75931e12f77d.png)

#キーペア作成とダウンロード（既存指定）
SSH接続用に、任意の名前をつけてキーペアの作成、ダウンロードします。
`~/.ssh/`に保存するのが一般的。
※キーをダウンロードした時に、拡張子が`.cer`でしたが、それをローカルで`.pem`に変えたらSSH接続問題なくできました。
![スクリーンショット 2021-05-24 10.21.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/e5818538-f689-c1e7-2c19-7c791a78f1aa.png)



#EC2にログイン(ssh接続)して、Dockerインストール
##EC2ログイン〜Dockerインストールの確認

```bash
$ ssh -i ~/.ssh/ec2_rsa.pem \
  ec2-user@ec2-xx-xxx-xx-xxx.ap-northeast-1.compute.amazonaws.com # EC2ログイン
$ sudo yum update -y # とりあえずインストールされているパッケージ更新
$ sudo amazon-linux-extras install docker # Dockerインストール
$ sudo usermod -a -G docker ec2-user # sudoを使用せずにDockerコマンドを実行できるように、ec2-userをdocker グループに追加
$ exit # 設定反映のために一回ログアウト
$ ssh -i ~/.ssh/ec2_rsa.pem \
  ec2-user@ec2-xx-xxx-xx-xxx.ap-northeast-1.compute.amazonaws.com # EC2に再度ログイン
$ docker version
# インストールしたDocker versionが表示される
```
ポイントとしては、dockerをインストールしてec2-userに権限を付与した後、**一度EC2からログアウトして、再度SSH接続すると、dockerコマンドが普通に使えるようになる**ので、インストール後コマンドを実行しても使えない場合は試してください。

```bash
$ sudo service docker start # Docker起動コマンド
```


##`docker-compose`のインストールと確認
```bash
$ sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` \
 -o /usr/local/bin/docker-compose # 公式より:https://docs.docker.jp/compose/install.html#linux
$ sudo chmod +x /usr/local/bin/docker-compose # ec2-userにも実行権限を付与
$ docker-compose --version
docker-compose version 1.16.1, build sdfeb43
```
コマンドが使えない場合はEC2に再ログインしてみてください

これで、Docker自体を起動した後に、`docker-compose up`でドッカーコンテナの起動ができるようになりました。


#EC2でGithubと連携
EC2でGithubからリポジトリをssh接続してクローンできるようにします。

##EC2上で、Github SSH接続用キーペアの生成
```bash
$ cd ~/.ssh
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa):ec2_github_rsa #<=名前を任意指定
Enter passphrase (empty for no passphrase):[enter]
Enter same passphrase again:[enter]
$ chmod 600 ~/.ssh/ec2_github_rsa # 秘密鍵 600は 所有者は読取&書込OK, グループ, その他は禁止
$ chmod 644 ~/.ssh/ec2_github_rsa.pub # 公開鍵 644は 所有者は読取&書込OK, グループ, その他は読取OK
```
※`passphrase`を指定する場合は、任意のものを指定してください。指定しない場合は`enter`


##EC2上で、`~/.ssh/config`の作成or編集
下記を記述。

```
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/ec2_github_rsa
  User git
```

##EC2上で生成した`公開鍵`をGitHubのSSHキー設定に登録
[Key Settings - Github](https://github.com/settings/keys)に遷移して、[New SSH Key]から作成。
![スクリーンショット 2021-05-24 10.56.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/944e3d58-b6cf-4e87-bb03-e3855147836c.png)

`ec2_github_rsa.pub`の内容を全てコピーして貼り付ける。
※**秘密鍵**をコピペしないように注意。
![スクリーンショット 2021-05-24 10.59.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/83d8a10d-8014-60cc-86d5-1afc6d2715e6.png)


##EC2上で、`Github`とのSSH接続確認
接続成功しました！！

```bash
$ ssh -T git@github.com
Hi UserName! You've successfully authenticated, but GitHub does not provide shell access.
```

##EC2内で任意のディレクトリに移動後、リポジトリのクローン
```
$ cd ~/src
$ git clone git@github.com:username/repository_name.git
```


こちらも参考にご確認ください。

https://qiita.com/ichi_zamurai/items/b62fa5d38fb8a6d23c7b


#`docker-compose up`でコンテナ起動
Docker Hubに保存したimageを使ってdocker-composeでコンテナ起動します。
※事前に、ローカルでbuildした`Dockerfile`のイメージを自分の`Docker Hub`のリポジトリにPushしておいてください。
※`Docker for Desktop`を使うと`GUI`でイメージの管理や`push`等が可能

```bash
$ cd ~/src/repository_name # docker-compose.ymlのあるディレクトリに移動
$ docker-compose up -d # デーモン化してDockerアプリケーション起動
```

##使用する`docker-compose`ファイルの中身
最小限の記述です。自分用にカスタマイズしてください。
[Compose ファイル・リファレンス - Docker](https://docs.docker.jp/compose/compose-file.html)

```yaml:docker-compose.yml
version: "3.3" # 2021/05/21時点で自分の環境的に3.3じゃないとエラーが出た

services:
  web:
    image: dockerhub-rep-username/image-name:tag-name # 自分のDocker Hubのリポジトリのイメージを使用
    container_name: web
    ports:
      - 80:80
    networks:
      - ec2_docker

  api:
    image: dockerhub-rep-username/image-name:tag-name # 自分のDocker Hubのリポジトリのイメージを使用
    command: >
      # some run app command
    container_name: api
    ports:
      - 8080:8080
    networks:
      - ec2_docker

  db:
    image: mysql:5.7 # Docker Hub公式のmysqlのイメージを使用
    container_name: db
    ports:
      - 3306:3306
    networks:
      - ec2_docker
    
networks:
  services:
    external:
      name: ec2_docker
```

#サイトにアクセスしてみる
開発合宿用にアプリを作成していたもんで、お恥ずかしい、、、w


###無事、接続できましたね✨
![スクリーンショット 2021-05-24 12.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/91573456-ec8f-284b-f59f-82016e5ae81d.png)


インスタンスも起動中🔛
![スクリーンショット 2021-05-24 12.20.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/1fe40a8b-0e58-310a-ae72-68adf4829bfd.png)



#ハマったポイント
- `EC2`の`ec2-user`に権限を付与しようと思って、`sudo chown -R ec2-user`とやってしまったら、`root`ユーザーの権限も変更されてしまい、`sudo`実行ができなくなってしまった。
    - インスタンス作成時には`root`のパスワード設定がされていないもんだから、`root`でログインや`sudo`実行ができなくなってしまい、試行錯誤したが、結局インスタンスの破棄をする羽目になった。（ファイル転送した2.5時間が無駄に汗）
        - 権限をいじったり、ユーザーを追加削除する際は気を付けるべきと学んだ。
- `git clone`や`Docker Hub`のイメージを使わずに、macローカルと同じファイルを転送してやれば動くのではと思い、ファイル転送したら**2.5時間**くらいかかり、時間を果てしなく無駄にした。`git cloneだったら数秒だった`。
    - ファイル転送し終わった後も、ファイルの欠損だったり、環境が違うから動かない等で苦しめられた。
    - ファイル転送後に、 `EC2`の`Amazon Linux`上で、`Dockerfile`のイメージを`build`しようとしたら、`EC2`の容量やメモリ不足で、`build`ができず、詰んだ。
        - 無料枠用のスペックが小さいEC2のホストだったので、遭遇したツラみ
- 最初セキュリティーグループを作成した時に、`http/https`接続の許可を忘れた。
- インスタンスを廃棄したときに、`EBS`ボリュームのスナップショットを取っておけばよかった。
    - インスタンスのターミネーション時にEBSボリュームも一緒に削除される。
- `github`との接続確認の際に、`root`ユーザーで`ssh -T git@github.com`したら、キーペアの問題が発生した。
    - `ec2-user`で作成した鍵だったので、`ec2-user`の状態で、`ssh -T git@github.com`しないとダメだった。
- macローカルとEC２で接続用に作成したキーペアの拡張子が`.cer`で、`.pem`にするにはどうしたら、、、って悩んだが、ローカルでファイルの拡張子を`.pem`に変えたら普通に使えた。
- `docker`をインストールした後に、コマンド使ってみたら反映されてなくて、ログアウトしてから試したら問題なくコマンド使えるようになった。

など、また思いついたら追記します。

#まとめ
これまでさくらのレンタルサーバーなどで、wordpressを使ったサイトなどのホストはしたことがあり、イメージがつかめてたんですが、
`EC2`を使って、その中にアプリケーションをホストして、アプリを起動したままにしたらインターネット上からアクセスできるようになるというのが、初めての経験だったから、なかなか難しく、ただ、ものすごく勉強になったし、イメージの作成や、プロビジョニングとかその辺の知見も深掘りできました。

せっかく`docker`のアプリを起動させたので、今度は`ECS`を使って`Docker`アプリケーションを起動させていなと思います。
（今回は、ECSをキャッチアップする時間がなかったので）


以上、ありがとうございました！！