В чем разница между портами docker-compose и expose

Ответы:

527

Согласно справочнику docker-compose ,

Порты определяются как:

Выставить порты . Либо укажите оба порта (HOST: CONTAINER), либо просто порт контейнера (будет выбран случайный порт хоста).

  • Порты, упомянутые в docker-compose.yml, будут совместно использоваться различными службами, запускаемыми docker-compose.
  • Порты будут выставлены на хост-машину с произвольным портом или заданным портом.

Моя docker-compose.ymlвыглядит так:

mysql:
  image: mysql:5.7
  ports:
    - "3306"

Если я это сделаю docker-compose ps, это будет выглядеть так:

  Name                     Command               State            Ports
-------------------------------------------------------------------------------------
  mysql_1       docker-entrypoint.sh mysqld      Up      0.0.0.0:32769->3306/tcp

Expose определяется как:

Открывайте порты, не публикуя их на хост-машине - они будут доступны только для связанных сервисов. Можно указать только внутренний порт.

Порты не отображаются на хост-машинах, только на других сервисах.

mysql:
  image: mysql:5.7
  expose:
    - "3306"

Если я это сделаю docker-compose ps, это будет выглядеть так:

  Name                  Command             State    Ports
---------------------------------------------------------------
 mysql_1      docker-entrypoint.sh mysqld   Up      3306/tcp
bibstha
источник
24
Можно ли объяснить, какие преимущества есть при указании exposeв docker-compose? Насколько я могу судить, вам не нужно указывать expose, чтобы сделать порты доступными для связанных служб.
Сочные
3
Разве это не говорит о том, что открытые порты будут доступны только для служб в той же сети док-станции (в большинстве случаев связь заменяется)?
мяу
8
@ Juicy Я думаю, что это похоже на exposeDockerfiles: «Инструкция EXPOSE фактически не публикует порт. Она работает как тип документации ...» docs.docker.com/engine/reference/builder/#expose
tsauerwein
1
Переопределяют ли порты какие-либо настройки на уровне брандмауэра? Я только заметил, что я не открыл порты для mysql на брандмауэре, но они были доступны удаленно. Я выставил порты на «3306: 3306» вместо «выставить».
TekiusFanatikus
3
И помните, если вы используете docker-compose run, определение порта в docker-compose.ymlэто игнорируется по умолчанию. Либо используйте, docker-compose upлибо предоставьте параметр--service-ports
Юха Унтинен,
178

порты :

  1. Активирует контейнер для прослушивания указанных портов из мира за пределами докера (это может быть тот же хост-компьютер или другой компьютер) И также доступный мир внутри докера.
  2. Можно указать более одного порта (поэтому порты не порты)

введите описание изображения здесь

выставить :

  1. Активирует контейнер для прослушивания определенного порта только из мира внутри докера И недоступного мира вне докера.
  2. Можно указать более одного порта

введите описание изображения здесь

Мехрадж Малик
источник
3
Обратите внимание, что expose позволяет использовать несколько портов - docs.docker.com/compose/compose-file/#expose - однако вы предоставляете только внутренний порт, а не внутренний + внешний
Стюарт Мур
Но что делать, если я хочу получить доступ к внешнему миру из моего контейнера? stackoverflow.com/questions/61322256/…
gstackoverflow
26

Порты Этот раздел используется для определения соответствия между хост-сервером и контейнером Docker.

ports:
   - 10005:80

Это означает, что приложение, работающее внутри контейнера, открыто на порт 80. Но внешняя система или объект не могут получить к нему доступ, поэтому его необходимо сопоставить с портом хост-сервера.

Примечание. Необходимо открыть порт хоста 10005 и изменить правила брандмауэра, чтобы разрешить внешним объектам доступ к приложению.

Они могут использовать

http: // {host IP}: 10005

что-то вроде этого

EXPOSE Это используется исключительно для определения порта, на котором приложение работает внутри контейнера Docker.

Вы также можете определить это в dockerfile. Как правило, это хорошая и широко используемая практика для определения EXPOSE внутри dockerfile, потому что очень редко кто-либо запускает их на другом порту, чем порт 80 по умолчанию

sorabzone
источник
19

Порты

В portsразделе будут публиковаться порты на хосте. Docker настроит переадресацию для определенного порта из хост-сети в контейнер. По умолчанию это реализуется с помощью процесса прокси-сервера пользователя (docker-proxy ), который прослушивает первый порт, и пересылается в контейнер, который должен прослушивать вторую точку. Если контейнер не прослушивает порт назначения, вы все равно увидите что-то прослушивающее на хосте, но получит отказ в соединении, если вы попытаетесь подключиться к этому порту хоста из-за сбоя пересылки в ваш контейнер.

Обратите внимание, что контейнер должен прослушивать все сетевые интерфейсы, поскольку этот прокси-сервер не работает в сетевом пространстве имен контейнера и не может достичь 127.0.0.1 внутри контейнера. Метод IPv4 для этого заключается в настройке приложения для прослушивания 0.0.0.0.

Также обратите внимание, что опубликованные порты не работают в обратном направлении. Вы не можете подключиться к службе на хосте из контейнера, опубликовав порт. Вместо этого вы обнаружите ошибки докера, пытающиеся прослушать уже используемый порт хоста.

разоблачать

Expose это документация. Он устанавливает метаданные на изображении, а при запуске - и на контейнере. Обычно вы конфигурируете это в Dockerfile с помощью EXPOSEинструкции, и она служит документацией для пользователей, запускающих ваш образ, чтобы они знали, по каким портам по умолчанию будет прослушивать ваше приложение. При настройке с помощью файла компоновки эти метаданные устанавливаются только для контейнера. Вы можете увидеть открытые порты при запуске docker inspectна образе или контейнере.

Есть несколько инструментов, которые полагаются на открытые порты. В докере -Pфлаг будет публиковать все открытые порты на временных портах хоста. Существуют также различные обратные прокси, которые по умолчанию будут использовать незащищенный порт при отправке трафика в ваше приложение, если вы явно не зададите порт контейнера.

Помимо этих внешних инструментов, expose не оказывает никакого влияния на взаимодействие между контейнерами. Вам нужна только общая сеть докеров и подключение к порту контейнера, чтобы получить доступ к одному контейнеру из другого. Если эта сеть создана пользователем (например, не называется мостовой сетью по умолчанию bridge), вы можете использовать DNS для подключения к другим контейнерам.

BMitch
источник
3

Я полностью согласен с ответами раньше. Я просто хотел бы отметить, что различие между expose и портами является частью концепции безопасности в Docker. Это идет рука об руку с сетью докера. Например:

Представьте себе приложение с веб-интерфейсом и базой данных. Внешний мир нуждается в доступе к веб-интерфейсу (возможно, через порт 80), но только самому серверу необходим доступ к хосту и порту базы данных. При использовании определенного пользователем моста необходимо открыть только веб-порт, а приложению базы данных не нужно открывать никаких портов, поскольку веб-интерфейс может достичь его через определенный пользователем мост.

Это частый случай использования при настройке сетевой архитектуры в Docker. Например, в мостовой сети по умолчанию недоступны порты из внешнего мира. Для этого вы можете открыть точку входа с помощью «портов». С помощью «выставить» вы определяете связь внутри сети. Если вы хотите выставить порты по умолчанию, вам не нужно определять «выставлять» в вашем файле docker-compose.

Медтехника
источник