Поиск по сайту:

В чем разница между раскрытием и публикацией порта Docker?


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

Открытие порта

Порты предоставляются с помощью инструкций EXPOSE в Dockerfile образа:

EXPOSE 80

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

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

Открытые порты видны, когда вы перечисляете свои контейнеры с помощью docker ps. Они будут отображаться в столбце ПОРТЫ, хотя на самом деле они не будут доступны за пределами контейнера. Это дает вам простой способ проверить, какие порты прослушивает программное обеспечение внутри контейнера.

Вы можете проверять порты, предоставляемые образом, без запуска контейнера с помощью docker inspect. Замените тег или идентификатор вашего изображения вместо demo-image:

docker inspect --format="{{json .Config.ExposedPorts}}" demo-image

Публикация портов

Публикация порта делает его доступным снаружи контейнера. Он позволяет вам взять порт, который вы обнаружили с помощью инструкции EXPOSE, а затем привязать к нему хост-порт.

Порты отображаются с флагом -p для команды docker run:

docker run -d -p 8080:80 httpd:latest

Эта команда связывает порт 8080 на вашем хосте Docker с портом 80 внутри вашего нового контейнера. Теперь вы можете посетить http://localhost:8080, чтобы получить доступ к порту контейнера. Если вы запустите docker ps, вы увидите, что столбец PORTS теперь показывает это сопоставление. Открытый контейнерный порт 80 опубликован на хосте.

Флаг -p можно использовать без указания порта для привязки:

docker run -d -p 80 httpd:latest

Этот вариант свяжет порт 80 в контейнере со случайным портом на хосте. Вы можете проверить назначенный порт, запустив docker ps.

-p также поддерживает публикацию порта на определенные сетевые интерфейсы:

docker run -d -p 127.0.0.1:8080:80 httpd:latest

Здесь порт 80 контейнера будет доступен только через порт 8080 по локальному петлевому адресу хоста. Это защитит ваш контейнер от сетевых вызовов, сделанных другими вашими устройствами.

Публикация всех открытых портов

Вы можете запустить контейнер с флагом --publish-all, чтобы Docker автоматически опубликовал все открытые порты, перечисленные в Dockerfile образа:

docker run -d --publish-all httpd:latest

Это назначит случайные свободные порты на вашем хосте каждому открытому порту в контейнере. Используйте команду docker ps, чтобы просмотреть сделанные назначения портов. Это упрощает запуск нового контейнера из образа, который требует открытия нескольких нестандартных портов.

Вы можете комбинировать --publish-all с явными сопоставлениями -p. В этом случае сопоставление, созданное флагом -p, переопределит случайный порт, назначенный --publish-all.

Когда вам не нужно публиковать порт

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

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

docker network create demo-network
docker run -d --network demo-network --name web web:latest
docker run -d --network demo-network --name database database:latest

В этом примере контейнер web может подключаться к серверу MySQL, работающему на порту 3306 в контейнере database, используя адрес database:3306. Docker автоматически настраивает таблицы маршрутизации для имен контейнеров в сети.

Использование диапазонов портов

Docker может выставлять и публиковать целые диапазоны портов, когда вам нужно иметь несколько доступных портов:

EXPOSE 8000-8100

docker run --publish-all
docker run -p 6000-6100:8000-8100

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

Краткое содержание

Открытые порты — это фрагменты метаданных, которые определяют порты, прослушиваемые программным обеспечением внутри образа контейнера. Наличие открытых портов не делает их доступными на интерфейсах хоста, если только вы не опубликуете их вручную. В этом смысле глагол «разоблачить» является неправильным, так как многие люди предполагают, что это активное действие, хотя на самом деле это информационное заявление. EXPOSE следует рассматривать как документацию, тогда как флаг -p создает функционирующее сопоставление портов.

Docker предоставляет дополнительное поведение на основе инструкций EXPOSE. Вы можете просматривать открытые порты контейнера с помощью docker ps независимо от того, были ли они опубликованы. Также есть флаг --publish-all, который публикует открытые порты образа на случайные порты хоста.

Порты контейнера всегда доступны через его собственный IP-адрес, даже если они не опубликованы. Любое устройство, которое может получить доступ к контейнеру, используя его назначенный Docker IP-адрес, видимый в выводе docker inspect, сможет использовать все его прослушивающие порты.

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