文章目录
- 环境
- 总结
- 测试
- 使用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:alpine
EXPOSE 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