docker-maven-plugin能有效帮助我们在面对数量众多的微服务项目时,自动化构建和容器化部署,提高部署效率。
docker-maven-plugin文档
dockerfile-maven-plugin文档
禁止转载!!!禁止转载!!!禁止转载!!!
首发地址:https://x.xuux.top
一、修改docker配置
修改宿主机的docker配置,让其可以远程访问
vi /lib/systemd/system/docker.service
# 在ExecStart=后添加配置
‐H tcp://0.0.0.0:2375 ‐H unix:///var/run/docker.sock
修改后配置如下:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
刷新配置重启服务:
# 通知docker服务做出的修改
systemctl daemon-reload
# 重启docker服务
systemctl restart docker
接下来测试一下看是否能连接到docker api
ps -ef | grep docker
[root@localhost ~]# curl -X GET http://192.168.122.22:2375/info
{"ID":"XHRK:S4AH:7YDS:X43Y:BFCZ:XQ5N:VBIV:K6V4:SUVK:VFPM:JJYS:KZBB","Containers":7,"ContainersRunning":4,"ContainersPaused":0,"ContainersStopped":3,"Images":7,"Driver":"overlay2","DriverStatus":[["Backing Filesystem","xfs"],["Supports d_type","true"],["Native Overlay Diff","true"],["userxattr","false"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","ipvlan","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","local","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"KernelMemoryTCP":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":true,"IPv4Forwarding":true,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":false,"NFd":50,"OomKillDisable":true,"NGoroutines":55,"SystemTime":"2021-11-11T15:21:22.728142607+08:00","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","CgroupVersion":"1","NEventsListener":0,"KernelVersion":"3.10.0-957.el7.x86_64","OperatingSystem":"CentOS Linux 7 (Core)","OSVersion":"7","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":[],"AllowNondistributableArtifactsHostnames":[],"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":["https://pee6w651.mirror.aliyuncs.com/"],"Secure":true,"Official":true}},"Mirrors":["https://pee6w651.mirror.aliyuncs.com/"]},"NCPU":2,"MemTotal":2928689152,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"localhost.localdomain","Labels":[],"ExperimentalBuild":false,"ServerVersion":"20.10.7","Runtimes":{"io.containerd.runc.v2":{"path":"runc"},"io.containerd.runtime.v1.linux":{"path":"runc"},"runc":{"path":"runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"d71fcd7d8303cbf684402823e425e9dd2e99285d","Expected":"d71fcd7d8303cbf684402823e425e9dd2e99285d"},"RuncCommit":{"ID":"b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7","Expected":"b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7"},"InitCommit":{"ID":"de40ad0","Expected":"de40ad0"},"SecurityOptions":["name=seccomp,profile=default"],"Warnings":["WARNING: API is accessible on http://0.0.0.0:2375 without encryption.\n Access to the remote API is equivalent to root access on the host. Refer\n to the 'Docker daemon attack surface' section in the documentation for\n more information: https://docs.docker.com/go/attack-surface/","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"]}
1.2 启动失败的问题
启动报错Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
[root@localhost ~]# systemctl start docker
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
[root@localhost ~]# systemctl start docker.service
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
[root@localhost ~]# systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: failed (Result: start-limit) since 四 2021-11-11 14:54:01 CST; 1min 14s ago
Docs: https://docs.docker.com
Process: 23534 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ‐H tcp://0.0.0.0:2375 ‐H unix:///var/run/docker.sock (code=exited, status=1/FAILURE)
Main PID: 23534 (code=exited, status=1/FAILURE)
11月 11 14:54:01 localhost.localdomain systemd[1]: start request repeated too quickly for docker.service
11月 11 14:54:01 localhost.localdomain systemd[1]: Failed to start Docker Application Container Engine.
11月 11 14:54:01 localhost.localdomain systemd[1]: Unit docker.service entered failed state.
11月 11 14:54:01 localhost.localdomain systemd[1]: docker.service failed.
11月 11 14:54:13 localhost.localdomain systemd[1]: start request repeated too quickly for docker.service
11月 11 14:54:13 localhost.localdomain systemd[1]: Failed to start Docker Application Container Engine.
11月 11 14:54:13 localhost.localdomain systemd[1]: docker.service failed.
11月 11 14:54:18 localhost.localdomain systemd[1]: start request repeated too quickly for docker.service
11月 11 14:54:18 localhost.localdomain systemd[1]: Failed to start Docker Application Container Engine.
11月 11 14:54:18 localhost.localdomain systemd[1]: docker.service failed.
[root@localhost ~]# netstat -ano | grep 2375
tcp6 0 0 :::2375 :::* LISTEN off (0.00/0/0)
1.3 解决启动失败
因为修改的是/usr/lib/systemd/system/docker.service
下的服务配置文件:ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
那么就应该加载该目录下的system服务systemctl start docker.service
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl stop docker.service
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
[root@localhost ~]# ps -ef | grep docker
root 47375 18279 0 15:13 pts/0 00:00:00 grep --color=auto docker
[root@localhost ~]# systemctl start docker.service
[root@localhost ~]# systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 四 2021-11-11 15:13:43 CST; 37s ago
Docs: https://docs.docker.com
Main PID: 47559 (dockerd)
CGroup: /system.slice/docker.service
├─47559 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
├─47751 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 6379 -container-ip 172.17.0.2 -container-port 6379
├─47756 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 6379 -container-ip 172.17.0.2 -container-port 6379
├─47783 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -container-ip 172.17.0.3 -container-port 3306
├─47788 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 3306 -container-ip 172.17.0.3 -container-port 3306
├─47822 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 9000 -container-ip 172.17.0.4 -container-port 9000
├─47836 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 9000 -container-ip 172.17.0.4 -container-port 9000
├─47884 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 30443 -container-ip 172.17.0.5 -container-port 443
├─47893 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 30443 -container-ip 172.17.0.5 -container-port 443
├─47924 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 30080 -container-ip 172.17.0.5 -container-port 80
└─47939 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 30080 -container-ip 172.17.0.5 -container-port 80
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.097948827+08:00" level=info msg="ClientConn switching balancer to \"pick_...ule=grpc
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.103540123+08:00" level=info msg="[graphdriver] using prior storage driver: overlay2"
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.109459318+08:00" level=info msg="Loading containers: start."
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.226585154+08:00" level=info msg="Default bridge (docker0) is assigned wit...address"
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.944106192+08:00" level=info msg="Loading containers: done."
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.973773238+08:00" level=info msg="Docker daemon" commit=b0f5bc3 graphdrive...=20.10.7
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.973916900+08:00" level=info msg="Daemon has completed initialization"
11月 11 15:13:43 localhost.localdomain dockerd[47559]: time="2021-11-11T15:13:43.999505683+08:00" level=info msg="API listen on /var/run/docker.sock"
11月 11 15:13:43 localhost.localdomain systemd[1]: Started Docker Application Container Engine.
11月 11 15:14:12 localhost.localdomain systemd[1]: Current command vanished from the unit file, execution of the command list won't be resumed.
Hint: Some lines were ellipsized, use -l to show in full.
二、修改防火墙
其他centos7防火墙配置
我这里是虚拟机,防火墙服务关闭了,所以无需配置下面的信息,生产环境自行配置
[root@localhost ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Docs: man:firewalld(1)
修改防火墙策略,允许访问2375端口:
#开放2375/tcp端口
firewall-cmd --zone=public --add-port=2375/tcp --permanent
#更新防火墙的设置,使上面的修改生效
firewall-cmd --reload
查看防火墙开放状态:
#查看所有打开的端口
firewall-cmd --zone=public --list-ports
三、使用插件
3.1 docker-maven-plugin插件
(1)不使用Dockerfile
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<imageName>${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<baseImage>xuux/small-jre8:1.0</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://192.168.122.22:2375</dockerHost>
</configuration>
</plugin>
执行 build 操作mvn clean package docker:build
执行 build 完成后 push 镜像:mvn clean package docker:build -DpushImage
执行 build 并 push 指定 tag 的镜像mvn clean package docker:build -DpushImageTag
注意:这里必须指定至少一个 imageTag,它可以配置到 POM 中,也可以在命令行指定。
指定方式有两种:
命令行指定如下:
mvn clean package docker:build -DpushImageTags -DdockerImageTags=imageTag_1 -DdockerImageTags=imageTag_2
POM 文件中指定:
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<imageName>${project.artifactId}:${project.version}</imageName>
<baseImage>xuux/small-jre8:1.0</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://192.168.122.22:2375</dockerHost>
<!--指定tag-->
<imageTags>
<imageTag>imageTag_1</imageTag>
<imageTag>imageTag_2</imageTag>
</imageTags>
</configuration>
</plugin>
</plugins>
</build>
(2)使用Dockerfile
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<imageName>${project.artifactId}:${project.version}</imageName>
<!-- 指定 Dockerfile 路径-->
<dockerDirectory>${basedir}/docker</dockerDirectory>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置,也可以写到 Docokerfile 中 -->
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://192.168.122.22:2375</dockerHost>
<!--指定tag-->
<imageTags>
<imageTag>1.0.1</imageTag>
</imageTags>
</configuration>
</plugin>
Dockerfile文件:
FROM xuux/small-jre8:1.0
MAINTAINER xu_ux test@email.com
WORKDIR /opt
CMD ["java", "-version"]
ENTRYPOINT ["java", "-jar", "${project.build.finalName}.jar"]
执行命令:mvn clean package docker:build -DpushImageTag
[INFO] Building image demo:0.0.1-SNAPSHOT
Step 1/5 : FROM xuux/small-jre8:1.0
---> 4fa1f55350fb
Step 2/5 : MAINTAINER xu_ux test@email.com
---> Running in c8b2e5b012c4
Removing intermediate container c8b2e5b012c4
---> 14353903927c
Step 3/5 : WORKDIR /opt
---> Running in d8dfcf2f63a6
Removing intermediate container d8dfcf2f63a6
---> 6e980ad6882a
Step 4/5 : CMD ["java", "-version"]
---> Running in 9bae114258a6
Removing intermediate container 9bae114258a6
---> 212ff76fe2a2
Step 5/5 : ENTRYPOINT ["java", "-jar", "${project.build.finalName}.jar"]
---> Running in 2f59b4c7ac0a
Removing intermediate container 2f59b4c7ac0a
---> 07c262894893
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 07c262894893
Successfully tagged demo:0.0.1-SNAPSHOT
[root@localhost jre1.8.0_311]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
demo 0.0.1-SNAPSHOT 07c262894893 About a minute ago 224MB
demo 1.0.1 07c262894893 About a minute ago 224MB
(3)绑定 Docker 命令到 Maven各个阶段
github上已经很详细了,大家可以上去看看官方文档
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
......
</configuration>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<execution>
<id>tag-image</id>
<phase>package</phase>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<image>${project.artifactId}:latest</image>
<newName>${project.artifactId}:${project.version}</newName>
</configuration>
</execution>
<execution>
<id>push-image</id>
<phase>deploy</phase>
<goals>
<goal>push</goal>
</goals>
<configuration>
<imageName>${project.artifactId}:${project.version}</imageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行mvn package时,执行 build、tag 操作
执行mvn deploy时,执行build、tag、push 操作
如果我们想跳过 docker 某个过程时,只需要:
-DskipDockerBuild 跳过 build 镜像
-DskipDockerTag 跳过 tag 镜像
-DskipDockerPush 跳过 push 镜像
-DskipDocker 跳过整个阶段
例如:我们想执行 package 时,跳过 tag 过程,那么就需要mvn package -DskipDockerTag
3.2 dockerfile-maven-plugin插件
官方推荐使用dockerfile-maven-plugin
docker-maven-plugin:We recommend you use dockerfile-maven instead.
注意:需要结合Dockerfile文件,设置环境变量
1.设置环境变量(必须)
环境变量名称:DOCKER_HOST
变量值:tcp://192.168.122.22:2375(根据实际IP地址来)
export DOCKER_HOST=tcp://localhost:2375
2. xml配置
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<configuration>
<repository>${project.artifactId}</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
或者
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${project.artifactId}</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
该插件的配置比docker-maven-plugin更简单
- repository:指定docker镜像的repo名字
- tag:指定docker镜像的tag
- buildArgs:可以指定一个或多个变量,传递给Dockerfile,在Dockerfile中通过ARG指令进行引用
在execution中同时指定build和push目标:
当运行mvn package时,会自动执行build目标,构建Docker镜像。当运行mvn deploy命令时,会自动执行push目标,将Docker镜像push到Docker仓库。
3. 创建Dockerfile文件
Dockerfile文件必须在根目录下,与pom.xml文件同级
FROM xuux/small-jre8:1.0
MAINTAINER xu_ux test@email.com
WORKDIR /opt
CMD ["java", "-version"]
ENTRYPOINT ["java", "-jar", "${project.build.finalName}.jar"]
4. 其他使用方法:
https://github.com/spotify/dockerfile-maven/blob/master/docs/usage.md
四、问题
<baseImage>jdk1.8</baseImage>
pull access denied for jdk1.8, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
原因:
报这个错是因为docker上没有jdk1.8镜像文件。
解决方法:
换成xuux/small-jre8
<baseImage>xuux/small-jre8</baseImage>
docker pull xuux/small-jre8