Текст и данные · Инструкция
Как узнать опубликованный порт Docker-контейнера
Как узнать опубликованный порт Docker-контейнера особенно важно, когда host port назначен автоматически или контейнер.
Короткий ответ
Как найти host port через docker port, отличить его от container port и проверить binding, протокол и случайно назначенный порт.
Что показывает docker port и чего он не показывает
Команда `docker port` — alias для `docker container port` — выводит опубликованные сопоставления конкретного контейнера. Если вы запускали `docker run -p 8080:80 nginx`, результат для `80/tcp` покажет host binding вроде `0.0.0.0:8080`. Если host port не был задан, например `docker run -p 80 nginx`, Docker выберет доступный ephemeral port, и `docker port` — самый прямой способ узнать его после запуска. При этом команда не сканирует процессы внутри контейнера и не доказывает, что приложение реально слушает целевой порт. Она показывает только настройки публикации Docker. Если Dockerfile содержит `EXPOSE 80`, но контейнер запущен без `-p` или `-P`, внешнего mapping может не быть вообще: EXPOSE — метаданные образа, а не команда публикации. Это различие помогает не тратить время на firewall, когда проблема находится на уровне создания контейнера.
Совет: Сначала выясните mapping через `docker port`, а уже затем проверяйте доступность приложения. Иначе легко диагностировать не тот слой сети.
Посмотреть все или один опубликованный порт
- Найдите имя или ID контейнера: `docker ps`. Если контейнер остановлен, добавьте `-a`, чтобы убедиться, что вы смотрите на нужный экземпляр.
- Выведите все mappings: `docker port mycontainer`. Формат будет похож на `80/tcp -> 0.0.0.0:54772`.
- Если интересует один внутренний порт, выполните `docker port mycontainer 80/tcp`. Для UDP укажите `80/udp`, потому что протокол — часть mapping.
- Если команда ничего не выводит, проверьте запуск контейнера: был ли `-p` или `-P`. Наличие `EXPOSE` в image само по себе не публикует порт.
- Сверьте host IP. Binding `127.0.0.1:8080` предназначен для доступа с локального хоста, а `0.0.0.0:8080` означает публикацию на всех IPv4-интерфейсах хоста по стандартной конфигурации Docker.
- После этого проверьте, что приложение внутри контейнера действительно слушает нужный container port и что запрос идёт на host port, а не на внутренний номер.
Важно: Если сервис должен быть только локальным, публикуйте на `127.0.0.1`, а не оставляйте bind без IP. Docker предупреждает, что публикация без адреса по умолчанию делает порт доступным на всех интерфейсах.
Как читать типичные строки
- 80/tcp -> 0.0.0.0:8080. TCP 8080 на всех IPv4-интерфейсах хоста перенаправляется в 80/tcp контейнера.
- 80/tcp -> 127.0.0.1:8080. Порт доступен только через loopback хоста, если нет особой сетевой конфигурации.
- 53/udp -> 0.0.0.0:5353. Опубликован UDP mapping; проверять его как TCP неправильно.
- Пусто. У контейнера нет опубликованных mappings либо запрошен другой порт/протокол.
Предупреждение: Не путайте `HOST_PORT:CONTAINER_PORT`: в `-p 8080:80` слева 8080 на хосте, справа 80 внутри контейнера.
Почему docker ps и docker port иногда удобны по-разному
`docker ps` уже показывает колонку PORTS и полезен для быстрого обзора нескольких контейнеров. Но если строка длинная, mappings несколько или нужно программно запросить конкретный внутренний порт, `docker port <name> <port/proto>` проще и однозначнее. В автоматизации не стоит парсить красиво отформатированную таблицу `docker ps` регулярным выражением, если задача сводится к одному mapping. Для более сложного машинного вывода можно использовать `docker inspect` и структуру NetworkSettings.Ports, но это другой уровень детализации. `docker port` хорош как операторская команда: короткий ввод, короткий ответ. Отдельно учитывайте IPv6 — один порт может иметь несколько bindings, и команда способна вернуть несколько строк. Скрипт, который ожидает ровно один адрес, должен обрабатывать этот случай, а не брать первую строку без проверки.
Почему порт опубликован, но сайт всё равно не открывается
Наличие mapping означает, что Docker настроил связь между host port и container port, но приложение может слушать другой порт, завершиться после старта или быть привязано только к `127.0.0.1` внутри контейнера. Для сервера внутри контейнера обычно нужен bind на `0.0.0.0:<container-port>`, чтобы трафик из контейнерной сети доходил до процесса. Проверьте `docker logs`, health status и список процессов, а затем при необходимости зайдите через `docker exec` и посмотрите слушающие сокеты. Также не путайте порт контейнера с портом хоста при curl: с самого хоста обращаются к опубликованному host port, а другой контейнер в одной пользовательской сети обычно обращается к service/container name и внутреннему порту напрямую. Публикация вообще не обязательна для связи контейнер–контейнер внутри одной сети. Если mapping настроен на `127.0.0.1`, удалённый компьютер не должен использовать этот адрес хоста как внешний endpoint.
Диагностика за одну минуту
- `docker ps` — нужный контейнер запущен и не перезапускается.
- `docker port <name>` — mapping существует и показывает ожидаемый host port.
- Протокол совпадает: tcp и udp проверяются отдельно.
- Приложение внутри слушает именно container port из правой части mapping.
- Host IP binding соответствует задаче: localhost для локального доступа, внешний интерфейс — только если это действительно нужно.
- Firewall и внешняя маршрутизация проверяются после того, как сам Docker mapping подтверждён.
Важно: Если база данных или административный интерфейс не должны быть доступны извне, не публикуйте их «на всякий случай». Для связи сервисов используйте Docker network без host publishing.
Как использовать docker port в скриптах без хрупкого парсинга
Если автоматизации нужен один конкретный mapping, запрашивайте его явно с портом и протоколом, например `docker port api 8080/tcp`, а затем обрабатывайте возможные несколько строк. Не предполагайте, что host IP всегда `0.0.0.0` или что binding только один: при IPv4/IPv6 и нескольких публикациях ответ может быть сложнее. Для строгого JSON-контракта лучше перейти на `docker inspect` и читать `NetworkSettings.Ports`, но для shell-проверки оператором `docker port` остаётся проще. Скрипт также должен корректно завершаться, если mapping отсутствует, вместо подстановки пустой строки в curl или конфигурацию другого сервиса. Перед использованием найденного адреса решите, откуда будет идти запрос: endpoint, пригодный для host, не обязательно является правильным адресом для другого контейнера в той же Docker network.
Что учитывать
`docker ps` уже показывает колонку PORTS и полезен для быстрого обзора нескольких контейнеров. Но если строка длинная, mappings несколько или нужно программно запросить конкретный внутренний порт, `docker port <name> <port/proto>` проще и однозначнее. В автоматизации не стоит парсить красиво отформатированную таблицу `docker ps` регулярным выражением, если задача сводится к одному mapping. Для более сложного машинного вывода можно использовать `docker inspect` и структуру NetworkSettings.Ports…
Источники и проверка
Фактическая часть сверена по первичным источникам (в т.ч. docker container port). Пример и формулировки — редакция N1RO на 2026-09-21.