雑にDockerでSSL対応NginxでNode-REDをproxyする方法

## 概要

SSL 対応にした Nginx を proxy とし、Node-RED をブラウザからアクセスするための手順です。Node-RED は標準では SSL 通信に対応していません。Nginx の SSL 設定に  Let's Encrypt の証明書を使い、Docker 環境を使って雑に設定する方法をまとめました。

ここでは Node-Red を対象にしていますが、様々なアプリケーションに活用できると思います。適時置き換えてご利用ください。

### 動機

Mastodonのdocker-compose.yamlに、このnginxとcertbotの設定を組み込みたい。

## 方向性

- Node-RED のポート 1881 はオープンにしない（Nginx <-> NodeRED 間は内部ネットワークで通信）
- ボリューム `certbot` で SSL 証明書を管理（証明書等をコンテナ間で共有するため）
- docker を使う

## 事前に必要なもの

- 対象サーバがインターネットからアクセス可能なホスト名（ A レコードなど）設定
- Docker CE / Docker Compose （オプション）

## 手順

### Docker のセットアップ（オプション）

```
# curl -sSL https://get.docker.com/ | sh
# systemctl start docker
# systemctl enable docker
```

### Docker Compose のセットアップ

```
# curl -L https://github.com/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
```

### 設定ファイルの取得

そして、GItHub からファイル群を取得するか、git が使えない場合は[リポジトリ](https://github.com/zembutsu/nginx-ssl)から直接取得ください。

```
$ git pull https://github.com/zembutsu/nginx-ssl.git
$ cd nginx-ssl
```


ファイル `nginx-default.conf` を開き、 `<MY_HOST_NAME>` を対象サーバのホスト名（例： `node.example.jp`）に変更（5箇所）します。

### SSL 証明書の作成

それから、Let's encrypt の証明書を発行します。まずはドライ・ランが正常に走るかどうかを確認します。

```
# docker container run -it --rm -v certbot:/etc/letsencrypt \
    -v /var/log/letsencrypt:/var/log/letsencrypt \
    -p 443:443 \
    certbot/certbot \
     certonly --standalone --agree-tos --dry-run -n \
    -d <ここをホスト名> --email <通知用のメールアドレス>
```

特にエラーがなければ、実際に証明書を作成します。

```
# docker container run -it --rm -v certbot:/etc/letsencrypt \
    -v /var/log/letsencrypt:/var/log/letsencrypt \
    -p 443:443 \
    certbot/certbot \
     certonly --standalone --agree-tos -n \
    -d <ここをホスト名> --email <通知用のメールアドレス>
```

次に openssl 用イメージを作成します。

```
# docker image build -t myopenssl - < ./Dockerfile.openssl
```

ここで作成したイメージは `openssl` コマンドを実行するだけの小さなものです。

``` Dockerfile.openssl
FROM alpine:latest
RUN apk update && apk add openssl
```

次に鍵交換用のパラメータ・ファイル `hdparam.pem` を作成します（数分かかります）。

```
$ docker container run -it --rm -v certbot:/certbot myopenssl openssl dhparam -out  /certbot/dhparam.pem 2048
```


### イメージのビルド

Docker Compose を使い、Node-RED や Nginx イメージの取得などを行います。

```
$ docker-compose build
```

### 起動

```
docker-compose up -d
```

### 動作確認

```
# docker-compose ps
        Name                   Command                  State                   Ports
---------------------------------------------------------------------------------------------
nginxssl_nginx_1        nginx -g daemon off;    Up                      0.0.0.0:443->443/tcp,
                                                                        0.0.0.0:80->80/tcp
nginxssl_node-red_1     npm start --            Up                      1880/tcp
                        --userDir /data
```

このように`Up`状態であれば問題ありません。

あとはブラウザから `http://<ホスト名>`  にアクセスするだけです。SSL で保護された状態として使えます。

![node-red.png](https://qiita-image-store.s3.amazonaws.com/0/13002/5d2571fa-5990-e4d5-e105-ec1dcd70e40d.png)



### 停止

```
$ docker-compose stop
```

### 削除

```
$ docker-compose down
```

このコマンドを実行しても証明書用のデータはボリューム `certbot` 残り続けます。
ボリュームを消すには `docker volume rm certbot` を実行します。


## 後日の課題(todo)

- 証明書作成手順のスクリプト化（もっと簡単になるはず）
- 証明書の定期的な更新(renew)方法（あとでまとめる予定）