1. 概述
在使用 Docker 容器化应用时,我们通常只需要暴露一个端口,供容器内外通信。但在某些场景下,单个端口并不够用。例如,在 Spring Boot 应用中,我们可能希望使用一个额外的端口来暴露监控接口(如 Actuator),以便更好地管理应用。
本文将介绍如何在 Docker 中声明并发布多个端口,以满足上述需求。
2. 声明端口
首先,我们需要在构建镜像或运行容器时声明要暴露的端口。
我们以一个简单的 Spring Boot 应用 my-app 为例。该应用监听端口 8080,并使用 8081 端口发布 Actuator 监控接口。本地运行时,我们可以通过以下命令访问:
$ curl http://localhost:8080
Hello buddy
$ curl http://localhost:8081/actuator/health
{"status":"UP"}
2.1. 在 Dockerfile 中声明端口
我们可以在 Dockerfile 中使用 EXPOSE
指令来声明需要暴露的端口:
FROM openjdk:8-jdk-alpine
EXPOSE 8080
EXPOSE 8081
ARG JAR_FILE=target/my-app-0.1.jar
ADD ${JAR_FILE} my-app.jar
ENTRYPOINT ["java","-jar","/my-app.jar"]
构建镜像:
$ docker build -t my-app:latest .
⚠️ 注意:EXPOSE
并不会自动将端口映射到宿主机,它只是对镜像使用者的一种说明。要真正使用这些端口,还需要后续的发布操作。
我们也可以指定协议:
EXPOSE 8080/tcp
EXPOSE 8081/udp
默认是 TCP,如未指定则自动使用 TCP。
还可以声明端口范围:
EXPOSE 8000-8009
表示从 8000 到 8009 的 10 个端口都需要开放。
2.2. 在 docker run 命令中声明端口
如果镜像只暴露了 8080 端口,但我们运行时还需要 8081,可以使用 --expose
参数:
$ docker run --name myapp -d --expose=8081 my-app:latest
该命令运行容器并暴露 8081 端口。我们可以通过以下命令查看:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2debb3c5345b my-app:latest "java -jar /my-app.j…" 5 seconds ago Up 3 seconds 8080-8081/tcp myapp
⚠️ 注意:--expose
只是在容器内部暴露了端口,并未映射到宿主机。我们可以使用以下命令验证:
$ docker port myapp
没有输出,说明端口尚未映射到宿主机。此时我们无法访问应用:
$ curl http://localhost:8080
curl: (7) Failed to connect to localhost port 8080: Connection refused
也可以暴露端口范围:
$ docker run --name myapp -d --expose=8000-8009 my-app:latest
3. 发布端口
现在我们已经了解了如何声明端口,接下来要真正将这些端口映射到宿主机。
3.1. 在 run 命令中发布端口
继续使用 my-app 镜像为例,它在 Dockerfile 中已经声明了 8080 和 8081 端口。
我们可以使用 -P
参数一次性发布所有暴露的端口:
$ docker run --name myapp -d -P myApp:latest
该命令将容器的 8080 和 8081 映射为宿主机的随机端口。我们可以通过以下命令查看映射关系:
$ docker port myapp
8080/tcp -> 0.0.0.0:32773
8081/tcp -> 0.0.0.0:32772
现在可以通过这些端口访问应用:
$ curl http://localhost:32773
Hello buddy
$ curl http://localhost:32772/actuator/health
{"status":"UP"}
如果我们希望指定宿主机的端口,则可以使用 -p
参数:
$ docker run --name myapp -d -p 80:8080 my-app:latest
该命令将容器的 8080 映射到宿主机的 80,但 8081 未被映射:
$ curl http://localhost:80
Hello buddy
$ curl http://localhost:8081/actuator/health
curl: (7) Failed to connect to localhost port 8081: Connection refused
✅ 要映射多个端口,可以多次使用 -p
参数:
$ docker run --name myapp -d -p 80:8080 -p 81:8081 my-app:latest
这样我们就完全控制了哪些端口被映射出去。
3.2. 在 docker-compose 中发布端口
如果我们使用 docker-compose,可以在 docker-compose.yml
文件中声明要发布的端口:
version: "3.7"
services:
myapp:
image: my-app:latest
ports:
- 8080
- 8081
启动服务后,Docker 会为这两个端口分配随机宿主机端口:
$ docker-compose up -d
Starting my-app_myapp_1 ... done
$ docker port my-app_myapp_1
8080/tcp -> 0.0.0.0:32785
8081/tcp -> 0.0.0.0:32784
也可以手动指定映射关系:
version: "3.7"
services:
myapp:
image: my-app:latest
ports:
- 80:8080
- 81:8081
其中 80 和 81 是宿主机端口,8080 和 8081 是容器端口。
4. 总结
本文介绍了在 Docker 中如何声明并发布多个端口。我们了解到:
EXPOSE
只是声明端口,并不映射到宿主机;--expose
可以在运行时动态添加未声明的端口;- 使用
-P
可以一键发布所有暴露的端口; - 使用
-p
可以精确控制端口映射; - 在 docker-compose 中可以通过
ports
字段声明发布端口。
通过这些方式,我们可以灵活地管理容器与宿主机之间的端口映射关系,满足各种应用场景。