Как отключить сетевой режим в переопределяющем файле docker compose?

#docker #docker-compose

#docker #docker-compose

Вопрос:

Рассмотрим часть некоторого базового docker-compose.yml файла:

 services:
  foo:
    image: bar
    network_mode: host
.
.
.
 

Затем рассмотрите docker-compose.prod.yml файл, который переопределит сетевой режим базового файла, а также установит порты:

 services:
  foo:
    ports:
      - 'xxxx:yyyy'
    network_mode: ?
 

Я ищу такое значение ? , которое network_mode считается отключенным. Другими словами, установка для него значения none или bridge , похоже, не работает, поэтому я хочу, чтобы оно просто исчезло или использовало значение с таким эффектом (я не думаю, что есть значение по умолчанию).

Альтернативным решением этой проблемы является определение трех файлов docker-compose: docker-compose.yml , docker-compose.prod.yml , и docker-compose.dev.yml (или что-то эквивалентное, не имеет значения). Это работает нормально (см. Ниже), но я бы предпочел иметь только 2 файла и переопределить файл dev файлом prod, а не наоборот (так кажется более естественным).

Рабочая версия, использующая три файла:

docker-compose.yml

 services:
  foo:
    image: bar
.
.
.
 

docker-compose.dev.yml

 services:
  foo:
    network_mode: host
 

docker-compose.prod.yml

 services:
  foo:
    ports:
      - 'xxxx:yyyy'
 

Примечания:

  • Все файлы используют версию docker-compose 3 .
  • Конкретная настройка, которая в моем случае не работает с bridge сетевым режимом, представляет собой набор из трех служб: одна для запуска веб-материалов (общедоступных), одна для работников сельдерея (внутренняя) и одна для Redis (внутренняя). Использование bridge в web и / или celery приводит к невозможности подключения к службе Redis.

Ответ №1:

Я не знаю, как удалить параметр из предыдущего docker-compose.yaml , но bridge он действительно работает, возможно, вам потребуется двойное подтверждение.

Если мы посмотрим на сеть docker по умолчанию, вы bridge действительно можете увидеть там, если мы не установим --net , docker по умолчанию будет использовать bridge :

 $ docker network ls
NETWORK ID          NAME                     DRIVER              SCOPE
32a9a31082ae        bridge                   bridge              local
dcb12f4cc711        host                     host                local
16c73acab8c9        none                     null                local
 

Я привожу небольшой пример, чтобы доказать это:

docker-compose.yaml:

 version: "3"

services:
  web:
    image: python:3.7
    network_mode: host
    command: python -m http.server 9000
 

docker-compose.prod.yaml:

 version: "3"

services:
  web:
    ports:
    - 10000:9000
    network_mode: bridge
 
  • docker-compose up

    С помощью этой команды мы фактически просто будем использовать docker-compose.yaml , в то время, если мы откроем браузер, который мы можем увидеть, может успешно посетить, например: http://$ip:9000 , это потому, что сеть есть host .

  • docker-compose -f docker-compose.yaml -f docker-compose.prod.yaml вверх

    С помощью этой команды мы будем использовать 2 файла compose, последний переопределит дублирующую опцию в первом.

    Если вы откроете браузер, вы обнаружите, что не можете зайти http://$ip/9000 сейчас, вы могли бы просто зайти http://$ip/10000 . Это может доказать, что host эффект потери и bridge переопределение host успешно.

    (ПРИМЕЧАНИЕ: после вам нужно будет убедиться docker-compose.prod.yaml docker-compose.yaml , что порядок последовательности важен.)

ОБНОВЛЕНИЕ 20211017 на основе ваших новых комментариев:

Если вы хотите дополнительно посетить другой контейнер в вашем compose, вам нужно будет определить network_mode в этой целевой службе, чтобы использовать ту же сеть исходной службы network_mode: service:web , см. Раздел Сетевой режим:

docker-compose.yaml:

 version: "3"

services:
  web:
    image: python:3.7-alpine3.13
    command: python -m http.server 9000
    network_mode: host

  db:
    image: python:3.7-alpine3.13
    command: python -m http.server 8000
    network_mode: service:web
 

docker-compose.yaml:

 version: "3"

services:
  web:
    ports:
    - 10000:9000
    network_mode: bridge
 

Затем, после up, вы можете использовать что-то вроде next, чтобы напрямую перейти к сервису в db:

 docker-compose exec web wget http://localhost:8000 -O -
 

ПРИМЕЧАНИЕ:

  • при network_mode: bridge использовании in web web контейнер больше не использует сеть по умолчанию, которую compose настроил для вас. В результате вы не получите выгоды от автоматической настройки dns с помощью compose, что означает web , что вы не сможете получить доступ db к контейнеру, используя имя службы db .
  • чтобы решить эту проблему, теперь вы можете разрешить db контейнеру web явно использовать сеть с network_mode: service:web помощью . Это означает, что 2 контейнера теперь используют одно и то же сетевое пространство имен, тогда вам не нужно посещать db с именем службы, но использовать localhost . Теперь web вы можете получить доступ db к порту 8000 только с http://localhost:8000 помощью .

Комментарии:

1. Спасибо за подробное описание. К сожалению, bridge у меня не работает, я проверил еще раз. У меня есть три службы: web stuff, celery stuff и Redis. Если я использую bridge on web и / или celery, я не могу подключиться к Redis внутренне, но если я ничего не использую, все подключается просто отлично (и порты из веб-материалов действительно доступны для общественности). Я обновил вопрос с помощью этой информации.

2. Я также пытался явно настроить bridge службу Redis, но без хороших результатов.

3. Поскольку мы указываем network_mode, мы не сможем извлечь выгоду из автоматического dns для docker-compose, поэтому вы не сможете посетить другой контейнер с именем службы. В качестве поправки вы можете разрешить контейнерам использовать одно и то же сетевое пространство имен, подробности см. В разделе Обновление в ответе.

4. Уверяю вас, я рассмотрю отредактированное решение, потому что оно выглядит очень многообещающим, просто нужно немного времени: (

5. Спасибо за ваше обновление. К сожалению, кажется, что я не могу публиковать порты и одновременно использовать ваше предложение : Cannot create container for service ...: conflicting options: port publishing and the container type network mode . Кроме того, кажется, что если я включаю depends_on: B в службу A, но включаю network_mode: service:A в службу B, я также получаю циклическое предупреждение о зависимости.

Ответ №2:

TL; DR

docker-compose.prod.yml

 services:
    foo:
        network_mode: unset    # Can be any string other than 'host'.
        networks: [ default ]
        
        ports: [ 80:80 ]
 

Docker Compose Сеть по умолчанию

Это поведение по умолчанию: если networks: для службы не определено и не network_mode: определено, то она подключена к default сети.

К сожалению, пустая строка игнорируется синтаксическим анализатором YAML, поэтому мы не можем переопределить network_mode: обратно '' , что мы можем сделать, это установить networks: [ default ] , но это не будет работать с network_mode: host так что мы можем установить network_mode: ?

network_mode: эквивалентно Docker --network , если мы установим для него сетевое имя networks: , оно переопределит его, поэтому мы можем использовать любое значение, отличное от host того, которое, по-видимому, вызывает какое-то особое поведение. Вероятно, хорошей идеей будет установить для него значение, которое не будет работать без networks: и избегать default bridge или none .

Чтобы восстановить поведение по умолчанию, нам нужно добавить default к networks: и установить network_mode: что-то другое, чем host .


Обратите внимание, что network_mode: default это эквивалентно --network default или --network bridge который использует сеть Docker по умолчанию: bridge , а не по умолчанию для всего проекта Compose network: projectName_default .

Комментарии:

1. Это выглядит многообещающе, я посмотрю, когда у меня будет такая возможность

2. Привет, извините — мне потребовалось некоторое время, чтобы попробовать это, поскольку я некоторое время не работал с docker. Не уверен, было ли какое-либо обновление за это время, но я получаю следующее: Cannot start service foo: network unset not found а также 'network_mode' and 'networks' cannot be combined

3. Но, похоже, я могу использовать network_mode: "" (пустую строку) просто отлично. Мне потребуется некоторое время, чтобы убедиться, что все службы доступны, как и ожидалось, в этом сетевом режиме, но я думаю, что это будет хорошим результатом.