initial commit

parents
### Miscellaneous
.Spotlight-V100
.Trashes
.DS_Store
.DS_Store?
ehthumbs.db
Thumbs.db
### Composer
composer.lock
/vendor/
### IDE
.idea/
*.cache
volumes/conf.d/*
### nginx-proxy
volumes/certs/*
!volumes/certs/.gitkeep
volumes/conf.d/*
!volumes/conf.d/.gitkeep
!volumes/conf.d/custom-params.conf
volumes/vhost.d/*
!volumes/vhost.d/.gitkeep
# Nginx proxy for Docker containers
Вдохновлено [pixelfordinner/pixelcloud-docker-apps](https://github.com/pixelfordinner/pixelcloud-docker-apps)
Простой Nginx прокси для Docker. Можно использовать для локальной разработки. Запускает контейнеры:
1. **[`nginx`](https://hub.docker.com/_/nginx/)** - Связывает порты 80 и 443 с хоста в контейнер, таким образом обрабатывает запросы, приходящие на хост.
1. **[`jwilder/docker-gen`](https://github.com/jwilder/docker-gen)** - Регенерирует конфиг для nginx при запуске/остановке контейнеров.
## Начало работы
1. Создать сеть `proxy` на хосте
```bash
docker network create proxy
```
1. Запустить эти контейнеры
```bash
docker-compose up -d
```
### Подключить проект к прокси
В конфиге проекта `docker-compose.yml` указать сеть `proxy`:
```yml
networks:
proxy:
external: true
```
Для контейнера с веб-сервером (nginx, apache) в переменные окружения указать:
- VIRTUAL_HOST=hostname
Можно указать несколько доменов через запятую.
Больше переменных окружения можно найти в документации к [`docker-gen`](https://github.com/jwilder/docker-gen)
Так же контейнеру с веб-сервером необходимо указать сети:
```yml
networks:
- default
- proxy-tier
```
`default` - чтобы для доступа к контейнерам в сети проекта
`proxy-tier` - для участия в прокси
## SSL на Localhost
В папке `volumes/certs` сгенерировать SSL ключ для нужного домена:
```bash
openssl req -x509 -newkey rsa:4096 -keyout demo.local.key -out demo.local.crt -days 365 -nodes -subj '/CN=demo.local'
```
Пересоздайте контейнер с приложением. После регенерации конфига, https будет настроен автоматически.
{{ $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 }}
server {{ .Network.IP }} down;
{{ 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 {
default $http_x_forwarded_proto;
'' $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
default upgrade;
'' close;
}
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
default off;
https on;
}
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log off;
{{ if (exists "/etc/nginx/proxy.conf") }}
include /etc/nginx/proxy.conf;
{{ else }}
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
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;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
{{ end }}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
listen 80 deferred;
listen [::]:80 deferred;
access_log /var/log/nginx/access.log vhost;
return 503;
}
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
listen 443 ssl http2 deferred;
listen [::]:443 ssl http2 deferred;
access_log /var/log/nginx/access.log vhost;
return 503;
include /etc/nginx/boilerplate/enable/ssl.conf;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
{{ end }}
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
{{ $upstream_name := sha1 $host }}
# {{ $host }}
upstream {{ $upstream_name }} {
{{ range $container := $containers }}
{{ $addrLen := len $container.Addresses }}
{{ range $knownNetwork := $CurrentContainer.Networks }}
{{ range $containerNetwork := $container.Networks }}
{{ if eq $knownNetwork.Name $containerNetwork.Name }}
## 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 }}
}
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
{{ $default_server := index (dict $host "" $default_host "default_server") $host }}
{{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
{{ $proto := or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http" }}
{{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
{{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
{{/* Get the first cert name defined by containers w/ the same vhost */}}
{{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }}
{{/* Get the best matching cert by name for the vhost. */}}
{{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}}
{{/* vhostCert is actually a filename so remove any suffixes since they are added later */}}
{{ $vhostCert := trimSuffix ".crt" $vhostCert }}
{{ $vhostCert := trimSuffix ".key" $vhostCert }}
{{/* Use the cert specified on the container or fallback to the best vhost match */}}
{{ $cert := (coalesce $certName $vhostCert) }}
{{/* Automatically redirect www domains */}}
{{ $www := or (first (groupByKeys $containers "Env.WWW")) "false" }}
{{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }}
{{ if $is_https }}
{{ if eq $https_method "redirect" }}
server {
server_name {{ $host }};
listen 80 {{ $default_server }};
listen [::]:80 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
return 301 https://$host$request_uri;
}
{{ end }}
server {
server_name {{ $host }};
listen 443 ssl http2 {{ $default_server }};
listen [::]:443 ssl http2 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }};
ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }};
{{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }}
ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $cert }};
{{ else if (exists ("/etc/nginx/certs/dhparam.pem")) }}
ssl_dhparam /etc/nginx/certs/dhparam.pem;
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ 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 (eq $www "no-www") }}
{{ if and (exists (printf "/etc/nginx/certs/www.%s.crt" $cert)) (exists (printf "/etc/nginx/certs/www.%s.key" $cert)) }}
server {
server_name www.{{ $host }};
listen 80 {{ $default_server }};
listen [::]:80 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
return 301 https://{{$host}}$request_uri;
}
server {
server_name www.{{ $host }};
listen 443 ssl http2 {{ $default_server }};
listen [::]:443 ssl http2 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
include /etc/nginx/boilerplate/enable/ssl.conf;
ssl_certificate /etc/nginx/certs/{{ (printf "www.%s.crt" $cert) }};
ssl_certificate_key /etc/nginx/certs/{{ (printf "www.%s.key" $cert) }};
{{ if (exists (printf "/etc/nginx/certs/www.%s.dhparam.pem" $cert)) }}
ssl_dhparam {{ printf "/etc/nginx/certs/www.%s.dhparam.pem" $cert }};
{{ else if (exists ("/etc/nginx/certs/dhparam.pem")) }}
ssl_dhparam /etc/nginx/certs/dhparam.pem;
{{ end }}
return 301 https://{{$host}}$request_uri;
}
{{ end }}
{{ else if (eq $www "www") }}
{{ $nowwwhost := replace $host "www." "" -1 }}
{{ $nowwwcert := replace $cert "www." "" -1 }}
{{ if and (exists (printf "/etc/nginx/certs/%s.crt" $nowwwcert)) (exists (printf "/etc/nginx/certs/%s.key" $nowwwcert)) }}
server {
server_name {{ $nowwwhost }};
listen 80 {{ $default_server }};
listen [::]:80 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
return 301 https://{{$host}}$request_uri;
}
server {
server_name {{ $nowwwhost }};
listen 443 ssl http2 {{ $default_server }};
listen [::]:443 ssl http2 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
include /etc/nginx/boilerplate/enable/ssl.conf;
ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $nowwwcert) }};
ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $nowwwcert) }};
{{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $nowwwcert)) }}
ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $nowwwcert }};
{{ else if (exists ("/etc/nginx/certs/dhparam.pem")) }}
ssl_dhparam /etc/nginx/certs/dhparam.pem;
{{ end }}
return 301 https://{{$host}}$request_uri;
}
{{ end }}
{{ end }}
{{ end }}
{{ if or (not $is_https) (eq $https_method "noredirect") }}
server {
server_name {{ $host }};
listen 80 {{ $default_server }};
listen [::]:80 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ 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 (eq $www "no-www") }}
server {
server_name www.{{ $host }};
listen 80 {{ $default_server }};
listen [::]:80 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
{{ if (exists (printf "/etc/nginx/vhost.d/www.%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/www.%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/www.%s" $host)) }}
auth_basic "Restricted {{ $host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/www.%s" $host) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/www.%s_location" $host)) }}
include {{ printf "/etc/nginx/vhost.d/www.%s_location" $host}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
}
{{ else if (eq $www "www") }}
{{ $nowwwhost := replace $host "www." "" -1 }}
server {
server_name {{ $nowwwhost }};
listen 80 {{ $default_server }};
listen [::]:80 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $nowwwhost)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $nowwwhost }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $nowwwhost)) }}
auth_basic "Restricted {{ $nowwwhost }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $nowwwhost) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $nowwwhost)) }}
include {{ printf "/etc/nginx/vhost.d/%s_location" $nowwwhost}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
}
{{ end }}
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
server {
server_name {{ $host }};
listen 443 ssl http2 {{ $default_server }};
listen [::]:443 ssl http2 {{ $default_server }};
access_log /var/log/nginx/access.log vhost;
return 500;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
{{ if (exists ("/etc/nginx/certs/dhparam.pem")) }}
ssl_dhparam /etc/nginx/certs/dhparam.pem;
{{ end }}
}
{{ end }}
{{ end }}
{{ end }}
version: "3"
services:
nginx:
image: nginx:${NGINX_VER:-1.13}
container_name: docker-proxy-nginx
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./volumes/conf.d:/etc/nginx/conf.d:ro
- ./volumes/vhost.d:/etc/nginx/vhost.d:ro
- ./volumes/certs:/etc/nginx/certs:ro
- /usr/share/nginx/html
networks:
- proxy
docker-gen:
image: jwilder/docker-gen:${DOCKER_GEN_VER:-0.7.3}
container_name: docker-proxy-docker_gen
restart: unless-stopped
depends_on:
- nginx
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./data/templates:/etc/docker-gen/templates:ro
- ./volumes/conf.d:/etc/nginx/conf.d:rw
- ./volumes/vhost.d:/etc/nginx/vhost.d:ro
- ./volumes/certs:/etc/nginx/certs:ro
networks:
- proxy
entrypoint: /usr/local/bin/docker-gen -notify-sighup docker-proxy-nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
networks:
proxy:
external: true
client_max_body_size 1024m;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment