From 8737184cbcd7e0665f6bb92b64c45d5a38d4d0b0 Mon Sep 17 00:00:00 2001 From: Hasnat Date: Sun, 23 Jun 2019 14:22:16 +0100 Subject: [PATCH 1/4] Container env SERVER_PASS -> proxy_pass line Adds a container env variable `SERVER_PASS` to replace the `proxy_pass` line e.g. ``` SERVER_PASS='proxy_pass http://container_name:8080' SERVER_PASS='fastcgi_pass fastcgi://container_name:8080' SERVER_PASS='grpc_pass grpc://container_name:8080' ``` Note: This is not using upstream_name --- nginx.tmpl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nginx.tmpl b/nginx.tmpl index a9fc47962..0b71745f2 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -172,6 +172,9 @@ upstream {{ $upstream_name }} { {{/* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}} {{ $vhost_root := or (first (groupByKeys $containers "Env.VIRTUAL_ROOT")) "/var/www/public" }} +{{/* Get the SERVER_PASS By containers e.g. proxy_pass..., grpc_pass..., fastcgi_pass... */}} +{{ $server_pass := or ($container.Env.SERVER_PASS) "" }} + {{/* Get the first cert name defined by containers w/ the same vhost */}} {{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }} @@ -273,7 +276,9 @@ server { {{ end }} location / { - {{ if eq $proto "uwsgi" }} + {{ if ne $server_pass "" }} + {{ $server_pass }}; + {{ else if eq $proto "uwsgi" }} include uwsgi_params; uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }}; {{ else if eq $proto "fastcgi" }} @@ -320,7 +325,9 @@ server { {{ end }} location / { - {{ if eq $proto "uwsgi" }} + {{ if ne $server_pass "" }} + {{ $server_pass }}; + {{ else if eq $proto "uwsgi" }} include uwsgi_params; uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }}; {{ else if eq $proto "fastcgi" }} @@ -359,3 +366,4 @@ server { {{ end }} {{ end }} + From 01a56b89947f5ddfd2102b8177362322d65f8ae3 Mon Sep 17 00:00:00 2001 From: Hasnat Ullah Date: Sat, 29 Jun 2019 12:47:49 +0100 Subject: [PATCH 2/4] Use container names instead of container IPs --- .gitignore | 1 + docker-compose-separate-containers.yml | 23 --------- docker-compose.override.yml | 6 +++ docker-compose.yml | 3 ++ nginx.tmpl | 70 ++++---------------------- 5 files changed, 21 insertions(+), 82 deletions(-) delete mode 100644 docker-compose-separate-containers.yml create mode 100644 docker-compose.override.yml diff --git a/.gitignore b/.gitignore index 5daab4f78..7378fa794 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/__pycache__/ **/.cache/ .idea/ +conf.d \ No newline at end of file diff --git a/docker-compose-separate-containers.yml b/docker-compose-separate-containers.yml deleted file mode 100644 index a4edb9414..000000000 --- a/docker-compose-separate-containers.yml +++ /dev/null @@ -1,23 +0,0 @@ -version: '2' -services: - nginx: - image: nginx - container_name: nginx - ports: - - "80:80" - volumes: - - /etc/nginx/conf.d - - dockergen: - image: jwilder/docker-gen - command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf - volumes_from: - - nginx - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl - - whoami: - image: jwilder/whoami - environment: - - VIRTUAL_HOST=whoami.local diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 000000000..6ea063298 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,6 @@ +version: '2' +services: + nginx: + build: . + volumes: + - ./conf.d:/etc/nginx/conf.d diff --git a/docker-compose.yml b/docker-compose.yml index b76f0c0bd..89e26f17f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,13 +2,16 @@ version: '2' services: nginx-proxy: image: jwilder/nginx-proxy + build: . container_name: nginx-proxy ports: - "80:80" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro + - ./conf.d:/etc/nginx/conf.d whoami: image: jwilder/whoami environment: - VIRTUAL_HOST=whoami.local + - VIRTUAL_PORT=8000 diff --git a/nginx.tmpl b/nginx.tmpl index a9fc47962..858d04472 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -1,27 +1,5 @@ {{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }} -{{ define "upstream" }} - {{ if .Address }} - {{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}} - {{ if and .Container.Node.ID .Address.HostPort }} - # {{ .Container.Node.Name }}/{{ .Container.Name }} - server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }}; - {{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}} - {{ else if .Network }} - # {{ .Container.Name }} - server {{ .Network.IP }}:{{ .Address.Port }}; - {{ end }} - {{ else if .Network }} - # {{ .Container.Name }} - {{ if .Network.IP }} - server {{ .Network.IP }} down; - {{ else }} - server 127.0.0.1 down; - {{ 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 { @@ -119,37 +97,7 @@ server { {{ $host := trim $host }} {{ $is_regexp := hasPrefix "~" $host }} -{{ $upstream_name := when $is_regexp (sha1 $host) $host }} - -# {{ $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 connected 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 }} - {{ else }} - # Cannot connect to network of this container - server 127.0.0.1 down; - {{ end }} - {{ end }} - {{ end }} -{{ end }} -} + {{ $default_host := or ($.Env.DEFAULT_HOST) "" }} {{ $default_server := index (dict $host "" $default_host "default_server") $host }} @@ -157,6 +105,8 @@ upstream {{ $upstream_name }} { {{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}} {{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }} +{{ $container_pass := (printf "%v:%v" (first (groupByKeys $containers "Name")) (trim (or (first (groupByKeys $containers "Env.VIRTUAL_PORT")) "80"))) }} + {{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}} {{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }} @@ -273,15 +223,16 @@ server { {{ end }} location / { + set $target {{ trim $container_pass }}; {{ if eq $proto "uwsgi" }} include uwsgi_params; - uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }}; + uwsgi_pass {{ trim $proto }}://$target; {{ else if eq $proto "fastcgi" }} root {{ trim $vhost_root }}; include fastcgi.conf; - fastcgi_pass {{ trim $upstream_name }}; + fastcgi_pass $target; {{ else }} - proxy_pass {{ trim $proto }}://{{ trim $upstream_name }}; + proxy_pass {{ trim $proto }}://$target; {{ end }} {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }} @@ -320,15 +271,16 @@ server { {{ end }} location / { + set $target {{ trim $container_pass }}; {{ if eq $proto "uwsgi" }} include uwsgi_params; - uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }}; + uwsgi_pass {{ trim $proto }}://$target; {{ else if eq $proto "fastcgi" }} root {{ trim $vhost_root }}; include fastcgi.conf; - fastcgi_pass {{ trim $upstream_name }}; + fastcgi_pass $target; {{ else }} - proxy_pass {{ trim $proto }}://{{ trim $upstream_name }}; + proxy_pass {{ trim $proto }}://$target; {{ end }} {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }} auth_basic "Restricted {{ $host }}"; From cd9771a7497e492520b8a0274993c52d1f3612b7 Mon Sep 17 00:00:00 2001 From: Hasnat Ullah Date: Sat, 6 Jul 2019 15:39:50 +0100 Subject: [PATCH 3/4] Add default ttl for dns resolver --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 45a09e3f8..fb0a0f292 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,7 @@ COPY . /app/ WORKDIR /app/ ENV DOCKER_HOST unix:///tmp/docker.sock +ENV RESOLVERS="127.0.0.11 valid=5s" VOLUME ["/etc/nginx/certs", "/etc/nginx/dhparam"] From 1f9c34c12dcb16d7b0aef2f87fc8c204313cdb7c Mon Sep 17 00:00:00 2001 From: Hasnat Ullah Date: Mon, 29 Jul 2019 20:38:52 +0100 Subject: [PATCH 4/4] Add htpasswd and custom vhost.d configs via env vars --- Dockerfile | 1 + Dockerfile.alpine | 1 + Procfile | 1 + README.md | 14 ++++++++++++++ htpasswd_generator.tmpl | 16 ++++++++++++++++ nginx.tmpl | 18 ++++++++++++++++++ 6 files changed, 51 insertions(+) create mode 100644 htpasswd_generator.tmpl diff --git a/Dockerfile b/Dockerfile index 45a09e3f8..dde9ab5f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,7 @@ COPY network_internal.conf /etc/nginx/ COPY . /app/ WORKDIR /app/ +RUN touch /app/htpasswd_generator.sh && chmod +x /app/htpasswd_generator.sh ENV DOCKER_HOST unix:///tmp/docker.sock diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 23459a36e..fa3577b6e 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -25,6 +25,7 @@ COPY network_internal.conf /etc/nginx/ COPY . /app/ WORKDIR /app/ +RUN touch /app/htpasswd_generator.sh && chmod +x /app/htpasswd_generator.sh ENV DOCKER_HOST unix:///tmp/docker.sock diff --git a/Procfile b/Procfile index 29fe16627..dad20bdfb 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,3 @@ +htpasswdgen: docker-gen -watch -notify "/app/htpasswd_generator.sh" /app/htpasswd_generator.tmpl /app/htpasswd_generator.sh dockergen: docker-gen -watch -notify "nginx -s reload" /app/nginx.tmpl /etc/nginx/conf.d/default.conf nginx: nginx diff --git a/README.md b/README.md index f27c46745..b4f6585dc 100644 --- a/README.md +++ b/README.md @@ -313,7 +313,17 @@ $ docker run -d -p 80:80 -p 443:443 \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ jwilder/nginx-proxy ``` +Or have your container with `VHOST_HTPASSWD` +``` +$ docker run -d -p 80:80 -p 443:443 \ + -v /var/run/docker.sock:/tmp/docker.sock:ro \ + jwilder/nginx-proxy +$ docker run -d \ + -e VIRTUAL_HOST=whoami.local \ + -e VHOST_HTPASSWD='abc:900150983CD24FB0D6963F7D28E17F72' `# this is abc:abc using md5` \ + jwilder/whoami +``` You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html) ### Custom Nginx Configuration @@ -385,6 +395,8 @@ If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=e If you want most of your virtual hosts to use a default single configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default` file. This file will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}` file associated with it. +You can also have `VHOST_CONF` environment variable in your container. + #### Per-VIRTUAL_HOST location configuration To add settings to the "location" block on a per-`VIRTUAL_HOST` basis, add your configuration file under `/etc/nginx/vhost.d` @@ -405,6 +417,8 @@ If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=e If you want most of your virtual hosts to use a default single `location` block configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default_location` file. This file will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}_location` file associated with it. +You can also have `VHOST_LOCATION_CONF` environment variable in your container. + ### Contributing Before submitting pull requests or issues, please check github to make sure an existing issue or pull request is not already open. diff --git a/htpasswd_generator.tmpl b/htpasswd_generator.tmpl new file mode 100644 index 000000000..b8cf08c18 --- /dev/null +++ b/htpasswd_generator.tmpl @@ -0,0 +1,16 @@ +#!/bin/sh + +mkdir -p /etc/nginx/htpasswd +{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }} + +{{ $host := trim $host }} + +{{ $htpasswd := or (first (groupByKeys $containers "Env.VHOST_HTPASSWD")) "" }} + +if [ ! -z '{{$htpasswd}}' ] +then + echo '{{ $htpasswd }}' > /etc/nginx/htpasswd/{{ $host }} +fi + +{{ end }} +nginx -s reload \ No newline at end of file diff --git a/nginx.tmpl b/nginx.tmpl index a9fc47962..a3712768e 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -157,6 +157,10 @@ upstream {{ $upstream_name }} { {{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}} {{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }} +{{ $vhost_conf := trim (or (first (groupByKeys $containers "Env.VHOST_CONF")) "") }} + +{{ $vhost_location_conf := trim (or (first (groupByKeys $containers "Env.VHOST_LOCATION_CONF")) "") }} + {{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}} {{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }} @@ -272,6 +276,10 @@ server { include /etc/nginx/vhost.d/default; {{ end }} + {{ if not (eq $vhost_conf "") }} + {{ $vhost_conf }} + {{ end }} + location / { {{ if eq $proto "uwsgi" }} include uwsgi_params; @@ -293,6 +301,9 @@ server { {{ else if (exists "/etc/nginx/vhost.d/default_location") }} include /etc/nginx/vhost.d/default_location; {{ end }} + {{ if not (eq $vhost_location_conf "") }} + {{ $vhost_location_conf }} + {{ end }} } } @@ -319,6 +330,10 @@ server { include /etc/nginx/vhost.d/default; {{ end }} + {{ if not (eq $vhost_conf "") }} + {{ $vhost_conf }} + {{ end }} + location / { {{ if eq $proto "uwsgi" }} include uwsgi_params; @@ -339,6 +354,9 @@ server { {{ else if (exists "/etc/nginx/vhost.d/default_location") }} include /etc/nginx/vhost.d/default_location; {{ end }} + {{ if not (eq $vhost_location_conf "") }} + {{ $vhost_location_conf }} + {{ end }} } }