Короткий ответ:
EXPOSEэто способ документирования
--publish(или -p) является способом отображения на хост - порт к включенному контейнерного порта
Обратите внимание, что ниже:
EXPOSEсвязано с Dockerfiles( документирование )
--publishсвязано с docker run ...( выполнение / время выполнения )
Разоблачение и публикация портов
В сети Docker есть два разных механизма, которые напрямую задействуют сетевые порты: открывающие и публикующие порты. Это относится к мостовой сети по умолчанию и пользовательским мостовым сетям.
Вы EXPOSEоткрываете порты, используя ключевое слово в Dockerfile или --exposeфлаг для запуска Docker . Предоставление портов - это способ документировать, какие порты используются, но на самом деле не отображает и не открывает какие-либо порты . Разоблачение портов не является обязательным.
Вы публикуете порты, используя --publishили--publish-all флагаdocker run . Это сообщает Docker, какие порты открывать в сетевом интерфейсе контейнера. Когда порт публикуется, он сопоставляется с доступным портом высокого порядка (выше, чем 30000) на хост-компьютере, если только вы не укажете порт, который будет отображаться на хост-компьютере во время выполнения. Вы не можете указать порт для сопоставления на хост-машине при создании образа (в Dockerfile), потому что нет способа гарантировать, что порт будет доступен на хост-машине, на которой вы запускаете образ .
от: Docker контейнерные сети
Обновление за октябрь 2019 года : вышеуказанный фрагмент текста больше не находится в документации, но архивная версия находится здесь: docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports
Возможно текущая документация ниже:
Опубликованные порты
По умолчанию при создании контейнера он не публикует свои порты во внешнем мире. Чтобы сделать порт доступным для служб вне Docker или для контейнеров Docker, которые не подключены к сети контейнера, используйте флаг --publishили -p. Это создает правило брандмауэра, которое сопоставляет порт контейнера с портом на хосте Docker.
и можно найти здесь: docs.docker.com/config/containers/container-networking/#published-ports
Также,
ПОДВЕРГАТЬ
... EXPOSEИнструкция фактически не публикует порт . Он функционирует как тип документации между человеком, который создает образ, и человеком, который запускает контейнер, о том, какие порты предназначены для публикации.
от: ссылка на Dockerfile
Доступ к услуге, когда EXPOSE/ --publishне определены:
В ответе @Golo Roden говорится, что:
«Если вы не укажете ни один из них, служба в контейнере не будет доступна нигде, кроме как внутри самого контейнера».
Возможно, именно так и было во время написания ответа, но теперь кажется, что даже если вы не используете EXPOSEили --publish, hostи другие containersпользователи той же сети смогут получить доступ к службе, которую вы можете запустить внутри этого контейнера.
Как проверить это:
Я использовал следующее Dockerfile. По сути, я начинаю с Ubuntu и устанавливаю крошечный веб-сервер:
FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd
Я buildизображение как «testexpose» и runновый контейнер с:
docker run --rm -it testexpose bash
Внутри контейнера я запускаю несколько экземпляров mini-httpd:
root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090
Затем я могу использовать curlхост или другие контейнеры для загрузки домашней страницы mini-httpd.