Я могу docker run -p 3000:3000 image
без EXPOSE
этого порта в контейнере (см. Ниже). Если это правда, тогда зачем вставлять EXPOSE в Dockerfile? Это просто для общения с пользователями изображений? Потому что я не знаю функциональной причины для EXPOSE портов, если они все равно являются связываемыми.
Вот шаги, показывающие мне привязку к порту в контейнере, несмотря на то, что это не EXPOSEd
$ cat Dockerfile
FROM alpine
RUN apk add nodejs npm vim
COPY webserver /webserver
CMD [ "node", "/webserver/index.js" ]
$ docker build .
Sending build context to Docker daemon 1.931MB
Step 1/4 : FROM alpine
---> 11cd0b38bc3c
Step 2/4 : RUN apk add nodejs npm vim
---> Using cache
---> 4270f8bdb201
Step 3/4 : COPY webserver /webserver
---> Using cache
---> 67f4cda61ff0
Step 4/4 : CMD [ "node", "/webserver/index.js" ]
---> Using cache
---> 1df8f9024b85
Successfully built 1df8f9024b85
$ curl localhost:4400
curl: (7) Failed to connect to localhost port 4400: Connection refused
$ docker run -d -p 4400:3000 1df8f9024b85
7d0e6c56f8ad8827fe72830a30c1aac96821104b8ea111291ca39e6536aad8fd
$ curl localhost:4400
Hello World!
$
источник
-P
флага, другие утилиты могут запрашивать у работающих контейнеров эти метаданные, что полезно в прокси-серверах, которые динамически обновляют свои правила пересылки, используя эти открытые порты в качестве значений по умолчанию.Это сделано ради автоматизации. У вас может быть универсальная команда, которая запускается
docker run -P
для запуска контейнера, а сам файл Dockerfile используется для указания того, какой контейнер предоставляет какой порт. Если вы имеете дело с десятками или сотнями контейнеров, создаваемых через конвейер, это очень полезно. Передача внешних деталей, не содержащихся в Dockerfile, вместе с контейнером по конвейеру от этапа к этапу довольно сложна в масштабе.источник