DockerでnginxでwebSocket

#DockerでnginxでwebSocket

dockerのnginx環境でwebSocket接続しようと思ったときハマったので共有します。
同じ悩みの方のヒントになれば幸いです。
なおここでは後述でのdocker-composeの使い方については省略します。
## 前準備
1. dockerhubから通常インストール
https://hub.docker.com/_/nginx/

2. nginxのdefault.confを作成
下記内容をコンテナ側ではなく親の方にファイル名mysite.templateで保存し、後述の方法でコンテナに読み込ませる

```
# For WebSocket

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    location /ws/ {
        proxy_pass http://(ws通信したいコンテナ名)/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
```

下記記述のところがwebSocket接続させるための記述

```
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
```

上記内容をファイル名mysite.templateで保存

## dockerでnginx環境を設定する（失敗例）

1. docker-compose.xmlで設定  
下記のような感じでmysite.templateをコンテナに読み込ませる感じで記述  

```
version: '2'
services:
    proxy:
        restart: always
        image: nginx
        container_name: nginx_proxy
        volumes:
         - ./mysite.template:/etc/nginx/conf.d/mysite.template
        ports:
         - "80:80"
        command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
```
environmentの記述のところでenvsubstコマンドを使ってテンプレートとして読み込ませる
2. docker-composeを実行

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

…とするとエラーで起動しない。。
3. コンテナ内のdefault.confを確認

```
docker exec -it nginx_proxy bash
```
(コンテナ内)

```
cat /etc/nginx/conf.d/default.conf
```
おそらく下記のような記述になっているはず

```
…（略）…
proxy_http_version 1.1;
        proxy_set_header Upgrade ;
        proxy_set_header Connection "upgrade";
…（略）…
```
（\$http_upgradeのところが消えてる。。）

と、ここにヒントが。
http://kiririmode.hatenablog.jp/entry/20150908/1441711463

単に\$...で記述するとテンプレート変数として扱われてしまうenvsubstの仕様ですね。
ということで、何らかのダミー変数を定義して渡せば\$...の記述もそのまま反映させることができそうです。

## dockerでnginx環境を設定する（成功例）
1. docker-compose.xmlで設定
下記のような感じでmysite.templateをコンテナに読み込ませる感じで記述 

```
version: '2'
services:
    proxy:
        restart: always
        image: nginx
        container_name: nginx_proxy
        volumes:
         - ./mysite.template:/etc/nginx/conf.d/mysite.template
        ports:
         - "80:80"
         environment:
         - DUMMY=dummy
        command: /bin/bash -c "envsubst '$$DUMMY' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
```
（変更点）

- environmentでダミー変数（DUMMY）を定義
- commandのenvsubstで定義した変数を渡す

2. docker-composeを実行

```
docker-compose up -d proxy
```
エラーなく実行できた！

あとは通常のwebSocket記述でクライアントから接続すれば応答するはずです。

## wssでの接続
wssの場合でも特殊な設定は不要です。通常のssl記述のところにwebSocket用記述を追加するだけです。

- docker-compose.xml

```
version: '2'
services:
    proxy:
        restart: always
        image: nginx
        container_name: nginx_proxy
        volumes:
         - ./mysite.template:/etc/nginx/conf.d/mysite.template
        ports:
         - "80:80"
         - "443:443"
        environment:
         - DUMMY=dummy
        command: /bin/bash -c "envsubst "envsubst '$$DUMMY' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
```

-mysite.template

```
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    ssl on;
    ssl_certificate （中間証明書のパス）/fullchain.pem;
    ssl_certificate_key （中間証明書のパス）/privkey.pem;

    server_name （ドメイン名）;

    location /ws/ {
        proxy_pass http://(wss通信したいコンテナ名)/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
```