为Spring Boot构建Docker 镜像及容器运行全流程
大家好,我是欧阳方超,微信公众号同名。本文介绍下,将Spring Boot工程打成Docker镜像,然后用镜像创建容器并执行。
1 Docker和Docker镜像
Docker是一个开源的容器化平台,它允许开发者将应用程序及其所有依赖项打包到一个称为容器的独立单元中。容器是轻量级的、可移植的,并且可以在任何支持Docker的环境中运行。
Docker镜像是一个只读模版,包含了运行一个容器所需的所有文件系统层、配置信息等。可以把它视为一个容器的蓝图。
2 构建项目
在执行Docker镜像构建之前,需要先使用Maven或Gradle构建Spring Boot项目,以生成可执行的jar文件。
3 创建Dockerfile
在Spring Boot项目的根目录下创建一个名为Dockerfile的文件,其内容一般如下。
基础镜像选择
对于 Spring Boot 应用,通常基于 Java 运行时环境的镜像。例如,使用openjdk:8-jdk-alpine作为基础镜像,这是一个基于 Alpine Linux 的 Docker 镜像,专为运行 Java 8 应用程序而设计。
FROM openjdk:8-jdk-alpine
设置工作目录
在镜像中设置一个工作目录,用于存放应用程序文件。例如:
WORKDIR /app
复制应用程序文件
将构建好的 Spring Boot JAR 文件复制到镜像的工作目录中并重命名为app.jar,当然也可以不进行重命名,此时写一个点(.)就行。假设你的 JAR 文件在target目录下,名为spring-boot-app.jar,可以使用以下命令:
COPY target/spring-boot-app.jar app.jar
暴露端口
Spring Boot 应用通常会运行在一个特定的端口上,比如 2002。需要在镜像中暴露这个端口,以便容器运行时可以访问应用。
EXPOSE 2002
定义容器启动命令
当容器启动时,需要执行的命令来运行 Spring Boot 应用。通常使用java -jar命令来运行 JAR 文件。
ENTRYPOINT [“java”, “-jar”, “app.jar”]
4 构建 Docker 镜像
在项目根目录下,打开终端或命令行窗口,执行以下命令来构建Docker镜像:
docker build -t my-spring-boot-app:1.0 .
这里的my-spring-boot-app是所要构建镜像的名称,英文冒号后的1.0表示tag号。
最后的点(.)号表示当前工作目录。Docker在构建镜像时需要一个上下文,这个上下文包含了所有Dockerfile中所需的文件和目录。点号(.)指向当前目录,Docker会将这个目录中的所有内容(除非在 .dockerignore 文件中排除)发送到Docker守护进程。
5 运行Docker容器
构建完成后,可以通过以下命令运行Docker容器:
docker run -p 8080:2002spring-boot-app:1.0
这个命令会基于1.0的spring-boot-app镜像启动一个容器,将容器的2002端口(冒号右边)映射到主机的8080端口(冒号左边),从而可以通过 http://localhost:8080来访问应用程序。
在使用docker run命令时,可以通过-d选项让容器在后台(守护进程模式)启动。
docker run -d -p 8080:2002 spring-boot-app:1.0
6 几个端口
Spring Boot工程一般在yml配置文件中都有一个端口,Dockerfile中会EXPOSE一个端口,运行docker容器的命令也会指定两个端口。
6.1 yml配置文件中的端口
yml配置文件中的端口是应用程序本身实际监听的端口,可以把这个端口想象成应用程序在容器内部的一个 “门牌号”。当有网络请求(如 HTTP 请求)想要访问这个应用程序时,应用程序就在这个端口处 “等待” 请求的到来。
例如,当你在容器内部有一个 Web 服务,这个端口就是用来接收来自其他组件(如在同一个容器网络中的其他微服务)或者外部(通过端口映射后)的 HTTP 请求,然后根据应用程序内部的代码逻辑(如控制器中的方法)来处理这些请求。
6.2 Dockerfile中的EXPOSE端口
该端口类似于给容器贴了一个标签。它主要是告诉 Docker 以及其他可能使用这个镜像的服务:“这个容器里面的应用程序在运行的时候会监听 2002端口。”
6.3 docker run命令中的端口映射
当使用docker run -p 8080:2002命令时,它就像是在主机(或者服务器)和容器之间建立了一座 “桥梁”。左边的 8080 是主机上的端口,右边的 2002 是容器内部的端口(也就是 Spring Boot 应用程序在application.yml中监听的端口)。
这就好比在主机的墙上开了一个门(主机上的 8080 端口),通过这个门,外面的人(外部网络请求)可以进入到容器内部的那个 “门牌号为 2002” 的房间(应用程序监听的端口),从而访问应用程序。
6.4 关于端口的几个问题
- docker run命令后所映射的容器内应用的端口可以跟应用的yml中写的端口不一致吗,当然不可以,刻意为之的话,容器启动后,你会访问不到实际的服务。
- Dockerfile中EXPOSE的端口可以不是应用的yml中写的端口吗,当然也可以,且容器启动后不影响访问服务,只是这个端口也会出现在容器信息的PORTS中(使用docker ps查看时),如下
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d6af70b2683 myfuyang:0.1 "java -jar app.jar" 22 minutes ago Up 22 minutes 8089/tcp, 0.0.0.0:8080->2002/tcp nice_poincare
7 总结
本文介绍了将 Spring Boot 工程打为 Docker 镜像及创建容器执行的流程。先构建项目生成 jar 文件,创建 Dockerfile 并设置基础镜像、工作目录等,构建镜像后运行容器,还阐述了 yml 配置、Dockerfile 暴露端口与 docker run 端口映射的作用及关系。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。