Help us understand the problem. What is going on with this article?

NginxでリクエストをLXCコンテナに振り分ける

More than 5 years have passed since last update.

やりたいこと

  • blog.abcang.netabcang.net宛のリクエストをwebコンテナに転送
  • blog.abcang.netabcang.netでそれぞれ別のページが表示される
  • app.abcang.net宛のリクエストをappコンテナに転送
  • 登録されていないサブドメインでのアクセスはabcang.netに転送
  • コンテナを増やすたびに設定ファイルを追加したくない

やったこと

以下のように設定ファイルを編集する。
各コンテナは普段通りの設定をすればいい。

/etc/nginx/conf.d/default.conf
map $http_host $cname {
    hostnames;
    abcang.net          web;
    blog.abcang.net     web;
    app.abcang.net      app;
    default             0;
}

server {
    listen       80 default_server;
    server_name  abcang.net;

    # 登録されていないホストはリダイレクト                            
    if ($cname = 0) {
        rewrite ^ http://abcang.net$request_uri? last;
    }

    # 内部DNSで名前解決して転送                                       
    location / {
        resolver dns.abcang.net valid=3600s;
        proxy_pass http://$cname;
        # 接続元情報を維持                                            
        proxy_set_header Host            $host;
        proxy_set_header X-Real-IP       $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_max_temp_file_size 0;

        # Websocket                                                   
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
    }
}

説明

ドメインからコンテナを指定

map $http_host $cname {
    hostnames;
    abcang.net          web;
    blog.abcang.net     web;
    app.abcang.net      app;
    default             0;
}

左にアクセス元のドメインを、右にコンテナの名前を書いていく。
新しくコンテナを追加した場合はこの部分を増やせば良い。
defaultは一致しなかったものがマッチして、0が設定されるようにしている。

登録されていないホストはリダイレクト

    # 登録されていないホストはリダイレクト                            
    if ($cname = 0) {
        rewrite ^ http://abcang.net$request_uri? last;
    }

先のmapでの設定で、登録されていない場合は$cname0になることがわかる。
それを検知したらrewriteでリダイレクトするようにしている。
lastをつけるとそこで処理を停止してくれるらしい。

各コンテナに転送

    # 内部DNSで名前解決して転送                                       
    location / {
        resolver dns.abcang.net valid=3600s;
        proxy_pass http://$cname;
        # 接続元情報を維持                                            
        proxy_set_header Host            $host;
        proxy_set_header X-Real-IP       $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_max_temp_file_size 0;

        # Websocket                                                   
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
    }

resolverの部分で内部DNS(LXCで使用されているもの)を指定する。
validをつけると再度DNSに問い合わせる時間を指定できるみたい。
proxy_passで転送先を指定しているが、ドメイン部分を変数にしておかないとnginx起動時以降名前解決してくれないらしい。
後は接続元の情報をヘッダに付けてあげたり、WebSocketも使えるようにしてあげたり。

参考

abcang
JavaScriptとかRubyとかがすきです
https://abcang.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away