AWSでEC2+RDSでGo+Nginxのアプリケーション構築

## 前提条件
- MacOSを対象としている
- LinuxのVPCを対象
- EC2のインスタンスを作成済み、キーペア作成済み
- RDSのインスタンスを作成済み

### EC2にSSH接続
#### ダウンロードしたキーペアの移動・権限付与（済みの場合はスキップ）

```
$ mv ~/Downloads/プライベートキーの名前.pem ~/.ssh
$ chmod 400 ~/.ssh/プライベートキーの名前.pem
# プライベートキーの名前は作成時に決められている（例：aws_user.pem）
```

#### SSH接続
```
$ ssh -i aws_user.pem ec2-user@パブリックIPv4アドレス
# パブリックIPv4アドレスはEC2のインスタンス詳細画面にて確認できる（例：12.34.567.890）
〜省略〜
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '13.231.224.154' (ECDSA) to the list of known hosts.
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
https://aws.amazon.com/amazon-linux-2/
1 package(s) needed for security, out of 10 available
Run "sudo yum update" to apply all updates.
# EC2に接続成功
[ec2-user@<ipアドレス> ~]$
```

### EC2上の環境構築
使用されているVPCによっては、下記いづれにてパッケージのインストールができるようになります。

```
[ec2-user@<ipアドレス> ~]$ sudo amazon-linux-extras install パッケージ名
[ec2-user@<ipアドレス> ~]$ sudo yum install パッケージ名
[ec2-user@<ipアドレス> ~]$ sudo dnf install パッケージ名
```


### EC2からRDSに接続
（今回はPostgreSQLを例に、MySQLの場合は適宜に置き換えるように）
[RDSの設定](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html "RDSの設定")

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html

```
# postgresqlのインストール
[ec2-user@<ipアドレス> ~]$ sudo amazon-linux-extras install postgresql14
# DBへの接続
# DB インスタンスエンドポイント (DNS 名)はRDS詳細に確認できる（例：data-name.xxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com）
[ec2-user@<ipアドレス> ~]$ psql --host=DB インスタンスエンドポイント (DNS 名) --port=5432 --dbname=postgres --username=postgres
# パスワードを求められたら、入力する
# 接続成功
psql (14.3, server 14.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=> 
```

[PSQLのコマンド](https://qiita.com/H-A-L/items/fe8cb0e0ee0041ff3ceb "PSQLのコマンド")


#### GoとNginxのインストール
```
# Goのインストール（2024年3月時点、なぜか1.11しかインストールできない）
[ec2-user@<ipアドレス> ~]$ sudo amazon-linux-extras install golang1.11
# Goのパス設定
[ec2-user@<ipアドレス> ~]$ vi .bashrc
# 下記の記載を追加
# export GOPATH="$HOME/go"
# export PATH=$PATH:$GOPATH/bin
# Nginxのインストール
[ec2-user@<ipアドレス> ~]$ sudo amazon-linux-extras install nginx1
# 初期設定のバックアップ
[ec2-user@<ipアドレス> ~]$ sudo cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.back
# Nginx の起動とインスタンス起動時自動起動の設定
[ec2-user@<ipアドレス> ~]$ sudo systemctl start nginx
[ec2-user@<ipアドレス> ~]$ sudo systemctl enable nginx
[ec2-user@<ipアドレス> ~]$ systemctl status nginx
# nginx.confの設定修正
[ec2-user@<ipアドレス> ~]$ sudo vi /etc/nginx/nginx.conf
server {
    listen       80;
    listen       [::]:80;
    server_name  _;
    root         /usr/share/nginx/html;
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    # 新規追加
    # /app にきたらローカルホストの9000ポートにプロキシする
    location /app {
        proxy_pass http://127.0.0.1:9000;
    }
    # ここまで
    error_page 404 /404.html;
        location = /40x.html {
    }
    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
# 設定ファイルのチェック
[ec2-user@<ipアドレス> ~]$ sudo nginx -t
# Nginx の再起動
[ec2-user@<ipアドレス> ~]$ sudo systemctl restart nginx
```

### GoのファイルをEC2にアップロード
```
cd .ssh
scp -r -i aws_user.pem Goのフォルダパス ec2-user@パブリックIPv4アドレス://home/ec2-user/EC2上のGoアプリのディレクトリ
```

### Git連携
#### 公開鍵の作成
```
[ec2-user@<ipアドレス> ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
# 下のコードが表示されたらenterキーを押す
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
# 下のコードが表示されたらenterキーを押す
Enter passphrase (empty for no passphrase):
# 下のコードが表示されたらenterキーを押す
Enter same passphrase again:
Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Bi7Ds2BBqjT1/H9Wx3Ayv9i2Nyfor9NdvmUpucGtjbs ec2-user@ip-172-31-47-9.ap-northeast-1.compute.internal
The key's randomart image is:
+---[RSA 2048]----+
|  ..             |
| o. o            |
|.o.  o.      + . |
|o .o ...      B  |
|. o = ..S    . + |
| . . = ..   o * +|
|    .    . o O O+|
|          o o @oB|
|           .oE+==|
+----[SHA256]-----+
#　作成された公開キーを確認する
[ec2-user@<ipアドレス> ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAaBAQC1RYWQHGhrcXljlUGJn7Sn8VOS7HNHsVNOXc7abdLRoXsfy7Iofys5ogGzHuJxdHEG75CwlmENBcZsh5lU/Tx/5F283KPPGyK2eFqld9/LEu9Z/yTVckStgN8dnmlr6rcWnJUTyj4cjenDg1TIo57TL07vFN+a87y506a9LV0Rzr+FsAFqQ5jw9ZlO9QshT72N7Kgwv+cpCv6RMtsO6solEjbc4yijFsb+NT6Jyp0EHYXW8jK8fWKp1bUwmZYu8jSTbSr2X9snJ5eB/w78g8Ie+kl87WgLBxVjXiEdMI2PUFweskvaaXDt3fEwLhIZeUbpQh9YAU9j+wYCI7aiR4en ec2-user@ip-172-31-47-9.ap-northeast-1.compute.internal
```

#### Git側の設定

![git_key.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615519/19a6eda2-817b-ebd9-b50f-b79886b3518f.png)

#### 接続確認
```
[ec2-user@<ipアドレス> ~]$ ssh -T git@github.com
The authenticity of host 'github.com (52.69.186.44)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
RSA key fingerprint is MD5:16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
# 確認メッセージが表示されたらyesと入力
Are you sure you want to continue connecting (yes/no)?
Warning: Permanently added 'github.com,52.12.345.67' (RSA) to the list of known hosts.
Hi GitHubユーザー名! You've successfully authenticated, but GitHub does not provide shell access.
```
#### Gitからファイルを取得
```
# SSHの接続を選択するように
[ec2-user@<ipアドレス> ~]$ git clone git@github.com:アカウント名/レポジトリ名.git
```


### Goの実行
```
[ec2-user@<ipアドレス> ~]$ cd EC2上のGoアプリのディレクトリ
[ec2-user@<ipアドレス> ~]$ go run main.go
```

### Goのビルド
```
[ec2-user@<ipアドレス> ~]$ cd EC2上のGoアプリのディレクトリ
# 本番ビルド用のパラメータをつけております
[ec2-user@<ipアドレス> ~]$ go build -ldflags="-s -w" -trimpath
```

### Goの実行
```
[ec2-user@<ipアドレス> ~]$ ./Goビルド後のバイナリファイル名（パッケージ名と一致）
```

### バックグランドでの実行（SSH接続が終わっても、実行しっぱなし）
#### 以下app.serviceというファイルを作成
```
[Unit]
Description=Automatic start server demon

[Service]
ExecStart=/home/ec2-user/api/Goビルド後のバイナリファイル名（パッケージ名と一致）
WorkingDirectory=/home/ec2-user/api
Restart=always
Type=simple
User=ec2-user

[Install]
WantedBy=multi-user.target
```

### ファイルのコピー（EC2上）と実行
```
# EC2上の実行する先のディレクトリへコピー
[ec2-user@<ipアドレス> ~]$ sudo cp -a app.service /etc/systemd/system
# 定期実行の開始と終了
[ec2-user@<ipアドレス> ~]$ sudo systemctl start app.service
[ec2-user@<ipアドレス> ~]$ sudo systemctl stop app.service
```