🤨

ローカル環境をHTTPSにする

2023/05/07に公開
1

動機

Sign in with Slackを使おうとしたが、独自ドメインかつSSL化されていないURLは許可されなかった。。。
例:
http://localhost:3000 => こいつだめ
https://example.com => こいつok

どうにかローカルでSlack認証を実現したいと試案した結果ローカル環境をssl x 独自ドメイン化することにした

やり方

今回は新たにリバースプロキシを建て、それを独自ドメイン化 & SSL化し、全ての通信をリバースプロキシを介すことで実現しようと思う。

最終的にリバースプロキシでこの様にリクエストを捌く
https://api.sampleApp.com => バックエンド
https://sampleApp.com => フロント

構成

(格サーバーはdocker-composeによって独立していて、networksを共有している状態。)

事前準備事項

  • フロントエンドとバックエンドのサーバーを建てる(この記事ならバックエンド8081、フロントエンド3001)。

  • docker-composeでnetworksを共有

  • mkcertの準備

$ brew install mkcert # mkcertのインストール
$ mkcert -install     # mkcertでローカルに認証局をインストール
  • hostsの編集
127.0.0.1 api.sampleApp.com 
127.0.0.1 sampleApp.com 

リバースプロキシを立てる

  1. まずはポート80を開けて、通信が可能か確認
    docker-compose.yaml
version: '3.8'
services:
  rpx:
    image: nginx:latest
    container_name: コンテナ名
    ports:
      - 80:80
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    networks:
      - 共有dockerネットワーク名

networks:
 共有dockerネットワーク名:
    external: true

nginx.conf

events {
  worker_connections 16;
}
http {
  server {
    listen 80;
    server_name sampleApp.com;
   
    location / {
      proxy_pass http://host.docker.internal:3001/;
      proxy_redirect off;
    }
  }

  server {
    listen 80;
    server_name api.sampleApp.com;

    location / {
      proxy_pass http://host.docker.internal:8081/;
      proxy_redirect off;
    }
  }
}

下記に通信できればok
http://sampleApp.com
http://api.sampleApp.com

SSL化

  1. 証明書と秘密鍵を生成する
# 証明書と鍵を保管するディレクトリに移動
# 私の場合はリポジトリのルート直下にsslディレクトリを作成し、その中
$ cd ssl

$ mkcert sampleApp.com
$ mkcert api.sampleApp.com

$ ls -la 
# 下のように生成されていたらok
# sampleApp.com.pem
# sampleApp.com-key.pem
# api.sampleApp.com.pem
# api.sampleApp.com-key.pem

docker-compose.yaml

  • 443ポートを解放
  • 先ほど生成した証明書と鍵をコンテナ内にマウントする
version: '3.8'
services:
  rpx:
    image: nginx:latest
    container_name: コンテナ名
    ports:
      - 443:443
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl/api.sampleApp.com-key.pem:/etc/certs/api.sampleApp.com-key.pem
      - ./ssl/api.sampleApp.com.pem:/etc/certs/api.sampleApp.com.pem
      - ./ssl/sampleApp.com-key.pem:/etc/certs/sampleApp.com-key.pem
      - ./ssl/sampleApp.com.pem:/etc/certs/sampleApp.com.pem
    networks:
      - 共有dockerネットワーク名

networks:
  共有dockerネットワーク名:
    external: true

nginx.conf

events {
  worker_connections 16;
}
http {
  server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /etc/certs/sampleApp.com.pem
    ssl_certificate_key /etc/certs/sampleApp.com-key.pem;

    location / {
      proxy_pass http://host.docker.internal:3001/;
      proxy_redirect off;
    }
  }

  server {
    listen 443 ssl;
    server_name api.sampleApp.com;
    ssl_certificate /etc/certs/api.sampleApp.com.pemm;
    ssl_certificate_key /etc/certs/api.sampleApp.com-key.pem;

    location / {
      proxy_pass http://host.docker.internal:8081/;
      proxy_redirect off;
    }
  }
}

下記に通信できる様になっていればok
https://sampleApp.com
https://api.sampleApp.com

まとめ

  • mkcertを使うと簡単に実装できました。今回は個人の学習のためのアプローチでしたが、実際に実務でやる分にはどのように対応するのがベターなのか気になります。

Discussion

shigeshige

docker composeを利用しているなら以下の書き方でいけるっぽい

version: 'x.x'
services:
    api:
    # 省略
        networks:
            defaults:
                aliases:
                    - ドメイン名

hostsファイルいじる必要なかった。。。