Next.jsをAWS Lightsail上にDocker Composeを使ってデプロイする方法

完成した図
![b7bcc17b-6493-455b-bb45-6ed748c03f72.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294049/5e919c35-c9f3-66a5-1303-2d286592441f.png)


Next.jsをAWS Lightsail上にDocker Composeを使ってデプロイする方法を以下に示します。この構成で、NGINX、Next.js、MySQLを使う場合の基本的なステップを説明します。

1. **Lightsailのインスタンス作成**:
    - AWS Management Consoleにログインし、Lightsailサービスを開きます。
    - `Create instance` を選択します。
    - インスタンスの設定を行い、`OS Only` と `Ubuntu` を選択します。

2. **DockerとDocker Composeのインストール**:
    LightsailインスタンスにSSH接続した後、DockerとDocker Composeをインストールします。

    ```bash
    # Dockerのインストール
    curl -fsSL https://get.docker.com -o get-docker.sh
    sh get-docker.sh

    # Docker Composeのインストール
    sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose
    ```

3. **Docker Composeの設定**:
    - ルートディレクトリに `docker-compose.yml` ファイルを作成します。
  
    ```yaml
    version: '3'

    services:
      nginx:
        image: nginx:latest
        ports:
          - "80:80"
        volumes:
          - ./nginx.conf:/etc/nginx/nginx.conf
        depends_on:
          - nextjs

      nextjs:
        build:
          context: ./path_to_nextjs_app
          dockerfile: Dockerfile
        environment:
          - DATABASE_URL=mysql://user:password@mysql:3306/dbname

      mysql:
        image: mysql:latest
        environment:
          MYSQL_DATABASE: dbname
          MYSQL_USER: user
          MYSQL_PASSWORD: password
          MYSQL_ROOT_PASSWORD: root_password
        volumes:
          - mysql-data:/var/lib/mysql

    volumes:
      mysql-data:
    ```

    注意: 上記のYAMLは基本的な設定のみを示しています。適切な設定と調整が必要です。

4. **Next.jsのDockerfileの作成**:
    - Next.jsのアプリケーションディレクトリに`Dockerfile`を作成します。
  
    ```Dockerfile
    FROM node:14

    WORKDIR /app
    COPY . .
    RUN npm install
    RUN npm run build

    CMD ["npm", "start"]
    ```

5. **NGINXの設定**:
    - `nginx.conf` ファイルを作成し、NGINXの設定を記述します。特に、Next.jsアプリケーションにリバースプロキシとしてリクエストを転送する設定が必要です。

6. **Docker Composeの実行**:
  
    ```bash
    docker-compose up -d
    ```

7. **セキュリティグループの設定**:
    Lightsailの管理コンソールで、インスタンスのセキュリティグループを編集し、適切なポート（例: 80, 443）が公開されていることを確認します。

以上で、基本的なデプロイが完了します。セキュリティ、バックアップ、エラーハンドリングなど、本番環境での使用を考慮した追加の設定が必要になる場合がありますので注意してください。

## Route 53を使用してLightsailインスタンスにドメイン名を関連付ける

Route 53を使用してLightsailインスタンスにドメイン名を関連付ける手順は以下のとおりです。

1. **Route 53で新しいホストゾーンの作成**:
    - AWS Management Consoleにログインし、Route 53サービスを開きます。
    - `Create Hosted Zone` ボタンをクリックして新しいホストゾーンを作成します。
    - ドメイン名を入力し、ホストゾーンを作成します。

2. **LightsailのパブリックIP取得**:
    - Lightsailの管理ページで、作成したインスタンスのパブリックIPアドレスをメモします。

3. **Route 53でレコードセットの作成**:
    - 先ほど作成したホストゾーンの管理ページに移動します。
    - `Create Record`をクリックします。
    - 次の設定でAレコードを作成します:
        - Name: あなたのドメイン名またはサブドメイン名。
        - Type: A - IPv4 address.
        - Value: LightsailインスタンスのパブリックIPアドレス。
    - レコードを保存します。

4. **ドメインレジストラでのNameserverの更新**:
    - Route 53で提供されるNameservers (NSレコード) の値をコピーします。
    - あなたのドメインを購入したレジストラの管理ページにアクセスし、ドメインのNameserver設定を更新してRoute 53のNameserverに変更します。

5. **SSL証明書の取得 (オプション)**:
    - HTTPSでサイトをホストする場合、SSL/TLS証明書が必要です。AWS Certificate Manager (ACM) またはLet's Encryptを使用して証明書を取得できます。
    - NGINX設定にSSLを追加する必要があります。これには、証明書のファイルへの参照と、HTTPSのポート443をリッスンする設定が必要です。

6. **NGINXの設定の更新 (オプション)**:
    - SSL/TLS証明書を使用する場合、NGINXの設定を更新して、HTTPSリクエストを適切に処理できるようにします。 

以上の手順を完了すると、Route 53を使用してドメイン名がLightsailインスタンスに関連付けられます。これにより、ブラウザからそのドメイン名を使用してインスタンスにアクセスできるようになります。

## SSL化はCertbotで設定

nginx.conf ファイルを作成し、NGINXの設定を記述。
Certbotを使用してSSL/TLS証明書を取得し、NGINX設定でそれを使用。

### docker-compose.ymlの例:

```yaml
version: '3'

services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./certs:/etc/letsencrypt
    depends_on:
      - nextjs

  nextjs:
    build:
      context: ./path_to_nextjs_app
      dockerfile: Dockerfile
    environment:
      - DATABASE_URL=mysql://user:password@mysql:3306/dbname

  mysql:
    image: mysql:latest
    environment:
      MYSQL_DATABASE: dbname
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: root_password
    volumes:
      - mysql-data:/var/lib/mysql

  certbot:
    image: certbot/certbot:latest
    volumes:
      - ./certs:/etc/letsencrypt
    command: certonly --webroot --webroot-path=/var/www/certbot -d yourdomain.com -d www.yourdomain.com --email your@email.com --agree-tos --non-interactive

volumes:
  mysql-data:
```

この例では、CertbotがSSL/TLS証明書を取得し、それをNGINXで使用するように設定されています。ただし、Certbotの設定はドメイン名やメールアドレスに応じて変更する必要があります。

## diagramsライブラリを使って構成図作成

```
from diagrams import Cluster, Diagram
from diagrams.aws.compute import Lightsail
from diagrams.aws.network import Route53
from diagrams.generic.os import Ubuntu
from diagrams.onprem.container import Docker
from diagrams.onprem.database import Mysql
from diagrams.onprem.network import Nginx
from diagrams.onprem.compute import Server

with Diagram("AWS Next.js Deployment", show=False):

    dns = Route53("Route 53\nDomain")
    
    with Cluster("Lightsail Instance"):
        os = Ubuntu("Ubuntu")
        docker = Docker("Docker")
        
        os >> docker
        
        with Cluster("Docker Services"):
            nginx = Nginx("NGINX")
            nextjs = Server("Next.js App")
            mysql = Mysql("MySQL")
            certbot = Server("Certbot")
            
            docker >> nginx
            
            nginx >> nextjs
            nextjs >> mysql
            certbot >> nginx

    dns >> os
```