---
url: /diary/hdb8szqk/index.md
description: 使用 Docker 和 Dockerfile 将 Spring Boot 应用打包成镜像并部署到云端镜像仓库的完整流程。
---
> Spring Boot 项目打包Docker镜像并push到云端镜像仓库

## 前言

首先来了解下什么是`Dockerfile`：

`Dockerfile`是一个包含命令和指令的脚本文件，用于构建`Docker`镜像。它包含了构建镜像的全部指令，可以使得从头开始构建一个完整的`Docker`镜像变得十分容易。

以下是`Dockerfile`的使用方法：

1. 创建`Dockerfile`文件：在项目目录中使用文本编辑器创建`Dockerfile`文件并编写相应的指令。
2. 编写`Dockerfile`指令：使用`Dockerfile`指令来构建镜像，例如`FROM`、`RUN`、`COPY`、`CMD`等等。
3. 构建镜像：使用`docker build`命令构建镜像。例如：`docker build -t imagename .`
4. 运行容器：使用`docker run`命令运行容器。例如：`docker run -d -p 8080:8080 imagename`。
5. 打包和分享镜像：可以使用`docker save`和`docker load`命令来打包和分享镜像。

以上是对dockerfile的一般理解和使用方法。

## 前提

* 一个正常可打包的`Spring Boot` `web` 项目
* 一个可用的云端镜像仓库
* 一个可以本地连接使用的`docker`

## 正文

### 创建Dockerfile

首先在项目的根目录里创建`Dockerfile`文件，通过这个文件我们可以将我们的`jar`包打包进`Docker`镜像，随着镜像启动的同时，将我们的`jar`包也启动

```dockerfile
# 该镜像需要依赖的基础镜像
FROM openjdk:8u322-oracle
# 将当前目录下的jar包复制到docker容器的/目录下
ADD target/my-demo.jar /my-demo.jar
# 运行过程中创建一个my-demo.jar文件
RUN bash -c 'touch /my-demo.jar'
# 声明服务运行在10316端口
EXPOSE 10318

# 指定docker容器启动时运行jar包
ENTRYPOINT ["java","-jar","/my-demo.jar","-Dfile.encoding=utf-8"]
# 指定维护者的名字
MAINTAINER xinwei
```

以上的操作是使用`jdk8`版本的程序，如果使用其他如`jdk17`版本，可以直接改变`jdk`的镜像版本即可。

这样我们就可以利用命令`docker build -t my-demo .`将程序打包在本地里，随着容器启动，容器内的`jar`包也会启动。但是这只是在我们的本地打包成`docker`镜像，如果手动迁移镜像到云服务器上，或者项目运行的服务器和镜像服务器不是同一台机器，手动操作就很繁琐了，故此继续改造`maven`，使得`maven`可以直接打包成镜像并上传到仓库。

### 改造Maven

首先介绍一个打包`docker`镜像的`maven`插件——`Docker Maven Plugin`，这时一个旨在为Java应用程序的开发人员提供方便和高效的Docker容器化过程的插，它允许Maven用户使用标准Maven构建方式来创建和构建Docker镜像，并支持将配置文件和资源文件打包到Docker镜像中，以便于部署和运行Java应用程序。

Docker Maven Plugin提供了一系列目标和插件，包括：

1. `docker:build`：用于构建Docker镜像的目标。
2. `docker:start`和`docker:stop`：用于启动和停止Docker容器的目标。
3. `docker:push`：用于将Docker镜像推送到远程仓库的目标。
4. `dockerfile:build`：使用自定义Dockerfile文件构建Docker镜像的目标。
5. `dockerfile:tag`：用于将Docker镜像标记为指定的标签的目标。
6. `dockerfile:push`：将Docker镜像推送到指定的Docker仓库的目标。

`Docker Maven Plugin`还提供了一些其他功能，如能够自动化地在Docker容器中运行Java应用程序，并提供了一些命令行参数和配置选项，以帮助开发人员定制和管理`Docker`镜像和容器。
github地址：[fabric8io/docker-maven-plugin: Maven plugin for running and creating Docker images (github.com)](https://github.com/fabric8io/docker-maven-plugin)

将其改造在`pom`文件里：

```xml :collapsed-lines
<!--重启时重新打包-->
    <build>
        <finalName>${project.artifactId}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!--开启过滤，用指定的参数替换directory下的文件中的参数-->
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.9.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.40.1</version>
                <configuration>
                    <!-- Docker 推送镜像仓库地址-->
                    <pushRegistry>swr.cn-south-1.xxxxcloud.com</pushRegistry>
                    <images>
                        <image>
                            <!--由于推送到私有镜像仓库，镜像名需要添加仓库地址-->
                            <name>swr.cn-south-1.xxxxcloud.com/${jenkins.service.name}/${project.name}</name>
                            <!--定义镜像构建行为-->
                            <build>
                                <dockerFileDir>${project.basedir}</dockerFileDir>
                                <tags>
                                    <tag>latest</tag>
                                    <tag>%T</tag>
                                </tags>
                            </build>
                        </image>
                    </images>
                </configuration>
            </plugin>
        </plugins>
    </build>
```

其中，

```xml
<tags>
            <tag>latest</tag>
            <tag>%T</tag>
       </tags>
```

这里的意思是同时打包2个镜像，一个镜像使用版本`latest`，一个镜像使用时间戳来标记版本，这样，我们的流水线只需要使用`image:latest`即一直使用`latest`版本即可，因为相同版本的镜像会覆盖，这样我们的`latest`就会保持最新，同时还会有一个时间戳版本的镜像用于回滚。

还有一个要注意的点就是使用这个插件的机器需要提前登录镜像仓库，即使用`docker login xxx`命令的操作，这个操作各云服务镜像仓库都给了详细的说明，这样我们就获取了打包到云上仓库的功能了，配合流水线启动美滋滋。

最后我们只需要在流水线脚本或者本地机器上使用`mvn clean package docker:build docker:push`命令即可完成`docker`镜像从打包到推送的全过程了。
