
Вступление
Представьте: вы собрали свой образ, запустили контейнер, внутри всё работает как часы. Но когда вы пытаетесь открыть сайт или API в браузере — тишина. Контейнер есть, а доступа нет. Знакомо?
Сегодня мы разбираемся с фундаментальной основой работы с Docker — пробросом портов (Port Mapping). Это та самая «дверь», через которую внешние пользователи (и вы сами) могут зайти внутрь вашего изолированного контейнера.
В этой статье на пальцах объясним, как работает -p и -P, и покажем живые примеры для реальных задач.

1. А зачем это вообще нужно?
По умолчанию Docker создает для контейнера изолированную сеть. У него есть свой IP-адрес (обычно вида 172.17.0.x), но из вашего браузера на хосте вы к нему не достучитесь. Это как квартира без звонка — внутри всё есть, но войти нельзя.


2. Главная команда: -p
Базовый синтаксис выглядит пугающе, но быстро запоминается:
bash
docker run -p [IP_хоста]:[порт_хоста]:[порт_контейнера] образ
Разберем на простом примере. Запустим веб-сервер Nginx:
bash
docker run -d -p 8080:80 nginx
Что произошло:
-d— запуск в фоне.-p 8080:80— мы сказали Docker: «Всё, что приходит на 8080 порт моего сервера, отправляй внутрь контейнера на 80 порт».
Теперь откройте в браузере http://ваш_сервер:8080 — вы увидите приветствие Nginx. Магия!
Типичные сервисы
| Сервис | В контейнере | Обычно публикуют |
|---|---|---|
| Nginx | 80 | 8080:80 |
| PostgreSQL | 5432 | 5432:5432 |
| MySQL | 3306 | 3306:3306 |
| Redis | 6379 | 6379:6379 |
| Grafana | 3000 | 3000:3000 |
3. Тонкие настройки (на всякий случай)
Докер дает гибкость. Вот три сценария, которые могут пригодиться:
Сценарий А: Привязка к конкретному IP
Если у вас на сервере несколько сетевых интерфейсов (например, публичный и внутренний), можно привязать проброс только к одному:
bash
docker run -p 127.0.0.1:8080:80 nginx
Теперь порт 8080 будет доступен только с локальной машины (localhost). Извне — не достучаться.
Сценарий Б: Случайный порт
Если вы не хотите заморачиваться с выбором цифр, Docker подберет свободный порт сам:
bash
docker run -P nginx
Флаг -P (большая буква) пробросит все EXPOSE-порты из Dockerfile на случайные порты хоста. Чтобы узнать, какой именно, введите docker ps.
Сценарий В: Привязка к UDP
Не только веб (TCP), но и UDP-сервисы (например, DNS или игры):
bash
docker run -p 53:53/udp dns-image
EXPOSE 80 в Dockerfile не открывает порт наружу. Это лишь информация о том, какой порт использует приложение. Чтобы получить доступ извне, всё равно нужен -p или ports: в Docker Compose.4. Как проверить, что проброс работает?
Жизненно важная команда после запуска:
bash
docker ps
В колонке PORTS вы увидите заветную запись: 0.0.0.0:8080->80/tcp. Если её нет — значит, контейнер работает, но «наружу» не выглядывает.
Если вы что-то напутали в настройках, всегда можно остановить контейнер и пересоздать его с новыми параметрами — в этом прелесть Docker.
5. Подводные камни (и как их обойти)
Проблема 1: «Порт уже занят»
Ошибка: Bind for 0.0.0.0:8080 failed: port is already allocated.
Это значит, что на хосте порт 8080 уже слушает другой процесс (или контейнер). Решение — сменить левый порт (например, -p 8081:80).
Проблема 2: Firewall
Помните, что проброс в Docker — это только половина дела. Если на вашем сервере включен ufw или iptables, не забудьте открыть порт и там. Docker часто редактирует правила сам, но не всегда это предсказуемо.
Совет для новичков:
Всегда используйте понятные порты для хоста, чтобы через месяц не гадать, что за сервис висел на порту 32773. Лучше -p 8080:80, чем случайная цифра от -P.
Заключение
Проброс портов — это ваш главный инструмент для публикации сервисов. Освоив -p, вы перестанете бояться сетевых настроек и сможете поднимать любые приложения (сайты, базы данных, очереди) за считанные секунды.
А вы уже пробовали поднимать свой стек в Docker? Если нет — самое время. Настройка проброса занимает 10 секунд, а экономит часы дебага.
P.S. Если вы ищете надежную площадку для ваших контейнеров, загляните на dockerhosting.ru — мы помогаем с хостингом и настройкой окружения, чтобы вы занимались кодом, а не инфраструктурой.