Как пробросить порт в контейнер
docker run -d --name web -p 8080:80 nginx:alpine-p 8080:80 — порт 8080 на хосте ведёт в порт 80 внутри контейнера. Сначала порт хоста, потом порт программы в контейнере. Теперь сайт открывается по адресу http://адрес-сервера:8080.
Варианты
| Запись | Что делает |
|---|---|
-p 80:80 | порт 80 хоста → 80 контейнера |
-p 8080:80 -p 8443:443 | несколько портов |
-p 127.0.0.1:8080:80 | только для самого хоста — снаружи недоступен |
-p 192.168.1.10:8080:80 | только на одном адресе хоста |
-p 1194:1194/udp | порт UDP |
-P | все порты из EXPOSE образа на случайные свободные порты хоста |
Какой порт слушает программа в контейнере, написано в описании образа на Docker Hub или в его Dockerfile (инструкция EXPOSE).
В Docker Compose
services:
web:
image: nginx:alpine
ports:
- "8080:80"
- "127.0.0.1:8443:443"Значения пишите в кавычках. После правки файла — docker compose up -d.
Проверить
docker port web
curl -I http://localhost:8080docker port показывает, какие порты контейнера куда опубликованы. curl -I должен вернуть ответ сервера, например HTTP/1.1 200 OK.
Добавить порт к готовому контейнеру
Порты задаются при создании контейнера, и у существующего контейнера их не добавить. Удалите контейнер и создайте заново с нужным -p — данные в томах сохранятся:
docker rm -f web
docker run -d --name web -p 8080:80 -p 8443:443 nginx:alpineПорт опубликован, а не открывается
- Программа слушает
127.0.0.1внутри контейнера. Подключения через-pприходят на сетевой адрес контейнера, а не на егоlocalhost. Программа должна слушать0.0.0.0— это настраивается в самой программе. - Перепутан порядок.
-p 80:8080вместо-p 8080:80— запросы уходят на порт, который в контейнере никто не слушает. - Контейнер не работает.
docker ps— есть ли он в списке; если нет, читайтеdocker logs web. - Порт занят. Ошибка
port is already allocatedилиaddress already in use— справка Ошибка port is already allocated. - Подключение из интернета. Домашний роутер не пропускает подключения снаружи: нужен проброс порта на самом роутере на адрес сервера (справка Как пробросить порт на роутере). У хостинга бывает свой брандмауэр в панели управления.
Порт, опубликованный без адреса (-p 8080:80), доступен из всей сети, и на Linux Docker открывает его в обход ufw. Базы данных и панели управления так не публикуйте: либо -p 127.0.0.1:…, либо вообще без -p — другие контейнеры в той же сети Docker достучатся и так. Подробно — в справке Docker открывает порты в обход ufw.
EXPOSE — не публикация
Инструкция EXPOSE 80 в Dockerfile и строка 80/tcp в docker ps только сообщают, какой порт слушает программа. Снаружи такой порт закрыт, пока его не опубликуют ключом -p или в разделе ports Compose.