
《SpringBoot 3入门与应用实战》第 14 章 打包与部署 制作 Docker 镜像 阅读笔记 43Docker 是一个开源的容器引擎是当下容器虚拟化的主流选择它可以为应用创建一个可移植的独立容器。Docker 的核心思想是一次构建处处运行这与 Java 的一次编译处处执行相似。Docker 有启动快、占用资源少、容器隔离等优点这使得 Docker 成为部署和运行基础组件、应用程序乃至微服务的不二选择。本节中会将工程打包为一个 Docker 镜像并使其在 Docker 中运行。14.3.1 Docker 基础Docker 的安装方式非常简单在 Linux 系统中只需要简单几条指令。笔者使用 CentOS 7 进行操作。搭建 Docker 环境一个 Docker 实例中可以下载和存放很多个镜像一个镜像又可以运行多个容器实例这组概念比较类似于 Java 中的类和对象。Docker 中的每个容器之间都是环境隔离的一个 Docker 容器可以简单理解为一个小微 Linux 系统的虚拟机。通常使用 Docker 的指令完成镜像的搜索、下载拉取、删除以及对容器的创建、启停、移除等操作常用的Docker 操作指令如表所示。操作类别核心指令作用与说明镜像管理docker pull 镜像名:标签从镜像仓库拉取指定镜像到本地。docker images查看本地所有已下载的镜像列表。docker build -t 名称:标签 路径根据 Dockerfile 构建自定义镜像。docker rmi 镜像名/ID删除本地指定的镜像。docker save / docker load将镜像导出为 tar 压缩包或从压缩包导入镜像常用于离线迁移。容器生命周期docker run [选项] 镜像创建并启动新容器。常用参数-d后台运行、-p端口映射、--name指定名称。docker ps/docker ps -a查看正在运行的容器加-a可查看包含已停止的所有容器。docker start / stop / restart启动、优雅停止或重启指定的容器。docker rm 容器名/ID删除已停止的容器加-f可强制删除运行中的容器。容器交互与调试docker exec -it 容器 /bin/bash进入正在运行的容器内部开启交互式终端。docker logs -f 容器名/ID查看容器日志-f参数可实时追踪最新日志。docker cp 源路径 目标路径在宿主机与容器之间双向复制文件或目录。网络管理docker network ls查看当前 Docker 环境中的所有网络。docker network create 网络名创建自定义网络常用于实现多容器间的内部通信。docker network connect 网络 容器将运行中的容器连接到指定的网络。数据卷管理docker volume create 卷名创建用于数据持久化的数据卷。docker run -v 卷名:容器路径在启动容器时挂载数据卷确保容器删除后数据不丢失。docker volume inspect 卷名查看数据卷的详细信息包括在宿主机上的实际存储路径。系统维护与清理docker system prune清理所有已停止的容器、未使用的网络及悬空镜像。docker system prune -a深度清理删除所有未使用的镜像和停止的容器谨慎使用。docker stats实时查看容器的 CPU、内存等资源使用情况。14.3.2 Dockerfile 文件使用 Dockerfile 文件可以将可执行 jar 包制作为 Docker 镜像为此需要编写一个 Dockerfile 文件首先要了解 Dockerfile 文件的一些指令如表所示。指令类别核心指令作用与说明基础与元数据FROM指定基础镜像必须是 Dockerfile 中的第一条非注释指令。LABEL为镜像添加键值对形式的元数据如维护者信息用于替代已弃用的MAINTAINER。ARG定义仅在构建阶段docker build有效的变量不会保留在最终镜像中。文件与目录操作COPY将本地构建上下文中的文件或目录复制到镜像中官方推荐优先使用。ADD功能类似COPY但额外支持自动解压本地 tar 包及从 URL 下载资源。WORKDIR设置后续指令的工作目录若目录不存在会自动创建。VOLUME声明数据卷挂载点主要用于数据持久化或容器间数据共享。环境配置与构建RUN在构建过程中执行命令如安装依赖每执行一次会生成一个新的镜像层。ENV设置环境变量在构建期和容器运行时均持久化生效。运行阶段控制EXPOSE声明容器运行时监听的端口仅为文档说明实际端口映射需在docker run时指定。CMD定义容器启动时的默认执行命令可被docker run后的命令行参数覆盖。ENTRYPOINT设置容器的主程序入口不易被覆盖通常与CMD配合使用以提供默认参数。高级与状态检查USER指定运行后续指令的用户身份生产环境推荐使用非 root 用户以增强安全性。HEALTHCHECK定义周期性检查容器健康状态的命令帮助 Docker 判断容器是否正常工作。14.3.3 使用 Dockerfile 构建镜像使用 Dockerfile 文件构建镜像时需要先准备好可执行 jar 包把 14.1 节中打包好的 jar 包上传到 Linux 主机中之后编写一个 Dockerfile 文件。简单解释这段 Dockerfile 的含义使用 FROM 指令声明当前 Spring Boot 应用依赖 eclipse-temurin 镜像这是一个基于 JDK 17 的较新的开源免费镜像EXPOSE 8080 代表指定当前镜像最终会在内部暴露 8080 端口使用 WORKDIR 和 VOLUME 分别指定工作目录和挂载目录使用ADD 命令将宿主机的 springboot.jar 复制到 Docker 镜像中最后使用 ENTRYPOINT 指定启动这个 jar 包。FROM eclipse-temurin:17.0.9_9-jre EXPOSE 8080 WORKDIR /opt/springboot/work VOLUME /opt/springboot/volume ADD springboot.jar /opt/springboot/springboot.jar ENTRYPOINT [java, -jar, /opt/springboot/springboot.jar]编写完这个 Dockerfile 文件后将其复制到 Linux 主机上放到与 springboot.jar 同一个目录下即可。之后使用命令行进入 /opt/springboot/ 目录下执行 docker build -t springboot-packages:1.0 . 命令即可完成 Docker 镜像的构建构建的镜像名为 springboot-packages版本号为 1.0 。构建成功的效果如图所示。cd/opt/springboot/dockerbuild-tspringboot-packages:1.0.如果此时使用 docker images 命令就可以看到刚构建的镜像如果要创建一个容器来运行可以使用 docker run -d --name springboot -p 8080:8080 springboot-packages:1.0 命令执行完成后将会创建一个后台运行的名称为 springboot 的容器且对外暴露 8080 端口提供服务。dockerimagesdockerrun-d--namespringboot-p8080:8080 springboot-packages:1.0dockerps14.3.4 使用 Maven 插件构建镜像敏锐的读者可能对于上面的内容察觉到一点使用 Dockerfile 创建镜像时需要每次先使用 Maven 打包之后再配合 Dockerfile 完成镜像构建能不能将这两者合并以减少工作量答案是可以的Maven 中有一个 Spotify 公司提供的一次性完成打包和镜像构建的插件docker-maven-plugin。下面来演示一下 docker-maven-plugin 插件的使用。找到 pom.xml 文件在 spring-boot-maven-plugin 插件的下面直接添加 docker-maven-plugin 插件的坐标并配置几个必需的配置项即可如代码所示。简单解释一下这些配置项的含义imageName 指定了本次制作镜像的名称和版本号类似于 14.3.3 节中 docker build 命令中指定的 -t参数dockerDirectory 指定了当前 Dockerfile 文件的位置这里选择放到 src/main/docker 目录下 标签中声明的是将哪些文件打包到镜像中很明显是通过 mvn package 命令得到的可执行 jar 包所以按照代码的方式就可以得到唯一的 jar 文件。另外注意一点为了与Dockerfile 中的 ADD 命令呼应在 标签中声明一个 springboot这样打包产生的 jar 文件名称就会变成springboot.jar。buildfinalNamespringboot/finalNamepluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/pluginplugingroupIdcom.spotify/groupIdartifactIddocker-maven-plugin/artifactIdversion1.2.2/versionconfigurationimageNamespringboot:${project.version}/imageNamedockerDirectory${project.basedir}/src/main/docker/dockerDirectoryresourcesresourcetargetPath//targetPathdirectory${project.build.directory}/directoryinclude${project.build.finalName}.jar/include/resource/resources/configuration/plugin/plugins/build编写完成后接下来就可以执行命令一次性完成打包和镜像构建但是请读者注意要想让这个 Maven 插件发挥作用需要在执行打包和镜像构建的主机上安装 Docker 环境。当前使用的 Windows 主机在国内安装 Docker 环境非常麻烦所以需要将当前工程的全部代码复制到 Linux 主机上并在 Linux 主机上配置 JDK 和 Maven 环境之后才能完成打包和镜像构建。将工程复制到 Linux 主机后执行 mvn clean package docker:build 命令Maven 会先完成打包动作之后根据提供的 Dockerfile 文件构建一个名为 springboot、版本号为 1.0-SNAPSHOT 的镜像可以使用 docker images 命令查看当前镜像。至此使用 Maven 插件完成 Docker 镜像构建的演示完毕。14.4 小结本章介绍了 Spring Boot 应用打包与部署的运行方式。项目开发完毕后必定要打包部署到生产环境运行Spring Boot 提供了非常方便的打包和运行方式同时兼顾了基于独立 jar 包运行和借助独立部署的 Servlet 容器运行的方式。此外还可以制作 Docker 镜像使用 Docker 容器的方式部署和运行 Spring Boot 的应用。