前面我们介绍了K8S+Docker+Maven插件打包部署SpringCloud微服务项目,在实际应用过程中,很多项目没有用到K8S和微服务,但是用到了Docker和SpringBoot,所以,我们这边介绍,如果使用Jenkins+jib-maven-plugin插件打包部署SpringBoot项目的Docker镜像。
网上有多种Docker打包插件使用说明,讲解最多的是Spotify开源的,Spotify官方已不再推荐使用docker-maven-plugin插件进行打包,而是推荐其最新的docker打包插件dockerfile-maven-plugin,但是dockerfile-maven-plugin也已经很久没有更新了,在使用方面也有局限性,比如:只支持在本机Docker的镜像build、tag、push。
经过几个插件的对比,发现Google开源的Jib插件功能更强大,它可以不写Dockerfile,不需要在本地安装Docker环境就能实现Docker打包,而且一直在更新,所以这里选择这个插件作为我们的Docker打包插件。
Jib构建Java的Docker和OCI映像,不需要在本机安装Docker daemon,也不需要深入掌握Docker最佳实践。它可以作为Maven和Gradle的插件以及Java库使用。
下面介绍Jib( jib-maven-plugin插件 )如何将SpringBoot应用程序分层打包Docker镜像,充分利用Docker的镜像分层复用机制,解决网络限制和占用大量磁盘空间的问题。
Jib( jib-maven-plugin插件 )构建的三个参数:
我们这里主要使用buildTar命令,将Docker镜像文件打包在本地,然后通过Jenkins插件发布到服务器运行,这样可以不需要搭建使用私有Docker镜像仓库Harbor。
-Dimage可以在打包时自定义镜像名称和版本,这个可以在Jenkins脚本时使用,如果不配置默认使用pom.xml里面配置的镜像名称和版本,如果不设置版本,默认版本是latest
clean package -Ptest -Dimage=gitegg:1.0.1 jib:buildTar -f pom.xml
docker load用来载入镜像包,但是不能对载入的镜像重命名;docker import用来载入容器包,但两者都会恢复为镜像,可以为镜像指定新名称;经过测试,jib-maven-plugin插件生成的Docker镜像文件jib-image.tar只能通过docker load载入,并且在pom.xml配置中format不能选择OCI(K8S时使用OCI),否则载入不了。
docker load --input jib-image.tar
install build
私有仓库地址/项目名称/${project.artifactId}:${project.version} 私有仓库用户名 私有仓库密码
/tmp /log
/gitegg
OCI
下面是SpringBoot项目中pom.xml的jib-maven-plugin插件配置信息:
············ ······3.3.2 ······com.google.cloud.tools jib-maven-plugin${jib.maven.plugin.version} install build true openjdk:11-jre ${docker.harbor.addr}/${docker.harbor.project}/${project.artifactId}:${project.version} ${docker.harbor.username} ${docker.harbor.password} -Xms512m -Xmx8g /tmp /log /gitegg Asia/Shanghai USE_CURRENT_TIMESTAMP
前面我们讲了如何安装Docker,以及相关配置,所以这里不再赘述,直接按照自己的服务器实际情况进行安装配置Docker即可,这里讲解如何为运行SpringBoot的Fat Jar做环境准备,以及说明镜像包传输到服务器之后执行的部署脚本。
mkdir -p /opt/tmp /opt/bak /opt/script /data/container/docker_server/tmp /data/container/docker_server/logs chmod -R 777 /opt/tmp /opt/bak /opt/script /data/container/docker_server/tmp /data/container/docker_server/logs
container_name=gitegg-server : 容器名称
image_name=gitegg-server : 镜像名称
version=latest : 镜像版本
image_port=8182 : 宿主主机端口映射
server_port=8080 : 容器内服务端口
echo "param validate" if [ $# -lt 1 ]; then echo "you must use like this : ./publish_docker_server.sh[image port] [server port]" exit fi
if [ "" != "" ]; then container_name="" fi echo "container_name=" $container_name if [ "" != "" ]; then image_name="" fi if [ "" != "" ]; then version="" fi echo "version=" $version if [ "" != "" ]; then image_port="" fi echo "image_port=" $image_port if [ "" != "" ]; then server_port="" fi echo "server_port=" $server_port
echo "执行docker ps" docker ps if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]]; then echo $container_name "容器存在,停止并删除" echo "docker stop" $container_name docker stop $container_name echo "docker rm" $container_name docker rm $container_name else echo $container_name "容器不存在" fi
# 删除镜像 echo "执行docker images" docker images if [[ "$(docker images -q $image_name 2> /dev/null)" != "" ]]; then echo $image_name '镜像存在,删除镜像' docker rmi $(docker images -q $image_name 2> /dev/null) --force else echo $image_name '镜像不存在' fi
#bak image echo "bak image" $image_name BAK_DIR=/opt/bak/docker/$image_name/`date +%Y%m%d` mkdir -p "$BAK_DIR" cp "/opt/tmp/jib-image.tar" "$BAK_DIR"/"$image_name"_`date +%H%M%S`.tar
echo "docker load" $image_name docker load --input /opt/tmp/jib-image.tar
echo "docker run" $image_name docker run -d -p $image_port:$server_port --name=$container_name --restart=always -v /data/container/docker_server/tmp:/tmp -v /data/container/docker_server/logs:/var/log $image_name
echo "remove tmp " $image_name rm -rf /opt/tmp/jib-image.tar
echo "Docker Server is starting,please try to access $container_name conslone url"
container_name=gitegg-server image_name=gitegg-server version=latest image_port=8181 server_port=8080 echo "param validate" if [ $# -lt 1 ]; then echo "you must use like this : ./publish_docker_server.sh[image port] [server port]" exit fi if [ "$1" != "" ]; then container_name="$1" fi echo "container_name=" $container_name if [ "$2" != "" ]; then image_name="$2" fi if [ "$3" != "" ]; then version="$3" fi echo "version=" $version if [ "$4" != "" ]; then image_port="$4" fi echo "image_port=" $image_port if [ "$5" != "" ]; then server_port="$5" fi echo "server_port=" $server_port echo "执行docker ps" docker ps if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]]; then echo $container_name "容器存在,停止并删除" echo "docker stop" $container_name docker stop $container_name echo "docker rm" $container_name docker rm $container_name else echo $container_name "容器不存在" fi # 删除镜像 echo "执行docker images" docker images if [[ "$(docker images -q $image_name 2> /dev/null)" != "" ]]; then echo $image_name '镜像存在,删除镜像' docker rmi $(docker images -q $image_name 2> /dev/null) --force else echo $image_name '镜像不存在' fi #bak image echo "bak image" $image_name BAK_DIR=/opt/bak/docker/$image_name/`date +%Y%m%d` mkdir -p "$BAK_DIR" cp "/opt/tmp/jib-image.tar" "$BAK_DIR"/"$image_name"_`date +%H%M%S`.tar echo "docker load" $image_name docker load --input /opt/tmp/jib-image.tar echo "docker run" $image_name docker run -d -p $image_port:$server_port --name=$container_name --restart=always -v /data/container/docker_server/tmp:/tmp -v /data/container/docker_server/logs:/var/log $image_name echo "remove tmp " $image_name rm -rf /opt/tmp/jib-image.tar echo "Docker Server is starting,please try to access $container_name conslone url"
clean package -Dmaven.test.skip=true -Ptest -Dimage=gitegg jib:buildTar -f pom.xml
/opt/script/publish_docker_server.sh gitegg gitegg latest 8181 8080
立即构建
查看构建日志:点击立即构建之后,下方会出现进度条,点击进度条就可以进入构建日志界面。
docker images
docker ps
docker stop 容器id
docker rm 容器id docker rmi 镜像id
docker logs -f 容器id
docker exec -it 容器id /bin/bash