【まとめ】踏み台サーバーを経由したSSH接続後にgit clone & docker composeで外部からのアクセスできるWebサイトを構築する手順

# 概要
* 以下のことを実施したので、備忘も兼ねて残します。
    * ローカル環境から踏み台サーバーへのSSH接続
    * 踏み台サーバーからEC2インスタンス「sample」へのSSH接続
    * 踏み台サーバーを経由したSSH接続後の`git clone`実行、dockerとdocker composeインストール・起動
    * 外部からアクセスできるURLの確認

## 環境
* Mac
    * 機種ID：MacBookPro18,3
    * macOS：Monterey
    * チップ：Apple M1 Pro
    * メモリ：16GB

## 作成するAWSシステム構成図
![Sample_システム構成図_20230204.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/add1a514-e051-752d-6625-7e735ae59ec6.png)

* AWSリソース作成における記事はこちら：
    * [【AWS】EC2+dockerで外部からアクセスできるWebサイトを構築する手順](https://qiita.com/Ryo-0131/items/55ed0bb578832ed44d58)

## 前提
* AWSでELBのリスナーやインバウンドルールは設定済みとします（詳細は上記システム構成図or上記記事）。
* 踏み台サーバー（パブリックサブネット）は既に他アプリで利用していたものを使います。
* わかりやすいようにするため、本記事では
    * 踏み台サーバーのEC2インスタンスは「踏み台サーバー」と呼んで進めます。（SSHクライアント・SSHサーバーという言葉はあえて使いません）
    * dockerで動かす予定のEC2インスタンス（プライベートサブネット）は、本記事では「sample」という名前とします。以下で記載する「接続先のEC2インスタンス」や「sample」は同様のものと考えてください。本記事はこのEC2インスタンスを作成するところからスタートします。
    * 踏み台サーバーのキーペアは「fumidai.pem」とします。ローカル環境にダウンロード済み。
    * 踏み台サーバーのパブリック IPv4 アドレスは「11.222.3.444」と置き換えています。
    * 接続先のEC2インスタンス「sample」のキーペアは「sample.pem」とします。
    * 接続先のEC2インスタンス「sample」のプライベート IPv4 アドレスは「555.666.77.888」と置き換えています。

# 実施手順
1. EC2インスタンス作成〜キーペア取得
2. ローカル環境から踏み台サーバーへのSSH接続手順
3. 踏み台サーバーからEC2インスタンス「sample」へのSSH接続手順
4. 踏み台サーバーを経由したSSH接続後の`git clone`実行手順
5. 踏み台サーバーを経由したSSH接続後の`git clone`後のdockerインストール・起動手順
6. 踏み台サーバーを経由したSSH接続後の`git clone`後のdocker composeインストール・起動手順
7. 外部からアクセスできるURLの確認


## EC2インスタンス作成〜キーペア取得
* EC2インスタンス「sample」を作成後、キーペアファイル「sample.pem」をダウンロードし、所定のディレクトリに格納します
    * 自分の場合は、ローカル環境のKeyPairというディレクトリにまとめていますが、ホームディレクトリなりsshディレクトリなりまとめておくと良いと思います。

* キーペアとは：プライベートキー(秘密鍵)とパブリックキー(公開鍵)を合わせた二つの鍵のこと。
    * Amazon EC2 インスタンスへの接続時の身分証明に使用する、セキュリティ認証情報のセット。
    * Amazon EC2はパブリックキー(公開鍵)を保存し、ユーザーはプライベートキー(秘密鍵)を保存します。

## ローカル環境から踏み台サーバーへのSSH接続手順
* cdでKeyPairディレクトリに移動し、以下のコマンドでローカル環境にある秘密鍵を利用してSSH接続を行います。
```
$ ssh -i {keypair.pemを指定} ec2-user@XX.XXX.XX.XXX
```
* XX.XXX.XX.XXXのところは、AWSのEC2インスタンス→踏み台サーバー→「パブリック IPv4 アドレス」から取得できます。

```terminal
$ ssh -i fumidai.pem ec2-user@11.222.3.444
```

* ここで早速、以下のエラーが表示されました。（初めての構築であればおそらく表示される）
```terminal
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'fumidai.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "fumidai.pem": bad permissions
ec2-user@11.222.3.444: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

* 「pemファイル(Private Key Files)がオープンすぎるぞ！」と怒られているので、秘密鍵のpermissionを変更します。

```terminal
chmod 600 fumidai.pem
```

* 再度SSH接続を実行すると、無事にログインが確認できました。

```terminal
Last login: （省略）

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
75 package(s) needed for security, out of 123 available
Run "sudo yum update" to apply all updates.
```

* これで、ローカル環境から踏み台サーバーへのアクセスができました。

## 踏み台サーバーからEC2インスタンス「sample」へのSSH接続手順
* 先ほどローカル環境から踏み台サーバーへのSSH接続の時に秘密鍵を利用したように、踏み台サーバーからEC2インスタンスへSSH接続する際にも秘密鍵が踏み台サーバーにある必要があります。どうやって踏み台サーバーに置いてあげるかというと、ローカル環境にダウンロードしてある秘密鍵をコピーしてあげます。
* ということで、事前にダウンロードしているEC2インスタンス「sample」のキーペア「sample.pem」があるディレクトリで、以下を実行します。

```terminal
$ scp -i fumidai.pem sample.pem ec2-user@ec2-11-222-3-444.ap-northeast-1.compute.amazonaws.com:
```

* scpコマンドはSecureなCopyという意味。ホストコンピュータからリモートコンピューへファイルをコピーする小窓のことです。つまり、ローカルにあるsample.pemを踏み台サーバーにコピーしてあげるコマンドです。
* @以降のIPアドレスは、以下のどちらかの方法で取得が可能です。
    * EC2インスタンス→「パブリック IPv4 DNS」
    * EC2インスタンス→「パブリック IPv4 アドレス」
* scpコマンドの構文は以下です。コピー先は今回は直下にしていますが、所定のディレクトリにしたい方は、指定してあげてください。
```
scp [オプション] コピー元 コピー先 
```

* より具体的に以下が詳細な構文です
    * 「-r」はディレクトリ全体をコピーするオプションです。以下では参考として付けていますが不要な方は外してください
    * 「-i 秘密鍵ファイル」は、公開鍵認証用の秘密鍵ファイルを指定するコマンドです
  
```
scp -r -i [鍵].pem [ローカルファイルパス] ec2-user@[アップロード先IPアドレス]:[アップロード先ディレクトリパス]
```

* ちなみに、細かいですが、以下だとエラーになるので注意です。

```terminal
scp -i fumidai.pem sample.pem ec2-user@ec2-11-222-3-444.ap-northeast-1.compute.amazonaws.com
## どこが違うんだ！？って感じかもしれませんが、最後に「：」が入っていません。こちらも長い名前のファイルが作られるだけです笑
```

* 上記scpコマンド実行後、以下のメッセージが表示されます。

```terminal
The authenticity of host 'ec2-11-222-3-444.ap-northeast-1.compute.amazonaws.com (11.222.3.444)' can't be established.
XXXXXXX key fingerprint is SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:7: 11.222.3.444
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ec2-11-222-3-444.ap-northeast-1.compute.amazonaws.com' (XXXXXXX) to the list of known hosts.
```

* yesと入力すると、無事にコピーされたことがわかります。

```terminal
sample.pem        100% 1674    28.1KB/s   00:00
```

* 踏み台サーバーに入ってから、lsでも存在が確認できます
```terminal
$ ls
sample.pem
```

* 踏み台サーバーにいる状態で、以下コマンドを実行するとEC2インスタンス「sample」へアクセスできます。

```terminal
$ ssh -i sample.pem ec2-user@555.666.77.888
The authenticity of host '555.666.77.888 (555.666.77.888)' can't be established.
XXXXX key fingerprint is SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXX key fingerprint is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '555.666.77.888' (XXXXX) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
7 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
```

* 無事に接続できていることがわかりますね。
* 参考記事：
    * [EC2踏み台サーバを経由してssh接続](https://kyrieee.com/ec2-ssh/1530/)
    * [AWS EC2 にて SSH 接続しようとしたら Permission denied (publickey,gssapi-keyex,gssapi-with-mic). エラーが出た時の対応](http://psychedelicnekopunch.com/archives/2738)
    * [AWS　踏み台サーバー経由のSSH接続](https://qiita.com/amakawa_/items/ab7d284566b5fd51d9ca)
    * [【初学者向け】はじめての公開鍵認証を用いたSSH接続](https://kojichu.photoruction.com/entry/adcale20221208)


## 踏み台サーバーを経由したSSH接続後の`git clone`実行手順
* まずはgitをインストールします

```terminal
$ sudo yum install -y git
```

* .sshディレクトリに移動後、以下のコマンドを実行して公開鍵と秘密鍵を作成します。
    * 適切な名前をつけます。今回は「sample-github」とします。パスワードはなしでも可能。

```terminal
$ ssh-keygen -t rsa
```

* 以下で公開鍵の中身を表示できるので、公開鍵をコピーします。
    * .pubが公開鍵の方です

```terminal
$ cat sample-github.pub
```

* 次にGithubにログインし、`git clone`したいリポジトリの設定画面から「SSH and GPG keys」に進んで、「New SSH key」をボタンをクリック。titleは任意のものでOKです。Keyに先ほどコピーしたキーを貼り付けます。

* 次に、configファイルを作ってあげます。

```terminal
$ vi config
```

* viで新規作成＆中身も以下のように記入してあげます。
    * 実際に記入すると、こんな感じです

```terminal
Host github-aaa
  HostName github.com
  Port 22
  User git
  IdentityFile ~/.ssh/sample-github
```

* いよいよgit clone!と思い実行してみますが、また先ほど同じ権限エラーが発生しましたので、permissionを以下コマンドで変更します。

```terminal
$ chmod 400 config
```

* 念の為、`ls -la`でconfigの権限を確認。rwだったのがrだけになった等の確認ができます。

```terminal
$ ls -la

(省略)
-r-------- 1 ec2-user ec2-user  103  1月 23 07:25 config
(省略)
```

* ということで、ついに`git clone`実施です。

```terminal
$ git clone git@github-aaa:XXXXXXXXXXX/xxxx.git
```

* ポイントは、先ほどのconfigファイルと対応していることです。
    * Userで定義したものが、@の前にきます
    * Hostで定義したものが、@の後にきます


* 無事に`git clone`ができました！
* 必要であれば、ブランチのチェックアウトやプルなどしてください。いずれもterminalで使っていたgitコマンドで可能なので便利ですよね。

* 参考記事
    * [AWSのEC2にgit cloneする方法（GitHub）](https://qiita.com/konshun_program/items/c41c62f465368f0b0152)

## 踏み台サーバーを経由したSSH接続後の`git clone`後のdockerインストール・起動手順
* 基本的に以下のサイトの手順で実施します。非常に丁寧でわかりやすいです。
    * 参考記事：[【AWS】EC2にDockerとDocker Composeをインストール](https://kacfg.com/aws-ec2-docker/)

* まずはEC2内のパッケージを最新にしておくコマンドを実行します。

```terminal
$ sudo yum update -y
```

* `amazon-linux-extras`(専用のリポジトリを操作するコマンド)で最新のDockerパッケージをインストールします。

```terminal
$ sudo amazon-linux-extras install -y docker
```

* 補足：インストール後の確認は以下で可能です。自分の場合は以下のように表示されました。
```terminal
$ amazon-linux-extras | grep docker
 20  docker=latest            enabled      \
```

* Dockerサービスを起動します。
```terminal
$ sudo systemctl start docker
```

* 以下コマンドを実行し、Dockerサービスが起動しているかを確認できます。`active`と出ていれば問題ありません。
```terminal
$ systemctl status docker
```

* Dockerサービスの自動起動を有効にします。（次回からいちいち立ち上げなくて良くなります）
```terminal
$ sudo systemctl enable docker
```

* 補足：Dockerサービスの自動起動が有効であることを確認可能。
```terminal
$ systemctl is-enabled docker
enabled
```

* dockerグループに`ec2-user`を追加します。
```terminal
$ sudo usermod -a -G docker ec2-user
```

* 補足：dockerグループの確認は以下コマンドで確認可能。
```terminal
$ grep docker /etc/group
docker:x:992:
```

## 踏み台サーバーを経由したSSH接続後の`git clone`後のdocker composeインストール・起動手順
* Docker Composeのバイナリファイルを格納するディレクトリを作成します。
```terminal
$ sudo mkdir -p /usr/local/lib/docker/cli-plugins
```

* GitHubにあるDocker Composeのバイナリファイルを上記ディレクトリにダウンロードします。
    * （2023.1.23時点ではv2.4.1が最新）
```terminal
$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
```

* docker-compose（バイナリファイル）に実行権限を付与します。
```terminal
$ sudo chomd +x /usr/local/lib/docker/cli-plugins/docker-compose
```

* docker compose versionを実行すると、、、
```terminal
Docker Compose version v2.4.1
```

* インストールされていることが確認できました。

* `docker-compose.yml`があるディレクトリに移動し、以下コマンドを実行します。
    * これにより、イメージの作成とコンテナ作成・起動の処理が行われます。
```terminal
$ docker compose up -d
```


## 外部からアクセスできるURLの確認
* AWSでの設定が完了していれば、あとは以下のリンクを叩けば表示されます。

```
<ELB DNS name><:Port>
```

* 例えば、以下のようなURLになります。
    * http://public-sample-123456789.ap-northeast-1.elb.amazonaws.com:8000
    * home.htmlなどで設定している場合は、8000/homeなどといったように続けます。

* 以下に、AWSでの設定における注意点やシステム構成図についてまとめていますので、こちらもぜひご参考ください。
    * [【AWS】EC2+dockerで外部からアクセスできるWebサイトを構築する手順](https://qiita.com/Ryo-0131/items/55ed0bb578832ed44d58)