–publish-all не публикует ОТКРЫТЫЙ порт

Вопрос или проблема

Вот базовый образ Docker NGINX:

FROM nginx:alpine
COPY src /usr/share/nginx/html
EXPOSE 80

Метаданные образа включают открытый порт:

> docker inspect --format '{{json .Config.ExposedPorts}}' ...
{"80/tcp":{}}

Но при запуске с docker run --publish-all сервер недоступен.
Его нужно запускать с docker run --publish 80:80.

Но разве не в этом заключается смысл EXPOSE — документировать порт образа, чтобы их можно было публиковать без необходимости явно указывать благодаря --publish-all?

--publish-all флаг публикует “открытые порты на временные порты”.

Таким образом, вы получите что-то вроде:

docker container inspect nginx --format=json \
| jq -r '.[0].NetworkSettings.Ports'
{
  "80/tcp": [
    {
      "HostIp": "0.0.0.0",
      "HostPort": "32769"
    }
  ]
}

Где, в этом случае, порт контейнера 80 сопоставлен с портом хоста 32769 (не 80).

Ответ или решение

Когда вы работаете с Docker, важно понимать механизм работы с портами, особенно в контексте флагов командной строки, таких как --publish и --publish-all. Давайте подробнее разберём проблему, с которой вы столкнулись при запуске контейнера с использованием --publish-all, и почему это может не давать ожидаемых результатов.

Объяснение проблемы

При использовании команды:

docker run --publish-all <image-name>

Docker автоматически открывает все порты, которые были объявлены с помощью директивы EXPOSE в Dockerfile. Однако, важно понимать, что при этом порты не публикуются на стандартных портах хоста. Вместо этого, каждый открытый порт сопоставляется с произвольным портом (эпhemeral port) на вашем хосте. Это значит, что ваш контейнерный порт 80 может быть сопоставлен, например, с портом 32769 на хосте (как показано в примере вашего вывода).

Почему EXPOSE не подразумевает публикацию на стандартных портах

Директива EXPOSE служит лишь для документирования того, какие порты используются приложением внутри контейнера. При этом, команда --publish-all сопоставляет эти порты с произвольными портами хоста, что часто вызывает путаницу. Однако это не означает, что пользователи всегда смогут получить доступ к контейнеру через стандартные порты, такие как 80.

Когда вы хотите, чтобы ваш сервер был доступен через стандартный HTTP-порт 80 на хосте, необходимо использовать команду:

docker run --publish 80:80 <image-name>

Эта команда явно указывает на то, что порт 80 вашего контейнера будет доступен через порт 80 вашего хоста.

Преимущества явной публикации портов

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

  2. Предсказуемость: С явной публикацией вы устраняете неопределенность, связанную с произвольным сопоставлением портов. Это особенно важно, если у вас работают несколько приложений, использующих один и тот же контейнерный порт.

  3. Простота отладки: Если возникли проблемы с доступом к приложению, проще диагностировать их, когда вы точно знаете, каким образом порты сопоставлены.

Заключение

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

Если у вас остались вопросы или требуется дополнительная информация, не стесняйтесь обращаться за разъяснениями!

Оцените материал
Добавить комментарий

Капча загружается...