Dockerfile的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 文件如下:

powershell 复制代码
FROM nginx:alpine

EXPOSE 80

构建:

powershell 复制代码
docker build -t kai0107_1 .

测试1:不做端口映射

启动容器:

powershell 复制代码
docker run kai0107_1

查看容器:

powershell 复制代码
➜  ~ 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

检查该容器:

powershell 复制代码
➜  ~ 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

启动容器:

powershell 复制代码
docker run -p 8080:80 kai0107_1

查看容器:

powershell 复制代码
➜  ~ 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的写法。

检查该容器:

powershell 复制代码
➜  ~ 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

启动容器:

powershell 复制代码
docker run -P kai0107_1

查看容器:

powershell 复制代码
➜  ~ 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

检查该容器:

powershell 复制代码
➜  ~ 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

启动容器:

powershell 复制代码
docker run --network=host kai0107_1

查看容器:

powershell 复制代码
➜  ~ docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
adcbcdd4698c   kai0107_1   "/docker-entrypoint...."   6 seconds ago   Up 6 seconds             quizzical_hugle

检查该容器:

powershell 复制代码
➜  ~ 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 文件如下:

powershell 复制代码
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
相关推荐
金刚猿2 分钟前
01_虚拟机中间件部署_root 用户安装 docker 容器,配置非root用户权限
docker·中间件·容器
JH_Kong28 分钟前
解决 WSL 中 Docker 权限问题:从踩坑到完整修复
docker·容器
忆~遂愿1 小时前
GE 引擎与算子版本控制:确保前向兼容性与图重写策略的稳定性
大数据·开发语言·docker
70asunflower4 小时前
Emulation,Simulation,Virtualization,Imitation 的区别?
linux·docker
春日见5 小时前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
xuhe26 小时前
[全流程详细教程]Docker部署ClawBot, 使用GLM4.7, 接入TG Bot实现私人助理. 解决Docker Openclaw Permission Denied问题
linux·docker·ai·github·tldr
星火s漫天6 小时前
第一篇: 使用Docker部署flask项目(Flask + DB 容器化)
数据库·docker·flask
MonkeyKing_sunyuhua8 小时前
docker compose up -d --build 完全使用新代码打包的方法
docker·容器·eureka
醇氧9 小时前
【docker】mysql 8 的健康检查(Health Check)
mysql·docker·容器
技术路上的探险家9 小时前
Ubuntu下Docker与NVIDIA Container Toolkit完整安装教程(含国内源适配)
linux·ubuntu·docker