当我在编写 Dockerfile 时没有公开任何端口,在运行docker run
时也没有绑定任何端口时,我仍然能够与容器内运行的应用程序进行交互。为什么?
我正在为我的 Node 应用程序编写我的 Dockerfile。它非常简单,看起来像这样:
FROM node:8
COPY . .
RUN yarn
RUN yarn run build
ARG PORT=80
EXPOSE $PORT
CMD yarn run serve
使用此 Dockerfile,我能够使用docker build
构建映像
$ cd ~/project/dir/
$ docker build . --build-arg PORT=8080
并使用docker run
运行它
$ docker run -p 8080 <image-id>
然后,我在 Docker 容器内访问了该应用程序,该应用程序位于http://172.17.0.12:8080/
这样的 IP 地址上,并且可以正常工作。
但是,当我从 Dockerfile 中删除EXPOSE
指令并删除docker run
中的-p
选项时,该应用程序仍然可以运行!就像Docker自动绑定我的端口一样
附加说明:
- 其他用户似乎遇到了同样的问题
- 删除
EXPOSE
说明后,我尝试使用--no-cache
重建映像,但此问题仍然存在。 - 使用
docker inspect
,我没有看到任何条目Config.ExposedPorts
Dockerfile 中的EXPOSE
命令真的没有多大作用,我认为阅读 Dockerfile 的人更了解容器内正在运行哪些端口/服务。但是,当您使用大写-P
参数启动 contianer 时,EXPOSE
很有用(-P、--publish-all 将所有公开的端口发布到随机端口(
docker run -P my_image
但是,如果您使用的是小写-p
则必须指定源:目标端口...查看此线程
如果你不在 Dockerfile 中编写EXPOSE
,它对容器内的应用程序没有任何影响,它仅用于大写-P
参数......