【AWSハンズオン】Nuxt + Golang構成のWebアプリをAWSへデプロイしよう！

みなさん、こんにちは！
学生サーバサイドエンジニアの[くろちゃん](@TakumaKurosawa)です。

今日はAWSを題材に、自分で作ったWebアプリケーションをデプロイできるようになることを目指して記事を書かせていただきます！

この記事を最後まで読むことで、下記のようなことができるようになります！

- 自分のWebアプリケーションを公開できるようになる
- AWSの下記のサービスを使えるようになる
    - VPC
    - EC2

ぜひ最後まで一緒に手を動かしながら楽しんでいってくださいね👍

なお、この記事は[CA Tech Dojo/Challenge/JOB Advent Calendar 2019](https://qiita.com/advent-calendar/2019/dojo-challenge-job)(22日目)の記事になります！

前日の@yawn_yawn_yawn_さんの[Ubuntu + nginx + LetsEncryptでSSL/TLSを設定する](https://qiita.com/yawn_yawn_yawn_/items/c436343f544d13e3be1d)からバトンを引き継いでお送りしています。まだ見てないよって方はそちらも合わせてどうぞ！

では、早速ハンズオン始めていきましょう〜！！

---
### `前提条件`
これらはできることを前提として話を進めていきますのでご了承ください。

**※なお、本ハンズオンはOS Xを対象ユーザとして定めていますので、Windowsその他OSを使用している皆さんにつきましては適時読み替えて頂きますようにお願いします。**


- AWSアカウントの作成＆[AWSマネージメントコンソール](https://console.aws.amazon.com/console/home?region=us-east-1)へのログイン成功
- GitHubアカウントの作成とSSH接続
    - こちらのSSH接続についてわからない方は、[GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~
](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)をご覧ください！
- [Dockerがローカル環境で利用できる状態であること](https://qiita.com/kimiko0217/items/2ab7ad8aafcd0c79d2ff)


## 目次
本ハンズオンでは下記のような流れでWebアプリケーションの公開〜自動デプロイの構築までを行っていきます。

[0. 事前準備](#0-事前準備)
[1. VPCを構築しよう！](#1-vpcを構築しよう)
[2. EC2インスタンスを起動しよう！](#2-ec2インスタンスを起動しよう)
[3. Webアプリをデプロイしよう！](#3-webアプリをデプロイしよう)

## 0. 事前準備
本ハンズオンでは私が事前に作っておいたアプリケーションを使用します。
下記の手順に従ってアプリケーションをダウンロード＆動作確認してみましょう！

### GitHubリポジトリをforkしてこよう！
下記のGitHubリポジトリから自分のリポジトリへforkしてきましょう！

▼まずはアクセス▼
https://github.com/Takumaron/AWS_tutorial

![スクリーンショット_2019-12-21_14_28_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/7c7256cf-9746-5101-0ea6-0f8c2a9176c3.png)


フォーク先を指定して、きちんとフォークできていれば下記のような画面になります。（Qiita-test-aws-tutorialの部分は皆さんのGitHubアカウント名になります。）

![スクリーンショット 2019-12-21 14.26.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/16269c42-ed4b-bada-0b3f-af9cf41fe615.png)

続いて、Forkしてきたリポジトリを自分のPCにクローンしてきます。

![スクリーンショット_2019-12-21_14_31_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/94759bae-248e-4c95-5fbe-c206fbbf984d.png)

ターミナルを開いて下記のコマンドを入力してください。

``` bash
git clone [コピーしたURL]
```

下記のような出力結果が得られれば正常にクローンできています。

``` bash
$ git clone git@github.com:Qiita-test-aws-tutorial/AWS_tutorial.git
Cloning into 'AWS_tutorial'...
remote: Enumerating objects: 55, done.
remote: Counting objects: 100% (55/55), done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 55 (delta 9), reused 49 (delta 5), pack-reused 0
Receiving objects: 100% (55/55), 155.68 KiB | 484.00 KiB/s, done.
Resolving deltas: 100% (9/9), done.
```

### アプリケーションが正常に動作するかチェックしよう！
クローンまでできたら、自分の環境で正しく動作するか検証しましょう。
下記のコマンドを入力してください。

``` bash
$ cd AWS_tutorial
$ make start
docker-compose up -d
Building api_server
Step 1/4 : FROM golang:1.12.4-alpine
 ---> b97a72b8e97d
Step 2/4 : COPY ./ /go/aws_tutorial
 ---> 4fda45b3bf59
Step 3/4 : WORKDIR /go/aws_tutorial
 ---> Running in 421be46cf16b
Removing intermediate container 421be46cf16b
 ---> 032f324638b8
Step 4/4 : RUN apk update   && apk add --no-c

---- 中略(少し時間がかかります。少々お待ちください。) -----

Creating aws_tutorial_api_server_1 ... done
Creating aws_tutorial_client_1     ... done

```

Dockerコンテナが正常に立ち上がったら、お好みのWebブラウザを開いて http://localhost:3000/hello へアクセスしてください。
下記のような画面が表示されていれば、OKです！お疲れ様でした。

<img width="1424" alt="スクリーンショット 2019-12-22 9.01.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/dc094d35-b097-79be-6f88-7a39dcbe2e34.png">

## 1. VPCを構築しよう！
さっそく、先ほどローカル上で動作確認したアプリケーションをAWSに乗せていきます！

まずはVPCというサービスを使って、グローバルなWebの世界に自分の領域を作っていきます。下記の手順に従って一緒に設定していきましょう！

まずは、AWSマネジメントコンソールへサインインします。

https://console.aws.amazon.com/console/home?region=us-east-1

サインインが完了したら、左上の「サービス」をクリックして下記の画像のようにVPCを検索します。

![スクリーンショット_2019-12-22_9_06_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/32c13130-8d0f-ad1f-cdb1-d93d1752718d.png)

このような画面は開けましたか？

![スクリーンショット_2019-12-22_9_12_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/28e8dd08-8d28-6400-a223-3965c41e2e76.png)

### 今回構築するVPCの全体像
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/eb769940-d663-c8f9-46d1-33e4296a25f3.png)

出た！訳のわからない図！！って言って諦めないでくださいw
システム構成図も理解できればそんなに大したものではありません。

まず押さえていただきたいポイントは、**VPCのなかにパブリックサブネットっていう奴があって、その中にEC2っていうものが動いている**というざっくりしたイメージです。

分かりやすい例えがないかなと一生懸命考えて思いついた「家の例え」でこの構成を説明していきます。

まずはこの対応表を頭にいれてください。

| サービス名 | 家に例えると？ |
| -------- | -------- |
| VPC     | 🏠 家     |
| インターネットゲートウェイ     | 🚪 玄関     |
| サブネット     | 🛋 部屋     |
| EC2    | 👨‍🦱 住人     |

イメージとしては、

`家（VPC）に外部から人がやってきたときには、玄関（インターネットゲートウェイ）を通して家に入ります。そして、部屋（サブネット）へ案内をして、住人（EC2）がおもてなしします。`

という一連の流れで理解するとそれぞれの役割が明確になるのではないでしょうか？

それぞれのサービスの役割が理解できたところでハンズオンに戻っていきましょう！

### VPCを作成する
![スクリーンショット_2019-12-22_9_54_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/2872eed1-847b-8dfa-c5ab-b0140aa48c01.png)

![スクリーンショット_2019-12-22_10_03_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/e2431ce5-1a85-90f0-9431-17dde879675a.png)

### サブネットを作成する
![スクリーンショット_2019-12-22_10_10_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/d1eb2c73-e617-90bb-a2b0-19f43df20e6f.png)

![スクリーンショット_2019-12-22_10_14_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/0350aedf-28e1-9045-e9ee-08be6bef21c7.png)

### インターネットゲートウェイを作成する
![スクリーンショット_2019-12-22_10_22_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/55c9dd30-bd61-fbaa-3936-e00bf6c7c5de.png)

![スクリーンショット_2019-12-22_10_24_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/7bcfa8c7-3f37-61b8-9081-81ab58ce1593.png)


![スクリーンショット_2019-12-22_10_26_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/6d04794f-2f97-9df0-cea4-f1df86c2920f.png)

![スクリーンショット_2019-12-22_10_31_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/a3162645-c250-23c1-7745-446d811a6162.png)

### ルートテーブルを編集する
サブネット（部屋）やインターネットゲートウェイ（玄関）がバラバラに存在している状態なので、それぞれの対応づけをしていきます。
![スクリーンショット_2019-12-22_10_38_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/b36c94b1-1c81-aaed-362d-34ea549a4d1e.png)

![スクリーンショット_2019-12-22_10_45_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/4ea2e678-96ca-a404-972d-b097431c3bf5.png)

![スクリーンショット_2019-12-22_10_48_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/e469bc07-0bfe-8fdb-bfa3-20e8d6ccea47.png)

![スクリーンショット_2019-12-22_10_50_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/33c43081-8748-af48-b5df-6c0d2bafd567.png)

![スクリーンショット_2019-12-22_10_53_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/26bf711d-a7ef-dd6e-0cdb-a78dafd80ee2.png)

VPCの構築はここまでで完了となります！お疲れ様でした！
次は、VPCの中で動作するEC2インスタンスを作成していきます。

## 2. EC2インスタンスを起動しよう！
Webアプリケーションを動かすための場所作りは[1. VPCを構築しよう！](#1-vpcを構築しよう)にて完了したので、実際に作ったWebアプリケーションを動かしてくれるマシーンを構築していきましょう！

【補足】
EC2インスタンスとは、仮想サーバーのようなものです。
AWSが事前に用意しているOSや独自で作成したOSイメージを使ってサーバを立てることができます。
今回は無料枠で利用できるAmazon Linux 2 AMIを利用します。

![スクリーンショット_2019-12-22_11_08_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/cdd06a00-d02b-412f-2377-f805071dddf6.png)

![スクリーンショット_2019-12-22_11_12_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/0a9b8aa8-bb12-f466-ec21-b7907a898e0a.png)

![スクリーンショット_2019-12-22_11_14_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/e4d110e2-0de3-775a-1447-28bc11cbcc27.png)

![スクリーンショット_2019-12-22_11_15_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/4bb2c0ab-5c6b-f7c6-a619-982051ee5e1c.png)

【変更点】のみ入力内容を修正して「次のステップ」へ

![スクリーンショット_2019-12-22_11_21_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/3e859ad6-10c9-1e57-c886-85f8dab7b976.png)

![スクリーンショット_2019-12-22_11_23_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/06fa9cde-9f57-3179-69ed-48823a291f70.png)

![スクリーンショット_2019-12-22_11_25_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/7e17a2a5-a9b0-f4dd-b4af-73d8d0586aa2.png)

![スクリーンショット_2019-12-22_11_29_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/828a655f-3927-ec92-883a-7ae1e441667b.png)

![スクリーンショット_2019-12-22_11_34_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/2306b837-5b41-0002-07bc-b2e6a38e373c.png)

![スクリーンショット_2019-12-22_11_38_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/b59a187c-790c-4067-f9dd-3ea1fdf72461.png)

**`キーペアは後ほどEC2にローカルからつなぎに行くときに必要になるファイルですので、ダウンロード後も無くさないようにしてくださいね！`**

ダウンロードが完了したら、「インスタンスの作成」をクリックすればEC2インスタンスの作成が始まります。（約２分ほど待てば下記のようにインスタンスの状態が「running」に切り替わると思います。）

![スクリーンショット_2019-12-22_11_48_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/bbbd2dc6-14e6-73e1-4ed5-361a75997ca6.png)

お疲れ様でした！
ここまででVPCの構築と、EC2インスタンスの起動まで終わりました！

あとは、EC2インスタンス上でWebアプリケーションを動かすだけです。もうちょっとなので一緒に頑張りましょう💪

## 3. Webアプリをデプロイしよう！
さぁ、あとは自作したWebアプリケーションをEC2上で動かすだけですね！

Webアプリのデプロイは下記のような手順で行なっていきます。

1. EC2インスタンスにssh接続する
2. GitコマンドとDocker・Docker-composeコマンドが使用できるようにパッケージをインストール
3. GitHubからプロジェクトをクローンしてくる
4. アプリケーションを立ち上げる

それでは、さっそく始めましょう〜！

### EC2インスタンスにSSH接続しよう！
まずは、作成したEC2インスタンスにSSHで接続しましょう！

自分のEC2インスタンスのIPアドレスを知っておく必要があるので、下記の画像を参考にして、IPアドレスをコピーしておきます。

![スクリーンショット_2019-12-22_11_48_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/74d9aa6d-2fc5-1ca5-ac76-de3b5700da2e.png)

それが完了したら、ターミナルを起動して下記のようなコマンドを打ちます。

``` sh
# ダウンロードしたaws-tutorial.pemがあるディレクトリへ移動
$ cd ~/Downloads

# pemファイルを~/.sshへ移動
$ mv aws-tutorial.pem ~/.ssh

# pemファイルにアクセス権限を付与しておく
$ chmod 400 ~/.ssh/aws-tutorial.pem

# ssh接続
$ ssh -i "~/.ssh/aws-tutorial.pem" ec2-user@[自分のIPアドレス（ペースト）]
Are you sure you want to continue connecting (yes/no)? yes # ←初回起動時には`yes`と入力
```

ssh接続が完了すると、下記のようなコマンドプロンプトに切り替わります。

```


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

https://aws.amazon.com/amazon-linux-2/
8 package(s) needed for security, out of 17 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-10-151 ~]$
```

これでSSH接続は完了です！
ちなみに、SSH接続を切断する場合は、下記のコマンドを打ちます。

``` bash
$ exit
```

### GitとDockerを動かせるようにしよう！
SSH接続が完了したら、GitとDockerを使えるようにセットアップしていきましょう！

``` bash
# yumをアップデート
$ sudo yum update -y

# Gitのインストール
$ sudo yum install git -y

# Dockerのインストール
$ sudo yum install -y docker

# Dockerの起動
$ sudo service docker start
$ sudo systemctl enable docker.service
$ sudo service docker status

# 下記のような出力結果が得られればOK
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2019-12-22 03:26:02 UTC; 10s ago
     Docs: https://docs.docker.com
 Main PID: 12952 (dockerd)
   CGroup: /system.slice/docker.service
           └─12952 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd....

# dockerコマンドを使用可能にする
$ sudo usermod -a -G docker ec2-user

# 一度exit
$ exit
```

ここまででDockerとGitが動くようになりました。
SSHで再接続して、Docker-composeも入れていきましょう！

``` bash
# スーパーユーザに切り替える
$ sudo -i

# 必要なファイルをダウンロード
curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 権限を与える
chmod +x /usr/local/bin/docker-compose

# 通常ユーザに戻る
exit

# 確認
$ docker-compose --version

```

### GitHubからプロジェクトをクローンしてこよう！
DockerとGitが使えるようになったので、GitHubからアプリケーションをダウンロードしてきましょう！

https://github.com/[あなたのGitHubID]/AWS_tutorial へ遷移しましょう。

**「Clone with HTTPS」**モードでクローンURLをコピーします。

![スクリーンショット_2019-12-22_12_37_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/9f9e836f-968c-29d3-7ec2-5415222be450.png)

コピーしたクローンURLを使ってEC2上にクローンしてきましょう！

``` bash
$ git clone [ペースト]

# AWS_tutorialが存在するか確認
$ ls
AWS_tutorial
```

### アプリケーションを立ち上げよう！
ここまでこれば準備万端！あとは立ち上げるだけですね😽

プロジェクトフォルダに移動して、アプリケーションを立ち上げましょう！

``` bash
# プロジェクトフォルダへ移動
$ cd AWS_tutorial

# アプリケーションを立ち上げる
$ make start

...

Creating aws_tutorial_api_server_1 ... done
Creating aws_tutorial_client_1     ... done
```
立ち上がりました！
Webブラウザからアクセスをして動作チェックをしてみましょう！

http://EC2インスタンスのIPアドレス:3000/
<img width="1425" alt="スクリーンショット 2019-12-22 12.56.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/057c6c11-24a7-42e6-ae7c-ca6490478ff9.png">

動いているみたいですね！
バックエンドとの連携もできているでしょうか？

http://EC2インスタンスのIPアドレス:3000/hello
<img width="1434" alt="スクリーンショット 2019-12-22 12.56.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/f8c63ef6-8354-c47c-13df-1f2b8f62acee.png">

できているみたいですね！！

バックエンドAPIに対してブラウザからはアクセスできないことも確認しておきましょう。

http://EC2インスタンスのIPアドレス:8080/ping
<img width="1422" alt="スクリーンショット 2019-12-22 12.59.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317034/e0492f40-f1db-66b9-8567-99d1df7bb9c4.png">

成功です！！お疲れ様でした:tada:
ハンズオンはここまでとなります。

【発展】
バックエンド側（:8080)にアクセスできない理由は分かりますか？
余裕のある方は、発展としてなぜアクセスできないのか考えてみてください！（ヒントは、**セキュリティグループ**です！）

---

いかがだったでしょうか？
かなり長いハンズオンになってしまいましたが、ここまで読んでいただきましてありがとうございました！

今回はVPCとEC2を使って簡単なWebアプリケーションをデプロイしました。

次はRDSというサービスを使ってDB機能を持たせたり、Code Buildというサービスを使って自動デプロイを実現できるようなハンズオンを作りたいと思います！

明日の[CA Tech Dojo/Challenge/JOB Advent Calendar 2019](https://qiita.com/advent-calendar/2019/dojo-challenge-job)は@hmarfさんが担当です！引き続きお楽しみください！！

▼こちらも要チェック！！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🔥サイバーエージェント 2021エンジニア採用本選考開始🔥<br><br>今年のテーマは『Make Your Chance』。<br>Chanceという単語には本来「偶然性」の意味合いもありますが、<br>それも含め自分から声を上げ動き、チャンスを作り出してほしいという思いを込めています。<br><br>挑戦、待ってます！<a href="https://t.co/zpnxztQOpl">https://t.co/zpnxztQOpl</a></p>&mdash; ゴッティ@サイバーエージェントエンジニア採用 (@masagotty) <a href="https://twitter.com/masagotty/status/1202532839071240193?ref_src=twsrc%5Etfw">December 5, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>