《SpringBoot 3:入门与应用实战》第 14 章 打包与部署 制作 Docker 镜像 阅读笔记 43

《SpringBoot 3:入门与应用实战》第 14 章 打包与部署 制作 Docker 镜像 阅读笔记 43

Docker 是一个开源的容器引擎,是当下容器虚拟化的主流选择,它可以为应用创建一个可移植的独立容器。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 。构建成功的效果如图所示。

bash 复制代码
cd /opt/springboot/
docker build -t springboot-packages:1.0 .

如果此时使用 docker images 命令就可以看到刚构建的镜像,如果要创建一个容器来运行,可以使用 docker run -d --name springboot -p 8080:8080 springboot-packages:1.0 命令,执行完成后将会创建一个后台运行的名称为 springboot 的容器,且对外暴露 8080 端口提供服务。

bash 复制代码
docker images
docker run -d --name springboot -p 8080:8080 springboot-packages:1.0
docker ps

14.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。

xml 复制代码
<build>
    <finalName>springboot</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.2.2</version>
            <configuration>
                <imageName>springboot:${project.version}</imageName>
                <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
                <resources>
                    <resource>
                        <targetPath>/</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${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 的应用。

相关推荐
MrSYJ42 分钟前
Network Namespace 到底是个啥,别人再问你告诉他
docker·云原生·kubernetes
噜~噜~噜~1 小时前
操作系统笔记-2.4.1 死锁的概念
笔记·操作系统
程序员老赵1 小时前
Docker 部署 Rocky Linux:轻松搭建 RHEL 兼容企业级基础镜像平台
linux·后端·docker
血小板要健康1 小时前
队列 + 宽搜(BFS):二叉树层序遍历 算法总结
java·数据结构·笔记·算法·leetcode·宽度优先
youm20031 小时前
【学习笔记】认识NoSQL——非关系型数据库
笔记·学习·nosql
神明不懂浪漫2 小时前
【第二章】库、表、增删改查操作
开发语言·数据库·经验分享·笔记
xiaoqiMikko2 小时前
七条 advisory 各给了一个修复版,而一次修完的那个数字一条都没写
java·spring boot
凯哥Java3 小时前
System.setProperty 的正确姿势:Spring Boot 启动类里的“缺省值“魔法
java·spring boot·后端
浔溺3 小时前
al+大数据每日学习笔记33
大数据·笔记·学习