Docker × Laravel ローカル環境でHTTPS(SSL)通信する

ローカル環境でもHTTPS通信したいという要望があり、ちょうど最近仕事でやる機会があったのでQiitaにもまとめたいと思います。

## 環境

- Mac

## Laravel環境

- https://github.com/ucan-lab/docker-laravel
  - v.2.1.0
- [最強のLaravel開発環境をDockerを使って構築する【新編集版】](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)

```shell-session
$ git clone git@github.com:ucan-lab/docker-laravel.git
$ cd docker-laravel

$ mkdir -p src
$ docker compose up -d
$ docker compose exec app composer create-project --prefer-dist laravel/laravel .
$ docker compose exec app php artisan key:generate
$ docker compose exec app php artisan storage:link
$ docker compose exec app chmod -R 777 storage bootstrap/cache
$ docker compose exec app php artisan migrate
```

http://localhost

![ScreenShot 2021-01-16 15.24.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/cb340216-b94a-2784-b9fe-e5197c61b346.png)

## 認証局、鍵の準備

### mkcert, nssのインストール

- https://github.com/FiloSottile/mkcert
  - ローカルで信頼できる開発証明書を作成するためのツール
- https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS
  - Network Security Services
  - FirefoxでlocalhostのSSLを有効化するために必要

```shell-session
$ brew install mkcert nss
```

### ローカル認証局(CA： Certification Authority)の作成

```shell-session
$ mkcert -install
```

ChromeのSSL警告をlocalhostの時だけ表示しないようにする。
`chrome://flags/#allow-insecure-localhost` アドレスバーに入力する。

![ScreenShot 2021-01-16 14.56.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/395c63b6-2ef8-5362-73fe-d5a6cf9bc17a.png)

`DISABLED` => `ENABLED` に変更してブラウザを再起動する。

## 秘密鍵、公開鍵の作成

コマンドの実行は `docker-laravel` ディレクトリルートで行ってください。

```shell-session
$ mkcert -cert-file ./infra/docker/nginx/localhost.pem -key-file ./infra/docker/nginx/localhost-key.pem localhost
```

Gitで管理しないように `.gitignore` ファイルを作ります。

```
$ echo '*.pem' >> ./infra/docker/nginx/.gitignore
```

## Dockerのコード書き換え

### docker-compose.yml

公開ポートを`80`から`443`へ変更する。
HTTPSは、ウェルノウンポート番号として`443`が使われるのが一般的です。
ローカルでは他のコンテナと被らない番号であれば何でも良いです。

- https://ja.wikipedia.org/wiki/HTTPS

```yaml:docker-compose.yml
services:
  web:
    ports:
      - target: 443
        published: ${WEB_PUBLISHED_PORT:-443}
        protocol: tcp
        mode: host
```

### infra/docker/nginx/default.conf

下記のコードを追記する。

- http://nginx.org/en/docs/http/configuring_https_servers.html

```infra/docker/nginx/default.conf
server {
    # listen 80;
    # listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name localhost;
    ssl_certificate /etc/nginx/conf.d/localhost.pem; # サーバ証明書
    ssl_certificate_key /etc/nginx/conf.d/localhost-key.pem; # 秘密鍵

    # ... 省略
}
```

### infra/docker/nginx/Dockerfile

下記のコードを追記する。

```Dockerfile:infra/docker/nginx/Dockerfile
COPY ./infra/docker/nginx/*.pem /etc/nginx/conf.d/
```

- 秘密鍵、公開鍵をコピーしてます。

## Dockerイメージの作成、コンテナ再生成

コマンドの実行は `docker-laravel` ディレクトリルートで行ってください。

```
$ docker compose down
$ docker compose build web
$ docker compose up -d
```

https://localhost

![ScreenShot 2021-01-16 14.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/74824e35-8a0f-447d-3de4-2fbf085765a4.png)

![ScreenShot 2021-01-16 14.54.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/4924f1a4-d50f-9b8d-81d4-a9ca27e1d510.png)

このようにSSL証明書が有効化されていればokです。