Как разделить (открыть) порт 80 для нескольких проектов при использовании докера - PullRequest
0 голосов
/ 21 декабря 2018

Я недавно решил перенести свою среду разработки с нативного Mac на Docker для Mac, и я хотел бы, чтобы несколько проектов предоставляли один и тот же порт 80, чтобы я мог просто набрать http://app1.dev/ и http://app2.dev/ в браузере без запоминания десятков номеров портов.

Мне не нужно ничего делать в родной среде, чтобы добиться этого.Но так как теперь nginx запускается отдельно в каждом контейнере, они конфликтуют при открытии порта.Я также знаю, что могу использовать внешнюю ссылку на внешний контейнер, но я не хочу разбивать мой файл docker-compose.yml, я просто хочу, чтобы все было в одном куске.

docker-compose.ymlв ~ / demo1 /

version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
# ... 

docker-compose.yml в ~ / demo2 /

version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
# ...

Когда я запускаю команду docker-compose up -d в demo2, я получаю:

Creating network "demo2_default" with the default driver
Creating demo2_web_1 ... error

ERROR: for demo2_web_1  Cannot start service web: driver failed 
programming external connectivity on endpoint demo2_web_1 
(cbfebd1550e944ae468a1118eb07574029a6109409dd34799bfdaf72cdeb3d35): 
Bind for 0.0.0.0:80 failed: port is already allocated

ERROR: for web  Cannot start service web: driver failed programming 
external connectivity on endpoint demo2_web_1 
(cbfebd1550e944ae468a1118eb07574029a6109409dd34799bfdaf72cdeb3d35): 
Bind for 0.0.0.0:80 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.

Есть ли способ заставить их использовать один и тот же порт или переназначить порты с хоста на контейнер без использования дополнительных команд для создания внешних контейнеров?Или есть способ создать внешние контейнеры в файле docker-compose.yml?

1 Ответ

0 голосов
/ 21 декабря 2018

Нельзя сопоставить несколько портов контейнера с одним и тем же портом хоста.Любой контейнер, который появится первым, будет привязан к порту 80, а второй контейнер выбрасывает порт, который уже используется, если вы попытаетесь связать тот же порт.

Для решения этой проблемы вы можете запустить еще одну пустышку Nginx , которая просто делает proxy_pass до demo1 и demo2 .В этом случае http://app будет родительским Nginx, а /dev1 будет proxy_pass до demo1 и /dev2 будет proxy_pass до demo2 .

Здесь вам просто нужно привязать порт родительского Nginx к хосту.Вам не нужно связывать порты дочернего Nginx, если вы подключаете все это к одной сети и используете docker service discovery .Если вы будете следовать этим правилам, вы обнаружите еще одну проблему , т. Е. Nginx будет кэшировать IP-адреса контейнеров, разрешенных с помощью обнаружения служб, и будет использовать этот IP-адрес, чтобы всегда попадать в контейнеры.После перезапуска дочернего контейнера существует вероятность того, что IP-адрес дочернего элемента может измениться, поэтому родительский Nginx выбрасывает 502 .Чтобы решить эту проблему, вы должны перезапускать родительский Nginx каждый раз, когда вы перезапускаете demo1 или demo2 .Чтобы решить эту проблему, вы должны использовать resolver как 127.0.0.11 с действительностью в родительском Nginx.Поэтому каждый раз, когда Nginx будет пытаться разрешить IP-адрес после последнего разрешения в соответствии с действительностью.

Я добавил фиктивные файлы конфигурации, суммирующие все вышеперечисленные пункты.

Родительский Nginx составляет:

version: '3'
services:
  parent:
    image: nginx:alpine
    volume:
         - ./nginx.conf:/etc/nginx/nginx.conf
    ports:
         - 80:80
networks:
  default:
    external:
      name: dev

Конфигурация родительского Nginx (./nginx.conf):

server {
    listen 80;

    resolver 127.0.0.11 valid=5s; #this is local docker DNS and the internal IP getting resolved will be valid only for 5 seconds.

    location /app/dev1 {
        proxy_pass http://dev1:80;
    }

    location /app/dev2 {
        proxy_pass http://dev2:80;
    }
}

docker-compose.yml в ~ / demo1 /

version: '3'
services:
  web:
    image: nginx:alpine
  networks:
    default:
       aliases:
          - dev1
networks:
  default:
    external:
      name: dev

docker-compose.yml в ~ / demo2 /

version: '3'
services:
  web:
    image: nginx:alpine
  networks:
    default:
       aliases:
          - dev2
networks:
  default:
    external:
      name: dev

Теперь вы можете использовать demo1, нажав URL http://app/dev1 и demo2 с использованием http://app/dev2.

Ссылки:

  1. Обратный прокси NGINX
  2. NGINX proxy_pass
  3. NGINX resolver
  4. Необходимость Docker DNS
  5. Сеть Docker-контейнеров
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...