Как извлечь порт контейнера в Docker?

Ответ

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

1. Команда docker port (самый прямой способ):

docker port <container_name_or_id> <container_port>
# Пример:
docker port my-nginx-container 80
# Вывод: 0.0.0.0:8080

Эта команда показывает маппинг только для явно опубликованных портов (флаг -p).

2. docker inspect с Go-шаблоном (для скриптов): Когда нужно программно получить порт в скрипте сборки или мониторинга:

# Получить хост-порт для контейнерного порта 80/tcp
docker inspect --format='{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' my-container

# Более надежный вариант, который обрабатывает случаи, когда порт не опубликован:
HOST_PORT=$(docker inspect my-container --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}')
if [ -n "$HOST_PORT" ]; then
    echo "Port is mapped to: $HOST_PORT"
fi

3. Просмотр через docker ps: Часто бывает достаточно посмотреть колонку PORTS:

docker ps --format "table {{.Names}}t{{.Ports}}" --filter "name=my-container"

Практический контекст: В CI/CD пайплайне, после развертывания контейнера, я могу использовать docker port для динамического определения порта и запуска интеграционных тестов:

APP_PORT=$(docker port my-app 8080 | cut -d: -f2)
curl -f http://localhost:$APP_PORT/health

Важно: Для контейнеров в Docker Swarm или Kubernetes используются другие методы (сервисы, Ingress, kubectl get svc).

Ответ 18+ 🔞

А, ну это классика, блядь! Каждый раз, когда контейнер запускаешь, начинается: «А на какой порт, сука, он там приземлился?» Особенно весело, когда этих контейнеров, как собак нерезаных, и каждый тянет своё. Ёпта, сейчас расскажу, как не сойти с ума.

1. docker port — твой прямолинейный друг, но с приколами. Вот ты запустил контейнер, а он молчит, как партизан. Хочешь узнать, куда стучаться? Команда — раз, и готово.

docker port <container_name_or_id> <container_port>
# Пример:
docker port my-nginx-container 80
# Вывод: 0.0.0.0:8080

Но тут, чувак, подвох! Эта команда показывает только то, что ты сам явно наружу высунул через этот самый -p. Если порт не публиковал — нихуя не увидишь, тишина. Так что имей в виду.

2. docker inspect с шаблонами — для тех, кто любит поковыряться в кишках. Это уже для серьёзных пацанов, которые в скриптах всё автоматизируют. Выглядит, конечно, как заклинание древнее, но работает на ура.

# Выцепить хост-порт для 80/tcp
docker inspect --format='{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' my-container

# А вот вариант понадёжнее, на случай, если порт вдруг не опубликован. Чтобы скрипт не накрылся медным тазом.
HOST_PORT=$(docker inspect my-container --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}')
if [ -n "$HOST_PORT" ]; then
    echo "Port is mapped to: $HOST_PORT"
fi

Сам от себя охуевал, когда первый раз этот формат писал, но, блядь, привыкаешь. Главное — скопипастить правильно, а то будет тебе хиросима.

3. Старый добрый docker ps — быстрый взгляд. Иногда не хочется заморачиваться, просто глянуть, что там творится. Колонка PORTS всё покажет.

docker ps --format "table {{.Names}}t{{.Ports}}" --filter "name=my-container"

Удобно, быстро, но деталей маловато. Зато сразу видно всю картину, если контейнеров несколько.

А вот где это реально в жизни пригождается, так это в CI/CD. Представь: контейнер взлетел, а тестам надо на него наброситься. Порт-то динамический может быть! Вот и крутишь, как мартышлюшка, чтобы вытащить его и подсунуть в curl.

APP_PORT=$(docker port my-app 8080 | cut -d: -f2)
curl -f http://localhost:$APP_PORT/health

Работает — красота. Не работает — ну, блядь, идём искать, где накосячили.

И главное, запомни раз и навсегда: вся эта магия только для обычного Docker. Если у тебя там Swarm или, упаси боже, Kubernetes — это совсем другой цирк. Там свои команды, свои service и ingress. Так что не пытайся docker port на кластере применить — будет тебе волнение ебать, а толку ноль.