SpringBoot 项目配置打包 docker 镜像并推送

default

概要

SpringBoot 项目配置打包 docker 镜像并推送到阿里云镜像仓库

系统:Win10

Docker: Docker Desktop For Windows

SpringBoot: 2.6.2


路线

安装并配置Docker

安装

Install Docker Desktop on Windows | Docker Docs

配置

“Setting” - “General “- 勾选 “Expose daemon on tcp://localhost:2375 without TLS”

测试

1
docker -H 127.0.0.1:2375 info

配置阿里云镜像仓库

容器镜像服务 (aliyun.com)

新建个人实例 - 创建命名空间

操作指南:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 登录阿里云Docker Registry
docker login --username=*** registry.cn-hangzhou.aliyuncs.com

# 从Registry中拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/workspace_name/[镜像名称]:[镜像版本号]

# 将镜像推送到Registry
docker login --username=*** registry.cn-hangzhou.aliyuncs.com
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/workspace_name/[镜像名称]:[镜像版本号]
docker push registry.cn-hangzhou.aliyuncs.com/workspace_name/[镜像名称]:[镜像版本号]

SpringBoot 项目

镜像选择(slim 是经过压缩的镜像,存在一定风险;alpine经常存在兼容性问题,不建议使用)

镜像稳定优先:

  1. 优先选择 openjdk:8 或者 openjdk:11;
  2. 其次,openjdk:8-jre 或者 openjdk:11-jre;
  3. 其次,openjdk:8-jre-slim 或者 openjdk:11-jre-slim;

镜像大小优先:

  1. 优先选择 openjdk:8-jre-slim,或者 openjdk:11-jre-slim;
  2. 如果抛出异常 Bean 无法注入,则需要换成 jdk 环境 openjdk:8-slim 或者 openjdk:11-jre-slim(也可以选择该大版本下更新的版本号,如: openjdk:11.0.11-slim );
  3. 其次,选择 openjdk:8-slim 或者 openjdk:11-slim;
  4. 其次,选择 openjdk:8 或者 openjdk:11;

spring-boot-maven-plugin 官方插件

官方插件自己规定好了基础镜像(docker.io/paketobuildpacks/builder:base),简单方便,但是镜像拉取很慢,可操作性差。

SpringBoot 版本要求大于 2.4.0

pom.xml 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <!--配置镜像名称-->
            <name>registry.cn-hangzhou.aliyuncs.com/gear-repo/${project.name}:${project.version}</name>
            <!--镜像打包完成后自动推送到镜像仓库-->
            <publish>true</publish>
        </image>
        <docker>
            <!--Docker远程管理地址-->
            <host>http://127.0.0.1:2375</host>
            <!--不使用TLS访问-->
            <tlsVerify>false</tlsVerify>
            <!--Docker推送镜像仓库配置-->
            <publishRegistry>
                <!--推送镜像仓库用户名-->
                <username>***</username>
                <!--推送镜像仓库密码-->
                <password>***</password>
                <!--推送镜像仓库地址-->
                <url>registry.cn-hangzhou.aliyuncs.com/gear-repo/</url>
            </publishRegistry>
        </docker>
    </configuration>
</plugin>
打包推送
1
2
3
4
# 双击SpringBoot插件的`build-image`命令即可一键打包并推送到镜像仓库

# 或者本地命令
mvn spring-boot:build-image

docker-maven-plugin(io.fabric8)

推送镜像仓库的账号密码配置有多种方式(以下按优先级从高到低):

  1. 从外部提供系统属性docker.username和docker.password。

  2. 从外部提供系统属性registry.username和registry.password。

  3. 在pom文件中配置

    1
    2
    3
    4
    5
    6
    7
    
    <configuration>
        ...
    	<authConfig>
          <username>jolokia</username>
          <password>s!cr!t</password>
        </authConfig>
    </configuration>
    
  4. 在~/.config/kube中使用OpenShift配置

  5. 使用~/.m2/settings.xml中的配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    <servers>
        ...
    	<server>
            <!-- docker-maven-plugin(farbric)推送镜像到远程仓库需要此配置 -->
            <id>registry.cn-hangzhou.aliyuncs.com</id>
            <username>gearing</username>
            <password>***</password>
        </server>
    </servers>
    
  6. 使用命令行 docker 登录,凭证会记录到 ~/.docker/config.json 中

    1
    
    docker login --username=gearing registry.cn-hangzhou.aliyuncs.com
    

详情见 fabric8io/docker-maven-plugin

pom.xml 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.33.0</version>
    <configuration>
        <!-- Docker 远程管理地址-->
        <dockerHost>http://127.0.0.1:2375</dockerHost>
        <images>
            <image>
                <!--由于推送到私有镜像仓库,镜像名需要添加仓库地址-->
                <name>registry.cn-hangzhou.aliyuncs.com/gear-repo/${project.name}:${project.version}
                </name>
                <!--定义镜像构建行为-->
                <build>
                    <!--定义基础镜像-->
                    <from>openjdk:8-jre</from>
                    <args>
                        <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                    </args>
                    <!--定义哪些文件拷贝到容器中-->
                    <assembly>
                        <!--定义拷贝到容器的目录-->
                        <targetDir>/</targetDir>
                        <!--只拷贝生成的jar包-->
                        <descriptorRef>artifact</descriptorRef>
                    </assembly>
                    <!--定义容器启动命令-->
                    <entryPoint>["java", "-jar","/${project.build.finalName}.jar", "$JAVA_OPTS"]
                    </entryPoint>
                    <!--定义维护者-->
                    <maintainer>guoyingdong</maintainer>
                </build>
            </image>
        </images>
        <authConfig>
          <username>gearing</username>
          <password>***</password>
        </authConfig>
    </configuration>
    <executions>
        <!--如果想在项目打包时构建镜像添加-->
        <execution>
            <id>build-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
                <goal>push</goal>
            </goals>
        </execution>
    </executions>
</plugin>
打包推送
1
2
3
4
# 直接点击 idea 的 package

# 或者执行以下命令
mvn package

dockerfile-maven-plugin(com.spotify)

pom.xml 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>dockerfile-maven-plugin</artifactId>
  <version>${dockerfile-maven-version}</version>
  <executions>
    <execution>
      <id>default</id>
      <goals>
        <goal>build</goal>
        <goal>push</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <repository>spotify/foobar</repository>
    <tag>${project.version}</tag>
    <buildArgs>
      <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
    </buildArgs>
  </configuration>
</plugin>
dockerfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
FROM openjdk:8-jre
MAINTAINER David Flemström <dflemstr@spotify.com>

ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"]

# Add Maven dependencies (not shaded into the artifact; Docker-cached)
ADD target/lib           /usr/share/myservice/lib
# Add the service itself
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar
打包推送
1
2
3
4
5
# idea 双击 package
# 或者命令
mvn package
# 或者
mvn dockerfile:build

服务器端创建容器并运行

docker-compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
version : '3'

services :
  general-data-platform:
    image: registry.cn-hangzhou.aliyuncs.com/gear-repo/[镜像名称]:[镜像版本号]
    container_name: app-dev
    ports: 
      - "8888:8888"
    restart: always
    # 覆盖容器中的执行命令,方便配置文件的映射。指定运行 profile 为 dev。-Dspring.config.location 为文件夹时,必须以"/"结尾
    entrypoint: java -jar -Dspring.profiles.active=dev -Dspring.config.location=/app-config/ app.jar
    # 配置文件放在 /app-config 路径下,需包含 application.yml 和 application-dev.yml
    volumes: 
      - /data/docker/app/config:/app-config
    networks:
      - dev-network

networks:
  dev-network:
  	# 使用的是外部创建的network,所以下面会标明 external
    external: true
1
2
cd /data/docker/app/
docker-compose up -d

参考

【1】Manuals | Docker Docs

【2】三种自动化构建Docker镜像的Maven插件使用 - 简书 (jianshu.com)

Gear(夕照)的博客。记录开发、生活,以及一些不足为道的思考……