DockerでローカルHTTPS通信を実現

Docker を利用すると、ローカル環境でも本番に近い環境を構築し、テストすることが一般的です。

本記事では、フロントエンドとバックエンドを分離した Web サービスを構築し、**HTTPS** を用いた **ローカル環境** のセットアップ方法を解説します。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941221/cd4ec8c9-9de0-4a1d-8390-ea48b674a61f.png">



## 環境構築の要件

### 1. HTTPS でアクセスするために必要なもの
HTTPSでアクセスするためには、まず証明書が必要です。**AWS Route 53**でドメインを登録し、証明書を取得します。

#### **ドメインの設定**
- **フロントエンド URL**: `https://front.com`
- **バックエンド URL**: `https://back.com`

とする場合、両方を **A レコード（IPv4）** として **127.0.0.1** に登録します。

:::note info
**127.0.0.1** はローカルホストを指し、そのリクエストを送信したマシン自身へ向かう IP アドレスです。
:::

#### **リバースプロキシの設定**
フロントエンドやバックエンドのコンテナの前に **リバースプロキシサーバー（Nginx）** を設置し、証明書を配置することで、外部から HTTPS でアクセスできるようになります。

##### **フロントエンドの Nginx 設定例**
```nginx
upstream front_server {
    server front-end:10080;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name front.com;

    ssl_certificate /etc/nginx/ssl/fullchain.pem; ← サーバー証明書
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;　← 証明書の秘密鍵

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass http://front_server;
    }
}
```

---

### 2. フロントエンドとバックエンドの区別
DNSにあるホストとIPの情報だけでは、フロントとバックが同じ**127.0.0.1**に設定されているため、区別がつきません。

✅ **解決策:**
- **異なるポートを割り当てる**
  - フロントエンド: `10080`
  - バックエンド: `20080`

:::note info
コンテナにはホスト側ポートとコンテナ側ポートがあります。コンテナ間の通信は **コンテナ側のポート** を利用します。
:::

---

### 3. コンテナ同士の通信方法

#### **外部ネットワーク（External Internet）**
- 世界中のネットワークに接続された **インターネット全体** を指します。
- ISP（インターネットサービスプロバイダー）を経由してアクセスします。

#### **内部ネットワーク（Docker 内部ネットワーク）**
- **Docker コンテナ間** で通信できる **プライベートネットワーク** です。
- **外部からはアクセスできません。**

#### コンテナ同士の通信方法
Docker Composeでは、コンテナ名が必ず定義されています。
```yaml
services:
  back-end: # コンテナ名
    image: amazonlinux:2
    restart: always
    env_file: ./.env
    ports:
      - 20081:20080
```

✅ **コンテナ名を指定** することで、Docker **内部ネットワーク** での通信が可能になります。

```plaintext
http://back-end:20080 　← コンテナ内部でバックエンドへの通信
```

---

### 4. `hostname` オプションを活用する
**Route 53** で `back.com` を登録しても、**フロントエンド** から `https://back.com` へのアクセスが失敗することがあります。

これは、`back.com` が **Route 53** を通じてローカルホストに返された際に、複数のコンテナのどちらへルーティングするかを Docker の**内部 DNS** が解決しようとします。しかし、内部 DNS の設定が不十分なため、アクセスに失敗してしまいます。

✅ **解決策:**
- **Docker 内部 DNS にホストを追加**
- **`hostname` オプションを利用**

:::note info
コンテナ の `/etc/hosts` ファイルを確認すると、内部 DNS の情報がわかります。
:::

Docker 内部の各コンテナにはプライベート IP が割り当てられています。内部 DNS にホスト名 `back.com` を **back-proxy** の IP に設定すれば名前解決できますが、Docker Compose でコンテナを起動するたびに IP が変わるため、都度設定が必要です。そこで、Docker の **`hostname`** オプションを利用すると、動的に内部 DNS の設定ができ、より便利になります。

#### **docker-compose.yml**
```yaml
services:
  front-proxy:
    image: nginx:1
    ports:
      - 443:443
    depends_on:
      - front-end
  back-proxy:
    image: nginx:1
    ports:
      - 443:443
    depends_on:
      - back-end
    hostname: back.com  # 内部ネットワークでも "back.com" でアクセス可能にする
  front-end:
    image: amazonlinux:2
    restart: always
    env_file: ./.env
    ports:
      - 10081:10080
  back-end:
    image: amazonlinux:2
    restart: always
    env_file: ./.env
    ports:
      - 20081:20080
```


## **まとめ**
1. **AWS Route 53 でドメインを登録し、127.0.0.1 に向ける**
2. **Nginx をリバースプロキシとして HTTPS 通信を実現**
3. **フロントエンドとバックエンドはポートで区別**
4. **コンテナ名で内部ネットワーク通信を行う**
5. **内部 DNS の問題を `hostname` オプションで解決**

この方法を活用すれば、**ローカル環境でも本番に近い HTTPS 環境を構築** できます！ 🎉

---

以上、ローカル環境で HTTPS 通信を実現する方法でした😊