Как настроить два проекта на Docker и Nginx на одном сервере?
Пытаюсь на одном сервере под разными ip запустить два сайта на django.
Возникает ошибка, что порт занят. Исправил порты, но сайт не старартует.
Подскажите, где ошибка?
Ip работают, когда захожу по второму ip получаю переадресацию на первый сайт. Все настройки указал для второго сайта. В конце добавил настройку nginx первого сайта:
#Django
# Should be one of dev, prod
MODE=prod
PORT=8008
#postgres
DB_NAME=xxx
DB_USER=xxx
DB_HOST=xxx
DB_PASSWORD=xxxx
DB_PORT=5432
POSTGRES_PASSWORD=mysecretpassword
#WSGI
WSGI_PORT=8008
WSGI_WORKERS=4
WSGI_LOG_LEVEL=debug
# Celery
CELERY_NUM_WORKERS=2
# Email
EMAIL_HOST_USER=xxxx
EMAIL_HOST_PASSWORD=xxxx
docker-compose.yaml:
version: '3'
services:
backend:
build: ./
container_name: site_container
restart: always
command: ./commands/start_server.sh
ports:
- "${PORT}:${WSGI_PORT}"
volumes:
- ./src:/srv/project/src
- ./commands:/srv/project/commands
- static_content:/var/www/site
env_file:
- .env
depends_on:
- postgres
postgres:
image: postgres:12
volumes:
- pg_data:/var/lib/postgresql/data
env_file:
- .env
# environment:
# - DJANGO_SETTINGS_MODULE=app.settings.${MODE}
nginx:
image: nginx:1.19
volumes:
- ./nginx:/etc/nginx/conf.d
- static_content:/var/www/site
ports:
- 81:80
- 444:443
env_file:
- .env
depends_on:
- backend
volumes:
pg_data: {}
static_content: {}
default.conf:
server {
listen 80 default_server;
server_name 183.22.332.12;
location /static/ {
root /var/www/site;
}
location /media/ {
root /var/www/site;
}
location / {
proxy_set_header Host $host;
proxy_pass http://backend:8010;
}
}
default.conf первый сайт:
server {
#listen 80 default_server;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name site1 ip_site1;
ssl_certificate /etc/letsencrypt/live/site1/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/site1/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/site1/chain.pem;
location /static/ {
root /var/www/artads;
}
location /media/ {
root /var/www/artads;
}
location / {
proxy_set_header Host $host;
proxy_pass http://backend:8008;
}
}
server {
listen 80 default_server;
server_name ip_site2 site2;
location /static/ {
root /var/www/gdr_mr;
}
location /media/ {
root /var/www/gdr_mr;
}
location / {
proxy_set_header Host $host;
proxy_pass http://backend:8013;
}
}
server {
listen 80;
listen [::]:80;
server_name www.site1 site1;
location / {
return 301 https://site1$request_uri;
}
}
Ответы (2 шт):
Насчет "правильного" запуска можно всегда и много спорить - ведь сколько людей, столько и мнений, но пример +- "удобной" и масштабируемой конфигурации опишу. Для "удобства" работы в такой конфигурации предложил бы установить https://nginxproxymanager.com/ в качестве реверс прокси и объединить контейнеры и nginxproxymanager в одну сеть - после чего появиться возможность прокидывать порты контейнеров по http(s), tcp, udp на внешний интерфейс при помощи GUI а так же еще ряд вских плюшек например как генерация SSL сертификатов и их авто продление
Сначала создадим саму сеть
docker network create --driver bridge --subnet 172.26.0.0/24 testnet
Настроим NPM (nginxproxymanager) - по умолчанию будем считать реверс прокси последним узлом сети, в итоге получим
version: "3"
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
networks:
testnet:
ipv4_address: 172.26.0.254
restart: always
ports:
# Public HTTP Port:
- '80:80'
# Public HTTPS Port:
- '443:443'
# Admin Web Port:
- '81:81'
environment:
# These are the settings to access your db
DB_MYSQL_HOST: "172.26.0.253"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "user"
DB_MYSQL_PASSWORD: "pwd"
DB_MYSQL_NAME: "npm"
volumes:
- ./data/nginx-proxy-manager:/data
- ./letsencrypt:/etc/letsencrypt
depends_on:
- db
db:
image: yobasystems/alpine-mariadb:latest
restart: always
networks:
testnet:
ipv4_address: 172.26.0.253
environment:
MYSQL_ROOT_PASSWORD: "pwd"
MYSQL_DATABASE: "npm"
MYSQL_USER: "user"
MYSQL_PASSWORD: "pwd"
volumes:
- ./data/mariadb:/var/lib/mysql
networks:
testnet:
external: true
И настроим сам контейнер
version: '3'
services:
backend:
build: ./
container_name: site_container
restart: always
command: ./commands/start_server.sh
networks:
testnet:
ipv4_address: 172.26.0.2
volumes:
- ./src:/srv/project/src
- ./commands:/srv/project/commands
- static_content:/var/www/site
env_file:
- .env
depends_on:
- postgres
postgres:
image: postgres:12
volumes:
- pg_data:/var/lib/postgresql/data
env_file:
- .env
# environment:
# - DJANGO_SETTINGS_MODULE=app.settings.${MODE}
networks:
testnet:
external: true
volumes:
pg_data: {}
static_content: {}
После чего проводим первоначальную настройку NPM согласно инструкции https://nginxproxymanager.com/guide/#project-goal и добавляем хост
Вариант использования Traefik как обратный прокси:
docker-compose.yml
version: '3.7'
networks:
traefik:
external: true
services:
reverse-proxy:
image: traefik:v2.2
command:
- "--api=true"
- "--log.level=INFO"
- "--accesslog=true"
- "--accesslog.filepath=logs/access.log"
- "--accesslog.bufferingsize=100"
- "--global.sendanonymoususage"
- "--providers.docker"
- "--providers.docker.exposedbydefault=false"
- "--providers.providersthrottleduration=10s"
- "--certificatesresolvers.traefik-resolver.acme.email=user@domain.com"
- "--certificatesresolvers.traefik-resolver.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.traefik-resolver.acme.tlschallenge=true"
- "--entrypoints.http.address=:80"
- "--entrypoints.https.address=:443"
- "--entrypoints.dashboard.address=:8000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=PathPrefix(`/`)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.entrypoints=dashboard"
- "traefik.http.routers.api.middlewares=auth"
# Note: all dollar signs in the hash need to be doubled for escaping.
# To create user:password pair, it's possible to use this command:
# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
- "traefik.http.middlewares.auth.basicauth.users=user:1qwdqw@#dfw3423eda"
# Redirect http to https
- "traefik.http.routers.redirect-to-https.entrypoints=http"
- "traefik.http.routers.redirect-to-https.rule=PathPrefix(`/`)"
- "traefik.http.routers.redirect-to-https.middlewares=redirect-to-https@docker"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true"
ports:
# The HTTP port
- "80:80"
# The HTTP secure port
- "443:443"
- "9001:8000"
volumes:
- "./logs:/logs"
- "./letsencrypt:/letsencrypt"
# So that Traefissk can listen to the Docker events
- "/var/run/docker.sock:/var/run/docker.sock"
networks:
- traefik
restart: always
Более подробно про настройки можно прочитать тут Traefik на dockerhub
Перед запуском нужно будет создать контейнерную сеть Traefik и запустить сам контейнер командой docker-compose up -d в каталоге с файлом выше.
Далее в контейнере приложения прописываем:
version: '3.7'
networks:
traefik:
external: true
...
services:
nameyouservice:
...
networks:
- traefik
...
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
- "traefik.http.routers.uniqhabname.rule=Host(`yourdomain.com`)"
- "traefik.http.routers.uniqhabname.entrypoints=https,wss"
- "traefik.http.routers.uniqhabname.tls=true"
- "traefik.http.routers.uniqhabname.tls.certresolver=traefik-resolver"
...
Заменяем uniqhabname на понятное имя, чтобы потом по логам можно было понять, чье перенаправление, и указываем yourdomain.com при обращении на чье имя будет перенаправление в данный контейнер. То есть, на одном ip может быть много сервисов и перенаправление на нужный будет по имени.
