Простой вариант использования: производственный сервер, работающий на Nginx (прослушивающий 0.0.0.0:80 и 443), отвечающий за чтение сертификатов SSL и, если он действителен, перенаправляет на «скрытую» службу в контейнере Docker.Эта служба запускает Gunicorn (так на веб-сайте Django) и прослушивает порт 8000. Это звучит стандартно, просто, проверено, почти слишком красиво, чтобы быть правдой ... но, конечно, это не работает, как хотелось бы.
Потому что Gunicorn, работающий в своем небольшом контейнере Docker, доступен через Интернет.Если вы перейдете на мое имя хоста, порт 8000, вы получите веб-сайт Gunicorn.Очевидно, это уродливо, но хуже всего то, что он полностью обходит Nginx и SSL-сертификаты.Так почему контейнер Docker будет доступен через Интернет?Я знаю, что какое-то время с Докером все было наоборот.Нам нужен правильный баланс!
При дальнейшей проверке проблемы: у меня есть брандмауэр, и он настроен так, чтобы быть чрезвычайно ограничивающим.Он допускает только порт 22 (для ssh, ожидающий переназначения), 80 и 443. Поэтому 8000 абсолютно не должен быть разрешен.Но ufw использует iptables, а Docker добавляет некоторые правила iptables для обхода конфигурации, если контейнер работает на этом порту.
Я пробовал много глупостей (это часть работы): в моем docker-compose.ymlфайл, указывающий порты для привязки, я пытался удалить их (конечно, если я это сделаю, nginx не сможет получить доступ к моей скрытой службе).Я попытался добавить IP-адрес, указанный для привязки (кажется, что он разрешен):
ports:
- "127.0.0.1:8000:8000"
Это привело к странным результатам, так как Nginx не смог подключиться, но Gunicorn все еще был виден через Интернет.Так что я бы сказал, как раз наоборот, чего я хочу.Я попытался вручную изменить службу Docker для добавления флагов (не очень хорошо) и попытался добавить файл конфигурации в etc/docker/daemon.json
(снова изменив настройку «ip» на «127.0.0.1»).У меня не хватает идей.Если у кого-то есть указатель ... Я бы не подумал, что это крайне редкое использование Docker, в конце концов.
Особенности: Я не запускаю контейнеры с docker run
напрямую.У меня есть файл docker-compose.yml
и я запускаю службы, используя docker stack
, поэтому в рое (хотя у меня есть только одна машина одновременно).Может быть связано, хотя, опять же, я думаю, что нет.
- Система: Debian 9.
- Версия Docker: 18.09.
- Версия Docker-Compose: 1.22
nginx (/etc/nginx/sites-available/example.com)
upstream gunicorn {
server localhost:8000;
}
server {
server_name example.com www.example.com;
location / {
proxy_pass http://gunicorn;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate ...;
ssl_certificate_key ...;
include ...;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
docker-compose.yml
version: '3.7'
services:
gunicorn:
image: gunicorn:latest
command: gunicorn mysite.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./:/usr/src/app/
ports:
- "8000:8000"
depends_on:
- db
networks:
- webnet
db:
image: postgres:10.5-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
networks:
- webnet
networks:
webnet:
volumes:
postgres_data:
Примечание: изображение с оружием было создано заранее, но неттрюк, просто Python-3.7: тонкое изображение со всем набором для gunicorn и веб-сайта Django под mysite /.Он не предоставляет никаких портов (не то, чтобы я думал, что здесь есть какая-то разница).