docker-composeを使ってnginxのリバースプロキシを設置する
nginxのdocker imageをSSL証明書を自動更新しながら使う。
サーバーを引っ越した話で最初に使ったイメージが悪かったので置き換えた
Table of Contents
最初のDocker image
サーバー移転した時にはNeilpang/nginx-proxyをforkしたkPherox/autocert-nginx-proxyを使ってた。fork元ではjwilder/nginx-proxyのfork(Neilpang/nginx-proxy-base)でnginxバージョンをlatestにする変更があったのだけれどimageを定期的に作り直してなく、むしろメンテされてるfork元の方が新しいnginxを利用するようになっていたのでjwilder/nginx-proxyを直接使うような変更を加えていた
しかし証明書の期限まで1ヶ月になった今月、問題が発生した
このimageで利用しているacme.shは/etc/nginx/conf.d
にある設定のバックアップを取ってlocation ^~ /.well-known/acme-challenge/<filename>
の設定を追加するようになっているためconf.d
ではなくvhost.d
をserverディレクティブで読み込んでいるこのimageではそれが追加されたところで全く意味がない
結局Invalid responseで証明書の更新がうまくいかないので別の方法を探すかどうにかimageを修正しなければいけない必要が出てきた
一度docker-compose v3で使うことを諦めてた方法
docker-composeはdocker --volumes-from
と同様のプロパティをv3になって廃止した。そのため、JrCs/docker-letsencrypt-nginx-proxy-companionのような--volumes-from
に依存する設計だと素直に使えないしdocker-composeの問題ということになって閉じられてるIssueまであった1
ただこちらは継続的にメンテされており先に使っていたものと違って正しく動くことが期待できるため、どうにか使う方法はないかとIssueを探すことにした
docker-compose v3で廃止されたvolumes_from
に相当する設定
とにかくvolumes_fromと同じことをしなくてはいけない。Docker公式のドキュメントにはnamed volumesを設定するといいとある2ので適当にvolumesを設定してみることにした
version: '3.5'
services:
nginx-proxy:
image: jwilder/nginx-proxy:alpine
network_mode: host
ports:
- "443:443"
- "80:80"
environment:
- ENABLE_IPV6=true
- VIRTUAL_HOST=kpherox.dev,www.kpherox.dev
- LETSENCRYPT_HOST=kpherox.dev,www.kpherox.dev
volumes:
- doc_root:/var/www
- html:/usr/share/nginx/html
- dhparam:/etc/nginx/dhparam
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
autocert:
image: jrcs/letsencrypt-nginx-proxy-companion:latest
environment:
- DEFAULT_EMAIL=admin@mail.kr-kp.com
- VIRTUAL_HOST=kpherox.dev,www.kpherox.dev
volumes:
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:rw
- vhost:/etc/nginx/vhost.d
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
doc_root:
driver_opts:
type: none
o: bind
device: /path/to/document_root
html:
driver_opts:
type: none
o: bind
device: /path/to/html
conf:
driver_opts:
type: none
o: bind
device: /path/to/conf.d
vhost:
driver_opts:
type: none
o: bind
device: /path/to/vhost.d
dhparam:
certs:
これでうまくいくかと思いきやautocertサービスがnginx-proxyを見つけられないようで解決しなかった。もう一度Issueを漁るとCompose V3 Compatibility - fix volume_fromで “This works for me” とリンクが貼られていた3
どうやらdepends_on
でnginx-proxy serviceを設定するといいらしい
https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/issues/102#issuecomment-463573796
なので最終的に以下の変更で動くようになった
--- old/compose.yml
+++ new/compose.yml
@@ -3,10 +3,8 @@
nginx-proxy:
image: jwilder/nginx-proxy:alpine
+ restart: always
network_mode: host
- ports:
- - "443:443"
- - "80:80"
environment:
- ENABLE_IPV6=true
- VIRTUAL_HOST=kpherox.dev,www.kpherox.dev
@@ -15,17 +13,22 @@
- doc_root:/var/www
- html:/usr/share/nginx/html
- dhparam:/etc/nginx/dhparam
- - conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
+ labels:
+ - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
autocert:
image: jrcs/letsencrypt-nginx-proxy-companion:latest
+ restart: always
+ depends_on:
+ - "nginx-proxy"
environment:
- DEFAULT_EMAIL=admin@mail.kr-kp.com
- VIRTUAL_HOST=kpherox.dev,www.kpherox.dev
volumes:
+ - doc_root:/var/www
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:rw
- vhost:/etc/nginx/vhost.d
@@ -42,11 +45,6 @@
type: none
o: bind
device: /path/to/html
- conf:
- driver_opts:
- type: none
- o: bind
- device: /path/to/conf.d
vhost:
driver_opts:
type: none
実際にはpleromaを別のdocker-composeで動かしてるのでnginx-proxy
をnetwork_mode: host
にしてconf.d
もnginx-proxy
のvolumesに追加してupstreamにpleromaを追加している。pleromaを更新する時にdockerのscaleを使ってコンテナを切り替えるようにしてるので複数のportへプロキシする必要があるためこうしている