Path-based routing
This commit is contained in:
commit
3b71bf0a9f
2 changed files with 106 additions and 85 deletions
|
@ -81,6 +81,12 @@ If you need to support multiple virtual hosts for a container, you can separate
|
|||
|
||||
You can also use wildcards at the beginning and the end of host name, like `*.bar.com` or `foo.bar.*`. Or even a regular expression, which can be very useful in conjunction with a wildcard DNS service like [xip.io](http://xip.io), using `~^foo\.bar\..*\.xip\.io` will match `foo.bar.127.0.0.1.xip.io`, `foo.bar.10.0.2.2.xip.io` and all other given IPs. More information about this topic can be found in the nginx documentation about [`server_names`](http://nginx.org/en/docs/http/server_names.html).
|
||||
|
||||
### Path-based Routing
|
||||
|
||||
You can have multiple containers proxied by the same `VIRTUAL_HOST` by adding a `VIRTUAL_PATH` environment variable containing the absolute path to where the container should be mounted. For example with `VIRTUAL_HOST=foo.example.com` and `VIRTUAL_PATH=/api/v2/service`, then requests to http://foo.example.com/api/v2/service will be routed to the container. If you wish to have a container serve the root while other containers serve other paths, make give the root container a `VIRTUAL_PATH` of `/`. Unmatched paths will be served by the container at `/` or will return the default nginx error page if no container has been assigned `/`.
|
||||
|
||||
The full request URI will be forwarded to the serving container in the `X-Forwarded-Path` header.
|
||||
|
||||
### Multiple Networks
|
||||
|
||||
With the addition of [overlay networking](https://docs.docker.com/engine/userguide/networking/get-started-overlay/) in Docker 1.9, your `nginx-proxy` container may need to connect to backend containers on multiple networks. By default, if you don't pass the `--net` flag when your `nginx-proxy` container is created, it will only be attached to the default `bridge` network. This means that it will not be able to connect to containers on networks other than `bridge`.
|
||||
|
@ -323,6 +329,7 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|||
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
||||
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
|
||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
||||
proxy_set_header X-Forwarded-Path $request_uri;
|
||||
|
||||
# Mitigate httpoxy attack (see README for details)
|
||||
proxy_set_header Proxy "";
|
||||
|
|
138
nginx.tmpl
138
nginx.tmpl
|
@ -17,6 +17,59 @@
|
|||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "location" }}
|
||||
location {{ .Path }} {
|
||||
{{ if eq .Proto "uwsgi" }}
|
||||
include uwsgi_params;
|
||||
uwsgi_pass {{ trim .Proto }}://{{ trim .Upstream }};
|
||||
{{ else if eq (trim .Proto) "fastcgi" }}
|
||||
root {{ trim .VHostRoot }};
|
||||
include fastcgi.conf;
|
||||
fastcgi_pass {{ trim .Upstream }};
|
||||
{{ else }}
|
||||
proxy_pass {{ trim .Proto }}://{{ trim .Upstream }}/;
|
||||
{{ end }}
|
||||
|
||||
{{ if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }}
|
||||
auth_basic "Restricted {{ .Host }}";
|
||||
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" .Host) }};
|
||||
{{ end }}
|
||||
|
||||
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }}
|
||||
include {{ printf "/etc/nginx/vhost.d/%s_location" .Host}};
|
||||
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
||||
include /etc/nginx/vhost.d/default_location;
|
||||
{{ end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ define "upstream-definition" }}
|
||||
upstream {{ .Upstream }} {
|
||||
{{ range $container := .Containers }}
|
||||
{{ $addrLen := len $container.Addresses }}
|
||||
{{ $networks := .Networks }}
|
||||
{{ range $knownNetwork := $networks }}
|
||||
{{ range $containerNetwork := $container.Networks }}
|
||||
{{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }}
|
||||
## Can be connect with "{{ $containerNetwork.Name }}" network
|
||||
|
||||
{{/* If only 1 port exposed, use that */}}
|
||||
{{ if eq $addrLen 1 }}
|
||||
{{ $address := index $container.Addresses 0 }}
|
||||
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
||||
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
|
||||
{{ else }}
|
||||
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
|
||||
{{ $address := where $container.Addresses "Port" $port | first }}
|
||||
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
|
||||
# scheme used to connect to this server
|
||||
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
|
||||
|
@ -59,6 +112,7 @@ log_format vhost '$host $remote_addr - $remote_user [$time_local] '
|
|||
'"$http_referer" "$http_user_agent"';
|
||||
|
||||
access_log off;
|
||||
error_log /dev/stderr;
|
||||
|
||||
{{ if $.Env.RESOLVERS }}
|
||||
resolver {{ $.Env.RESOLVERS }};
|
||||
|
@ -78,6 +132,7 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|||
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
||||
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
|
||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
||||
proxy_set_header X-Forwarded-Path $request_uri;
|
||||
|
||||
# Mitigate httpoxy attack (see README for details)
|
||||
proxy_set_header Proxy "";
|
||||
|
@ -112,36 +167,20 @@ server {
|
|||
|
||||
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
|
||||
|
||||
{{ $host := trim $host }}
|
||||
{{ $is_regexp := hasPrefix "~" $host }}
|
||||
{{ $upstream_name := when $is_regexp (sha1 $host) $host }}
|
||||
{{ $paths := groupBy $containers "Env.VIRTUAL_PATH" }}
|
||||
{{ $nPaths := len $paths }}
|
||||
|
||||
{{ if eq $nPaths 0 }}
|
||||
# {{ $host }}
|
||||
upstream {{ $upstream_name }} {
|
||||
|
||||
{{ range $container := $containers }}
|
||||
{{ $addrLen := len $container.Addresses }}
|
||||
|
||||
{{ range $knownNetwork := $CurrentContainer.Networks }}
|
||||
{{ range $containerNetwork := $container.Networks }}
|
||||
{{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }}
|
||||
## Can be connect with "{{ $containerNetwork.Name }}" network
|
||||
|
||||
{{/* If only 1 port exposed, use that */}}
|
||||
{{ if eq $addrLen 1 }}
|
||||
{{ $address := index $container.Addresses 0 }}
|
||||
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
||||
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
|
||||
{{ template "upstream-definition" (dict "Upstream" $host "Containers" $containers "Networks" (json $CurrentContainer.Networks)) }}
|
||||
{{ else }}
|
||||
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
|
||||
{{ $address := where $container.Addresses "Port" $port | first }}
|
||||
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
||||
{{ range $path, $containers := $paths }}
|
||||
{{ $sum := sha1 $path }}
|
||||
{{ $upstream := printf "%s-%s" $host $sum }}
|
||||
# {{ $host }}{{ $path }}
|
||||
{{ template "upstream-definition" (dict "Upstream" $upstream "Containers" $containers "Networks" $CurrentContainer.Networks) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
|
||||
{{ $default_server := index (dict $host "" $default_host "default_server") $host }}
|
||||
|
@ -267,28 +306,15 @@ server {
|
|||
include /etc/nginx/vhost.d/default;
|
||||
{{ end }}
|
||||
|
||||
location / {
|
||||
{{ if eq $proto "uwsgi" }}
|
||||
include uwsgi_params;
|
||||
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||
{{ else if eq $proto "fastcgi" }}
|
||||
root {{ trim $vhost_root }};
|
||||
include fastcgi.conf;
|
||||
fastcgi_pass {{ trim $upstream_name }};
|
||||
{{ if eq $nPaths 0 }}
|
||||
{{ template "location" (dict "Path" "/" "Proto" $proto "Upstream" $host "Host" $host "VHostRoot" $vhost_root) }}
|
||||
{{ else }}
|
||||
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||
{{ range $path, $containers := $paths }}
|
||||
{{ $sum := sha1 $path }}
|
||||
{{ $upstream := printf "%s-%s" $host $sum }}
|
||||
{{ template "location" (dict "Path" $path "Proto" $proto "Upstream" $upstream "Host" $host "VHostRoot" $vhost_root) }}
|
||||
{{ end }}
|
||||
|
||||
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
||||
auth_basic "Restricted {{ $host }}";
|
||||
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
|
||||
{{ end }}
|
||||
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
|
||||
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
|
||||
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
||||
include /etc/nginx/vhost.d/default_location;
|
||||
{{ end }}
|
||||
}
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
|
@ -314,27 +340,15 @@ server {
|
|||
include /etc/nginx/vhost.d/default;
|
||||
{{ end }}
|
||||
|
||||
location / {
|
||||
{{ if eq $proto "uwsgi" }}
|
||||
include uwsgi_params;
|
||||
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||
{{ else if eq $proto "fastcgi" }}
|
||||
root {{ trim $vhost_root }};
|
||||
include fastcgi.conf;
|
||||
fastcgi_pass {{ trim $upstream_name }};
|
||||
{{ if eq $nPaths 0 }}
|
||||
{{ template "location" (dict "Path" "/" "Proto" $proto "Upstream" $host "Host" $host "VHostRoot" $vhost_root) }}
|
||||
{{ else }}
|
||||
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
||||
{{ range $path, $containers := $paths }}
|
||||
{{ $sum := sha1 $path }}
|
||||
{{ $upstream := printf "%s-%s" $host $sum }}
|
||||
{{ template "location" (dict "Path" $path "Proto" $proto "Upstream" $upstream "Host" $host "VHostRoot" $vhost_root) }}
|
||||
{{ end }}
|
||||
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
||||
auth_basic "Restricted {{ $host }}";
|
||||
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
|
||||
{{ end }}
|
||||
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
|
||||
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
|
||||
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
||||
include /etc/nginx/vhost.d/default_location;
|
||||
{{ end }}
|
||||
}
|
||||
}
|
||||
|
||||
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
||||
|
|
Loading…
Reference in a new issue