開発合宿の準備をしていて今日のバドミントン練習はお休み。

nginx のリバースプロキシ

compose に起動している2つのサービスを同じポート番号で共有したい。nginx を tls 終端にしていてリバースプロキシとして構築している。ルーティングするには2つの方法がある。次のような compose.yml を作ってローカルのファイルシステムをマウントして設定変更しながら検証する。

services:
  proxy:
    container_name: proxy
    image: docker.io/library/nginx:stable
    ports:
      - 8443:8443
    network_mode: "host"
    restart: unless-stopped
    volumes:
      - ./nginx:/etc/nginx

sub-domain based routing

クラウドでは普通のやり方がサブドメインのホスト名でルーティングを行う。設定もシンプルでファイルも管理しやすいように分割できてよいと思える。システム変更時の移行も名前を切り替えればよいので移行しやすい。

  • nginx.conf
http {
    sendfile on;

    upstream web-api1 {
        server localhost:8801;
    }

    upstream web-api2 {
        server localhost:8802;
    }

    ssl_certificate /etc/nginx/ssl/sample.crt;
    ssl_certificate_key /etc/nginx/ssl/sample.key;

    include /etc/nginx/sites-enabled/*;
}
  • nginx/sites-enabled/www.sub1.example.com
server {
    listen 8443 ssl;
    server_name sub1.example.com;
    location / {
        include     /etc/nginx/common_proxy.conf;
        proxy_pass  http://web-api1;
    }
}

path based routing

サブドメインの方が私は好みではあるが、サブドメインをネームサーバーに登録したり、tls の証明書にも複数ホストの考慮が必要になってくる。パスでルーティングするなら1台のマシンのように仮想的にみせられるというメリットはある。

http {
    sendfile on;

    upstream web-api1 {
        server localhost:8801;
    }

    upstream web-api2 {
        server localhost:8802;
    }

    ssl_certificate /etc/nginx/ssl/sample.crt;
    ssl_certificate_key /etc/nginx/ssl/sample.key;

    server {
        listen 8443 ssl;

        location /app1/ {
            include     /etc/nginx/common_proxy.conf;
            proxy_pass  http://web-api1;
        }

        location /app2/ {
            include     /etc/nginx/common_proxy.conf;
            proxy_pass  http://web-api2;
        }
    }
}

コンテナの capability

docker compose を rootless mode で使っていて 443 ポートを使いたいと言われてどうしたらいいのだろう?といままで考えていないことに気付いた。調べたらすぐにやり方が書いてあった。

$ sudo setcap cap_net_bind_service=ep $(which rootlesskit)
$ systemctl --user restart docker

これだけで compose サービスの1つにポート設定できた。めちゃ簡単だった。いままで capability を設定したことがなかったのと、権限周りはややこしいという先入観もあって触る機会がなかった。いろいろ洗練されて抽象化されているのだと推測する。バックエンドの場合は任意のポート番号を使えばよいから capability の設定をして 1024 以下のポート番号を使わないといけない理由はあまりない気はするが、そういう設定もできるようにはみえる。そういう話題すら聞いたことがなかった。