Docker + ec2 + nginx + Next.jsでの環境構築してWebアプリを公開する

# はじめに

- タイトルの通りの環境を構築したい
- 色々苦戦したので、その時のメモ
- エンジニア歴半年の備忘録

# バージョン（2023.10.6 現在最新）

- AWS EC2 t2.micro + Ubuntu 22.04 LTS
- Docker 24.0.6
- docker-compose 2.21.0
- nginx 1.18.0
- Next.js 13

# やっていく

### EC2の環境構築

すでにやってあるのでこちらからどうぞ

今回はVScodeからSSH接続して使ってます（GUIの方が何かと便利なので）

あと、HTTP（80番ポート）は開けておいて下さい。

https://qiita.com/Kento210/items/2a7a61fd034b8b5001a6

AWS EC2のUbuntuはrootユーザーのパスワードが初期で入っていないため、パスワードを使うような今回の場面では設定しておくことが無難です。（sudoで突破することもできる）

- 一般ユーザでログイン
- `sudo su -` でrootユーザーに変更
- `passwd` コマンドでnew passwordを設定

これだけ。

参考：

https://ja.stackoverflow.com/questions/82749/amazon-ec2-で-ubuntu-を作ると-su-でパスワードを聞かれる

### Dockerとdocker-composeを入れる

これは非常に簡単

以下を順に実行するだけ

```
// 更新とインストール
$ sudo apt-get update

$ sudo apt-get install

// GPGキーを保存するディレクトリを作成
$ sudo mkdir -p /etc/apt/keyrings

// GPGキーを取得
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

// Dockerリポジトリをとってくる
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

// ここで改めて更新
$ sudo apt-get update

// 最後にインストール
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```

簡単なテストの前に、どの権限ユーザーでも実行できるようにします

```
// ユーザーをDockerグループに追加
$ sudo usermod -aG docker $USER

// 設定を変更
$ sudo su - ${USER}
```

バージョンを確認してHello worldして確認します

```
// バージョン確認
$ docker -v

// 動作確認
$ docker run hello-world
```

以下が出ていれば成功です！

![スクリーンショット 2023-10-06 2.41.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3504047/ea4fd1de-eff1-057e-757d-e88c955ed2d1.png)

docker-composeを入れます

```
// インストール
$ sudo apt install docker-compose-plugin

// 確認
$ docker compose version
```

参考：

https://www.kagoya.jp/howto/cloud/container/dockerubuntu/

https://qiita.com/kujiraza/items/a8236f65e2c46735ee91

### Next.js + dockerのセットアップ

ここは使いたいフレームワークを入れてDockerのコンテナを立ち上げてあげるだけです。今回は例としてNext.jsを爆速でセットアップします。

Next.jsの立ち上げ

```
$ npx create-next-app nextjs-docker-app
$ cd nextjs-docker-app
```

ルートディレクトリにDockerfileを作成

```
# ベースイメージとして公式のNode.jsを使用
FROM node:16-alpine

# アプリケーションのディレクトリを作成
WORKDIR /app

# 依存関係のコピーとインストール
COPY package*.json ./
RUN npm install

# アプリケーションのソースをコピー
COPY . .

# アプリケーションをビルド
RUN npm run build

# ポート3000でアプリを起動
EXPOSE 3000
CMD ["npm", "start"]
```

ビルド

```
$ docker build -t nextjs-docker-app .
```

コンテナの起動

```
$ docker run -p 3000:3000 nextjs-docker-app
```

非常に簡単なものですが、ここはEC2内でローカルホストに渡せれば何でも良いです。

### Nginxを設定していく

まずはnginx自体をインストールします

```
sudo apt update
sudo apt install nginx
```

nginxは、基本的に`/etc/nginx`のディレクトリに格納されています。

めんどくさいことにrootユーザーじゃないと書き込み権限がないので権限を調節するか、sudoをいちいちつける必要があります（めんどい）

以下のポイントだけ押さえておきましょう

- `/etc/nginx/nginx.conf`：メイン設定ファイル、値の最大値など色々変更できる
- `/etc/nginx/sites-available/`：ここを主に変更することで設定する
- `/etc/nginx/sites-enabled/`：有効化された設定（のリンク）が保存される

要は、sites-availableディレクトリに設定を保存し、有効化するだけです。

実際にやってみましょう！

my-nestjs-appという設定ファイルを新しく作ります

```
$ sudo nano /etc/nginx/sites-available/my-nextjs-app
```

ちなみにCtrl + Xを押した後にY、Enterでnanoは保存可能です。

今回はHTTPアクセスを可能にします

以下を簡単に要約すると、

- 80番ポートでアクセス可能
- 立ち上がっているlocalhost3000をドメイン名やIPと結びつけて公開

って感じです。簡単〜〜〜〜

```
server {
    listen 80;

    server_name [ここにドメイン名やIPなど];

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
```

設定を有効化（シンボリックリンクの作成）します

```
$ sudo ln -s /etc/nginx/sites-available/my-nextjs-app /etc/nginx/sites-enabled/
```

簡単な構文チェックをしましょう

```
$ sudo nginx -t
```

以下のように出ていればエラーがないのでok

```
syntax is okay
test is successful
```

nginxを再起動します

```
$ sudo systemctl restart nginx
```

`http://[IPやドメイン名]/`

でブラウザからアクセスしてみましょう！

よく見るNext.jsの最初ページが見れたら設定完了です。お疲れ様でした！

# おまけ

### CI / CDの環境を構築して開発を容易にする

EC2に直でSSHして開発を行うのも趣がありますが、クッソだるいです

今回は省略しましたが、CI / CDをGithub Actionで構築しておきたいと感じたら以下をぜひ参考にしてください（便利です）

https://qiita.com/Kento210/items/4c96d2fa5220e6f52cec