在把应用打包成 Docker
镜像的时候,需要两个文件,一个是 SpringBoot
应用的打包文件,也就是一个可执行的 jar
文件,第二个是构建 Docker
镜像的文件 Dockerfile
。
通过 Dockerfile
中描述的信息,把 jar
文件加入到一个基础镜像中,然后重新打包成新的镜像,这个新的镜像就是我们的 SpringBoot
应用 Docker
镜像。
Dockerfile
描述镜像打包过程,在这个文件中明确 基础镜像、把jar加入到镜像、启动jar的Java命令
如果没有现成可用的可执行jar文件,则需要从一个项目中通过项目源码把项目打包成一个可执行的jar
文件。如果已经有一个可执行的jar
文件则可以跳过此步骤。
通过 Maven 管理的项目可执行以下命令:
mvn clean package -Dmave.test.skip=true -DskipTests
执行完该命令后,在项目的 target/
路径下会有一个jar文件 spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar
该jar文件为Java
的可执行jar
文件。可以通过在target/
路径下执行Java
命令来验证这个jar
文件是否正常
java -jar spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar
如果jar
文件无误,看到 SpringBoot
启动成功提示:
通过第一步,我们已经拿到一个可执行的 jar
文件,那么第二步就需要编写 Dockerfile
来描述如何去构建一个新的镜像。在项目路径下新建一个Dockerfile
文件,然后写入以下内容:
FROM java:8-alpine
ADD target/spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar ./
EXPOSE 8080
ENTRYPOINT ["java","-jar","spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar"]
这是一个最简单的 Dockerfile
文件,共有4行。
FROM [image-name:tag]
设置一个基础镜像,这里是要把 SpringBoot
应用打包成镜像,因此需要一个Java
环境,java:8-alpine
镜像是一个精简的Java环境镜像,其镜像体积比java:8
要小很多,但是提供了同样的环境。ADD [source file or dir] [directory]
在 java:8-alpine
镜像的基础上把某个文件添加到指定的路径中EXPOSE [port]
声明这个镜像使用哪个端口对外提供服务ENTRYPOINT [commands...]
容器启动时执行的命令至此,已经编写好构建镜像所需的 Dockerfile
文件
在第一步拿到一个可执行的jar
文件,第二步编写好构建镜像的Dockerfile
文件,此时可以使用docker
命令来构建一个镜像了。
在项目路径下执行镜像打包命令:
# 命令格式:docker build -t [镜像名称] [Dockerfile文件所在路径]
docker build -t spring-boot-app .
此时就把SpringBoot
应用成功的打包成了docker
镜像。可以通过以下命令来查看当前系统中所有的镜像列表:
docker images
镜像是一个只读的状态,容器是镜像的运行状态,是可写的,它是在镜像层上添加一个读写层,可以通过以下命令指定某个镜像运行一个容器:
docker run -it -p 8081:8080 spring-boot-app
# 命令格式:docker run [参数列表] [镜像名称:镜像标签]
# 如果未指定镜像标签,则默认为latest标签,表示最新的镜像
# -it 说明:-i 打开STDIN,用于控制台交互;-t 分配tty设备,该可以支持终端登录,默认为false
# -it 参数起到的作用,当我们使用 Ctrl+C 组合键时可以停止容器关闭应用,否则容器将会一直在运行
# -p 参数表示把主机的8081端口映射到容器的8080端口,实际上也就是端口转发,当访问本机127.0.0.1的8081端口时会把数据转发到这个容器的8080端口。如果不设置端口映射,想要访问的时候需要访问 http://容器IP:容器端口号/
此时可以在控制台看到启动SpringBoot应用时打印的日志信息,表示打包的这个镜像是正常可用的。我们可以通过在浏览器访问:http://127.0.0.1:8081/
来检查应用是否可访问。
这个问题很大可能会在生产环境中遇到,因为生产环境是使用Linux系统,docker也运行在Linux系统上,容器时间有可能会变成UTC
时区时间,此时Java应用获取到的时间就比北京时间晚了8个小时,与其他系统对接(比如对接数据库)的时候会因为时间问题而产生时间错乱、不一致,或者页面展示数据的时间不准确的问题。
关于该问题,有两种解决方案,一种是配置环境变量,一种是修改容器内/etc/timezone
和/etc/localtime
文件内容。
一般只要给容器添加表示时区的环境变量即可,把时区的环境变量设置为上海Asia/Shanghai
。
我们在Dockerfile
文件中加入环境变量来指定容器的时区:
FROM java:8-alpine
ENV TZ Asia/Shanghai
ADD target/spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar ./
EXPOSE 8080
ENTRYPOINT ["java","-jar","spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar"]
docker run -it -p 8081:8080 -e TZ="Asia/Shanghai" spring-boot-app
通过在 Dockerfile
文件描述构建镜像的过程中修改容器内文件信息
FROM java:8-alpine
RUN ln -sf /usr/share/zoneinfo/Asia/shanghai /etc/localtime
RUN echo "Asia/shanghai" > /etc/timezone
ADD target/spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar ./
EXPOSE 8080
ENTRYPOINT ["java","-jar","spring-boot-docker-deploy-0.0.1-SNAPSHOT.jar"]
或者通过启动命令直接挂载当前主机(需要当前主机时区正常)的文件到容器内:
docker run -it -p 8081:8080 -v /etc/timezone:/etc/timezone -v /etc/localtime:/etc/localtime spring-boot-app
在使用docker运行应用的时候,我们应用可能会产生一些文件和数据需要永久存储的,而不是删除容器后导致数据同时丢失,要做到即使删除容器、升级镜像版本也不会影响我们的数据。
此时需要设置在容器上面挂载一个目录,把这个目录的所有数据保存到主机中。
docker run -it -p 8081:8080 -v /var/www/data:/app/log spring-boot-app
此处用到一个 -v
参数,这个参数把当前主机上的 /var/www/data
目录挂载到容器的 /app/log
路径,当容器应用在容器内的 /app/log
路径下写入数据时,会把数据保存到我们主机的 /var/www/data
路径下。
通过Maven插件来构建Docker镜像的时候,就只需要在pom.xml
文件中配置好镜像信息,然后执行Maven命令即可构建镜像。
这里用到的 com.spotify
的docker-maven-plugin
插件,当第一次使用该插件的时候需要下载插件依赖,由于网络原因,这个可能会花很久的时间。
需要在pom.xml
文件中配置插件信息:
<build>
<plugins>
<!-- docker的maven插件,官网:https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<!-- 设置构建的应用镜像名称,注意 imageName 一定要是符合正则 [a-z0-9-_.] 的,否则构建不会成功 -->
<!-- 详见:https://github.com/spotify/docker-maven-plugin -->
<imageName>${project.artifactId}</imageName>
<baseImage>java:8-alpine</baseImage>
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
<!-- 设置容器内的工作目录 -->
<workdir>/app</workdir>
<exposes>8080</exposes>
<env>
<TZ>Asia/Shanghai</TZ>
</env>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"]
</entryPoint>
<!-- 指定 Dockerfile 所在的路径 -->
<!-- <dockerDirectory>${project.basedir}</dockerDirectory> -->
<resources>
<resource>
<targetPath>.</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
在这里,设置了构建的镜像名称为${project.artifactId}
表示当前项目的artifactId
信息,每个标准的Maven项目都会有三个基本信息:
<groupId>com.timeloit.gx</groupId>
<artifactId>spring-boot-docker-deploy</artifactId>
<version>0.0.1</version>
每个镜像都会有一个镜像标签 imageTage
,可以用这个镜像标签来表示当前镜像对应的应用版本信息,在插件配置中分配了两个标签,分别为${project.version}
和latest
,前者当前Maven项目的版本,后者表示镜像的最新版本,表示构建的这个镜像的版本是 0.0.1
同时也是一个最新的版本。
此时执行以下Maven命令即可构建一个Docker镜像
mvn docker:build
在执行 Maven Docker 构建镜像命令的时候,需要先执行 Maven 打包命令,先生成一个jar文件才能进行Docker镜像打包,否则打包出来的镜像将无法正常运行。
此时可以把Docker镜像构建命令与Maven打包jar命令结合起来,在打包项目的时候同时构建一个Docker镜像,这时候需要修改Maven Docker插件配置。
<build>
<plugins>
<!-- docker的maven插件,官网:https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<!-- start:本次添加内容 -->
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<!-- end:本次添加内容 -->
<configuration>
<!-- 设置构建的应用镜像名称,注意 imageName 一定要是符合正则 [a-z0-9-_.] 的,否则构建不会成功 -->
<!-- 详见:https://github.com/spotify/docker-maven-plugin -->
<imageName>${project.artifactId}</imageName>
<baseImage>java:8-alpine</baseImage>
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
<!-- 设置容器内的工作目录 -->
<workdir>/app</workdir>
<exposes>8080</exposes>
<env>
<TZ>Asia/Shanghai</TZ>
</env>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"]
</entryPoint>
<!-- 指定 Dockerfile 所在的路径 -->
<!-- <dockerDirectory>${project.basedir}</dockerDirectory> -->
<resources>
<resource>
<targetPath>.</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。