文章目录
- 环境
- 总结
- 测试
- 使用EXPOSE
- 测试1:不做端口映射
- 测试2:-p 8080:80
- 测试3:-P
- 测试4:--network=host
- 不使用EXPOSE
- 参考
环境
- RHEL 9.3
- Docker Community 24.0.7
总结
如果懒得看测试的详细信息,可以直接看结果:
docker run 选项 | 在Dockerfile里 EXPOSE 80 | 在Dockerfile里不 EXPOSE 80 | 备注 |
---|---|---|---|
无 | 在容器外无法访问容器的80端口 | 在容器外无法访问容器的80端口 | |
-p 8080:80 | 8080 | 8080 | 显式指定映射端口 |
-P | 随机端口 | 随机端口 | 随机映射端口 |
--network=host | 80 | 80 | 直接使用容器的端口 |
所以,EXPOSE并不会真正开放端口,它更像是一个说明文档,由image的开发者声明image所监听的端口,使用者以此为依据,在启动容器时,可以以不同的策略来开放端口。
测试
使用EXPOSE
创建 Dockerfile
文件如下:
FROM nginx:alpineEXPOSE 80
构建:
docker build -t kai0107_1 .
测试1:不做端口映射
启动容器:
docker run kai0107_1
查看容器:
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
430b0c2bee65 kai0107_1 "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 80/tcp recursing_noyce
检查该容器:
➜ ~ docker container inspect 430b0c2bee65 | grep -i3 port"Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0
--"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "",
--"AttachStdin": false,"AttachStdout": true,"AttachStderr": true,"ExposedPorts": {"80/tcp": {}},"Tty": false,
--"HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {"80/tcp": null},"SandboxKey": "/var/run/docker/netns/c762f4dc271b",
注:可以用 -f
选项指定输出格式,参见 https://docs.docker.com/engine/reference/commandline/inspect
。
打开浏览器,访问 http://localhost:80
,如下:
可见,在容器之外,无法访问80端口。
测试2:-p 8080:80
启动容器:
docker run -p 8080:80 kai0107_1
查看容器:
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd9ea9e98b4b kai0107_1 "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, :::8080->80/tcp naughty_almeida
注: 0.0.0.0
和 ::
都是代表匹配所有IP地址。前者是IPv4的写法,后者是IPv6的写法。
检查该容器:
➜ ~ docker container inspect dd9ea9e98b4b | grep -i3 port"Config": {}},"NetworkMode": "default","PortBindings": {"80/tcp": [{"HostIp": "","HostPort": "8080"}]},
--"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "",
--"AttachStdin": false,"AttachStdout": true,"AttachStderr": true,"ExposedPorts": {"80/tcp": {}},"Tty": false,
--"HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {"80/tcp": [{"HostIp": "0.0.0.0","HostPort": "8080"},{"HostIp": "::","HostPort": "8080"}]},
打开浏览器,访问 http://localhost:8080
,如下:
可见,在容器外部,可以通过8080端口访问容器里的80端口。
测试3:-P
启动容器:
docker run -P kai0107_1
查看容器:
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
241fd7f0ee87 kai0107_1 "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:32768->80/tcp, :::32768->80/tcp jovial_haslett
检查该容器:
➜ ~ docker container inspect 241fd7f0ee87 | grep -i3 port"Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0
--"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": true,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "",
--"AttachStdin": false,"AttachStdout": true,"AttachStderr": true,"ExposedPorts": {"80/tcp": {}},"Tty": false,
--"HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {"80/tcp": [{"HostIp": "0.0.0.0","HostPort": "32768"},{"HostIp": "::","HostPort": "32768"}]},
打开浏览器,访问 http://localhost:32768
,如下:
可见,在容器外部,可以通过32768端口访问容器里的80端口。
注意:32768是一个随机端口。下次再启动容器时,可能就是另外一个端口了。
测试4:–network=host
启动容器:
docker run --network=host kai0107_1
查看容器:
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
adcbcdd4698c kai0107_1 "/docker-entrypoint.…" 6 seconds ago Up 6 seconds quizzical_hugle
检查该容器:
➜ ~ docker container inspect adcbcdd4698c | grep -i3 port"Config": {}},"NetworkMode": "host","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0
--"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "",
--"AttachStdin": false,"AttachStdout": true,"AttachStderr": true,"ExposedPorts": {"80/tcp": {}},"Tty": false,
--"HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/default","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,
打开浏览器,访问 http://localhost:80
,如下:
可见,在容器外部,可以通过80端口访问容器里的80端口。
不使用EXPOSE
创建 Dockerfile
文件如下:
FROM nginx:alpine
再次做测试1到测试4,其结果和使用EXPOSE时是完全一致的。
参考
https://docs.docker.com/engine/reference/run/#expose-incoming-ports
https://blog.csdn.net/qq_33801641/article/details/121122334
https://www.php.cn/faq/494255.html
https://yeasy.gitbook.io/docker_practice/network/port_mapping