一、背景

1、优化前:

目前构建docker镜像都是先执行mvn clean package打包之后,将target目录下的jar包放到服务器上,再通过Dockerfile去build成镜像,步骤多,而且每次都需要登录服务器进行操作,十分麻烦。

2、优化后:

在Spring Boot项目中引入docker-maven-plugin进行相关配置,之后就可以在项目根目录下执行mvn clean package docker:build -DpushImage,就可以在服务器上的docker生成镜像,并且推送到远程仓库上,十分方便,不用每次都登录服务器进行操作。

在进行项目引入docker-maven-plugin之前,先进行docker的配置,使我们能够通过2375端口访问到docker。

二、配置docker,开放2375端口

Docker的2375端口是默认关闭的,如果我们要使用到它,就需要进行以下的配置:

1、安装有docker的服务器,修改docker.service文件:

vi /etc/systemd/system/docker.service

具体文件所在地,得看你安装docker的位置,如果不知道自己安装在哪里了,执行以下指令去查找:

sudo find / -name docker.service

2、修改docker.service

找到文件以下内容:

ExecStart=/usr/bin/dockerd

修改为:

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

3、重启docker服务

systemctl daemon-reload
systemctl restart docker

4、查看端口是否开启

netstat -anp | grep 2375

如果没有被占用,就什么都不显示

5、如果通过以上配置,发现2375没有开启的话,那么请尝试修改daemon.json文件:

vi /etc/docker/daemon.json

具体文件所在地,得看你安装docker的位置,如果不知道自己安装在哪里了,执行以下指令去查找:

sudo find / -name daemon.json

在配置文件添加上hosts项:

{
  "insecure-registries":["xx.xx.xx.xx:5000"],
  "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}

通过以上操作,基本可以打开2375端口,并且可以通过该端口连接上docker,如果还是不行,那么请通过网络查找原因及解决方法了哈。

注意:以上开发的2375端口访问docker的方式是不安全的,如果想要安全的访问,请自行百度了解。

三、搭建docker registry,镜像推送的仓库

一般我们的镜像除了放在docker上,还可以将其推送到docker registry上,其他服务器上的docker就可以在该docker registry上拉取镜像。

关于docker registry的安装及配置,请参考我的另外一篇博客,这里就不重复去写了:

https://blog.csdn.net/Staba/article/details/124550444?spm=1001.2014.3001.5502

四、项目配置docker-maven-plugin

  1. 在父工程pom.xml配置如下,如果你不愿意将插件在父工程的pom.xml中进行管理与配置,那么就将以下配置去掉pluginManagemt标签,然后放在子工程中的pom.xml中即可

<!--你的其他配置-->

<profiles>
    <profile>
        <!--默认激活配置-->
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <imageVersion>${project.version}</imageVersion>
            <tag.suffix>dev</tag.suffix>
            <docker.host>http://开发环境服务器ip:2375</docker.host>
            <docker.registry>开发环境docker registry服务器ip:5000</docker.registry>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <imageVersion>${project.version}</imageVersion>
            <tag.suffix>test</tag.suffix>
            <docker.host>http://测试环境服务器ip:2375</docker.host>
            <docker.registry>测试环境docker registry服务器ip:5000</docker.registry>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <imageVersion>${project.version}</imageVersion>
            <tag.suffix>prod</tag.suffix>
            <docker.host>http://生产环境服务器ip:2375</docker.host>
            <docker.registry>生产环境docker registry服务器ip:5000</docker.registry>
        </properties>
    </profile>
</profiles>

<build>
    <pluginManagement>
        <plugins>

            <!—如果是springboot项目,引入这个,否则打的jar包大小不正确-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
            </plugin>
    
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.2.2</version>
                <!--有需求就绑定,不绑定就更加灵活点-->
                <!--<executions>
                    &lt;!&ndash; 当mvn执行install操作的时候,执行docker的build和push &ndash;&gt;
                    <execution>
                        <id>buildAndPush</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                            &lt;!&ndash;                            <goal>push</goal>&ndash;&gt;
                        </goals>
                    </execution>
                </executions>-->
                <configuration>
                    <!--docker build 开始-->
                    <!-- 连接到 带docker环境的linux服务器 编译image -->
                    <dockerHost>${docker.host}</dockerHost>
    
                    <!-- 指定tag版本,可不加,在imageName上指定-->
                    <!-- <imageTags>-->
                    <!--    <imageTag>${project.version}</imageTag>-->
                    <!-- </imageTags>-->
                    <!-- build 时强制覆盖 tag,配合 imageTags 使用 -->
                    <!--<forceTags>true</forceTags>-->
    
                    <!--
                        格式:私有仓库/镜像名称:版本号, 如果要执行push操作, 那么镜像名称必须为私有仓库为前缀,且后缀为版本号,不然无效
                        注意:镜像名称不加:tag, build时会生成latest和你指定版本的两个镜像,加上只生成一个tag为你指定版本的镜像
                    -->
                    <imageName>${docker.registry}/${project.artifactId}:${imageVersion}-${tag.suffix}</imageName>
    
                    <!--指定dockerfile文件路径-->
                    <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
    
                    <!-- 用于指定需要复制的文件,需要包含jar包 -->
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                    <!--docker build 结束-->
    
    
                    <!-- push到 docker hub/registry 开始 -->
                    <!--serverId 这个是配置在maven的setting.xml中hub/registry的登录账户信息,无密码登录则无需配置-->
                    <!--<serverId>docker-registry</serverId>-->
                    <!--docker hub/registry地址-->
                    <registryUrl>${docker.registry}</registryUrl>
                    <!--重试推送次数-->
                    <retryPushCount>3</retryPushCount>
                    <!--推送超时时间-->
                    <retryPushTimeout>2000</retryPushTimeout>
                    <!--是否自動推送到Registry Server, 建議手動推送,开启后build之后就会push,执行mvn时就无需加上-DpushImage -->
                    <!--<pushImage>true</pushImage>-->
                    <!-- push到 docker hub 结束 -->
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>

</build>

如果指定了<serverId>xxx</serverId>,那么请在maven的setting.xml中配置以下信息:

<server>
      <id>xxx</id>
      <username>your username</username>
      <password>your password</password>
      <configuration>
        <email>you email</email>
      </configuration>
</server>

2、子工程引入插件,因为docker相关配置都在父工程中写好了,子工程中无须重复写,只需引入插件

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

3、在<dockerDirectory>标签中指定的路径下创建Dockerfile文件,内容如下:

FROM java
VOLUME /tmp
ENV LANG C.UTF-8 
COPY *.jar app.jar
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 
RUN echo "Asia/Shanghai" > /etc/timezone 
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-Djava.util.Arrays.useLegacyMergeSort=true", "-jar","app.jar"]

4、在子项目根路径上执行mvn clean package -P dev -DimageVersion='1.0.9' docker:build –DpushImage指令,即可将target目录下的jar包构建成镜像,并且推送到docker registry上。

参数解析:

-P dev -> 由于我们在Profile标签中指定了不同环境中使用不同服务器上的docker,所有由该参数指定我们哪个环境的配置生效,默认是dev生效(配置了)。
-DimageVersion='1.0.9' -> 在配置中我们这个属性默认值是当前项目版本,通过该参数指定我们打包镜像的tag最终版本,因为懒的每次去改pom中的version标签,于是自定义一个属性,通过命令行传入版本
docker:build -> 打包完jar之后就会指定docker build指令,将jar包构建成镜像
–DpushImage –> 构建完镜像之后就会将镜像推送到docker registry仓库上
-DpushImageTag -> 如果在<imageTags>中指定了tag,且在<imageName>中没有:tag信息,使用pushImageTag去推送标签指定的tags镜像

当然,如果你懒的去敲docker相关的指令,可以与maven插件的各执行周期绑定,那么就请在executions中进行绑定配置。

通过执行以上的指令,就可以在控制台上看到镜像build的过程以及推送的过程。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐