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
相关推荐
梦想的颜色11 小时前
【Docker原理】Docker 容器一文打尽:生命周期、环境管控、迁移备份、日志进程排查、垃圾清理
运维·docker·容器·容器生命周期·容器日志排查·容器迁移备份·容器进程管理
极客先躯19 小时前
高级java每日一道面试题-2026年03月30日-实战篇[Docker]-如何监控容器的网络流量?
java·运维·docker·容器·prometheus·高级面试
大E帝国子民121 小时前
Docker 部署 RocketMQ 5
docker·容器·rocketmq
江湖有缘1 天前
【保姆级教程】使用Docker Compose一键搭建Picsur私有图床服务
java·docker·容器
java_logo1 天前
5 分钟共享打印机:用 Docker 一键部署 CUPS
运维·docker·容器·cups·网络打印机·共享打印机·docker部署cups
fen_fen1 天前
Docker部署PostgreSQL10 开启SSL和证书安装文档
docker·容器·ssl
EnCi Zheng1 天前
N3A-一个端口只能给一个程序使用吗?[特殊字符]
网络·nginx·docker
彼岸笙箫1 天前
Centos7离线安装docker
运维·docker·容器
nuo5342021 天前
基础 1 —— Docker 的简介
运维·docker·容器
承渊政道1 天前
OneNav书签导航实操:极空间Docker部署、分类整理与公网访问
运维·docker·内网穿透·cpolar·nas·onenav·轻量级部署