#DockerでnginxでwebSocket
dockerのnginx環境でwebSocket接続しようと思ったときハマったので共有します。
同じ悩みの方のヒントになれば幸いです。
なおここでは後述でのdocker-composeの使い方については省略します。
前準備
-
dockerhubから通常インストール
https://hub.docker.com/_/nginx/ -
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環境を設定する(失敗例)
- 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環境を設定する(成功例)
- 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で定義した変数を渡す
- 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";
}