转载于 http://blog.c7d8.com/blog/18.html ,原文可能有更新,以原文为准
现有的应用编译、maven打包、docker镜像构建都是在一个job或者同一个gitlab-runner中完成的,且使用了 maven 的 插件 “docker-maven-plugin” ,虽然一个命令 mvn package 就可以在CI环境构建为镜像,但毕竟maven本身的打包过程被强行与docker镜像的打包过程耦合在了一起,也会导致不了解的同学在自己的开发机器上执行mvn package的时候出现缺少docker的错误,本篇文章就是为了避免以上问题
要实现上一个job的构建物(即我们的mvn package执行产生的jar/war包)传递到下一个,我们需要了解 artifacts ,artifacts.path你可以填写你需要传递的路径,可以正则匹配,符合的文件/文件夹会被上传到gitlab。我们看看构建日志
//这里我们提前创建好了放构建物的路径 并将所有构建物 依赖包 dockerfile都整理到一起
$ mkdir -p sartifacts/test-order-service && mkdir -p sartifacts/test-product-service && mkdir -p sartifacts/test-user-service $$ mkdir -p sartifacts/test-webapp-app
$ cp -r test-order-service/target/test-order-service-*.jar test-order-service/target/lib test-order-service/Dockerfile sartifacts/test-order-service
$ cp -r test-product-service/target/test-product-service-*.jar test-product-service/target/lib test-product-service/Dockerfile sartifacts/test-product-service
$ cp -r test-user-service/target/test-user-service-*.jar test-user-service/target/lib test-user-service/Dockerfile sartifacts/test-user-service
$ cp test-webapp-app/target/app.war test-webapp-app/Dockerfile sartifacts/test-webapp-app
Uploading artifacts...
sartifacts/*: found 326 matching files
Uploading artifacts to coordinator... ok id=1862 responseStatus=201 Created token=ydasdaeyvZ
下一个job执行的时候会自动下载回来。所以我们的.gitlab-ci.yml前半部分是这样
makejava:
image: maven:3-jdk-8
stage: package
tags:
- docker
script:
# - mvn clean
- mvn clean package -Dmaven.test.skip=true
# 在根目录创建一个文件夹来放所有的构建物
- mkdir -p sartifacts/test-order-service && mkdir -p sartifacts/test-product-service && mkdir -p sartifacts/test-user-service $$ mkdir -p sartifacts/test-webapp-app
- cp -r test-order-service/target/test-order-service-*.jar test-order-service/target/lib test-order-service/Dockerfile sartifacts/test-order-service
- cp -r test-product-service/target/test-product-service-*.jar test-product-service/target/lib test-product-service/Dockerfile sartifacts/test-product-service
- cp -r test-user-service/target/test-user-service-*.jar test-user-service/target/lib test-user-service/Dockerfile sartifacts/test-user-service
- cp test-webapp-app/target/app.war test-webapp-app/Dockerfile sartifacts/test-webapp-app
- du -h --max-depth=1 sartifacts
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
paths:
- sartifacts/*
expire_in: 1 day
为了不给gitlab的存储增加压力,我们将构建物的有效期设置为1天
在下一个job我们可以看到上一个job缓存的构建物已经下载好了 我们就可以直接执行docker build命令了
发现构建物已经上传gitlab成功后,我们就可以忙活在docker中构建一个镜像了,这会涉及到“docker in docker”,因为我们需要在docker容器中执行docker build构建命令,所以我们另外搭建了一个runner专门干构建镜像的事情。这里我们参考了 这篇文章,其提供了三种方式来实现在容器中执行docker命令,我们选择了其中第三种
第三种方法是将/var/run/docker.sock绑定装载到容器中,以便 docker 在该镜像的上下文中可用。
为了做到这点,遵循以下步骤:
gitlab-runner register -n --url http://gitlab.example.com/ --registration-token REGISTRATION_TOKEN --executor docker --description "My Docker Runner" --docker-image "docker:latest" --docker-volumes /var/run/docker.sock:/var/run/docker.sock
上面的命令将注册一个新的 Runner 来使用 Docker 提供的特殊docker:latest镜像。请注意,它正在使用 Runner 本身的 Docker 守护进程,docker 命令产生的任何容器都将是 Runner 的兄弟,而不是所运行程序的子进程。这可能会有不适合您的工作流程的复杂性和局限性。
现在我们需要完善.gitlab-ci.yml
image: docker:latest
stages:
- package
- build
variables:
test_order_service: 172.16.1.111:5000/cdyb/test-order-service:latest
test_product_service: 172.16.1.111:5000/cdyb/test-product-service:latest
test_user_service: 172.16.1.111:5000/cdyb/test-user-service:latest
test_webapp_app: 172.16.1.111:5000/cdyb/test-webapp-app:latest
test_webapp_center: 172.16.1.111:5000/cdyb/test-webapp-center:latest
test_ttsaqc_service: 172.16.1.111:5000/cdyb/test-ttsaqc-service:latest
makejava:
image: maven:3-jdk-8
stage: package
tags:
- docker
script:
# - mvn clean
- mvn clean package -Dmaven.test.skip=true
# 在根目录创建一个文件夹来放所有的构建物
- mkdir -p sartifacts/test-order-service && mkdir -p sartifacts/test-product-service && mkdir -p sartifacts/test-user-service $$ mkdir -p sartifacts/test-webapp-app
- cp -r test-order-service/target/test-order-service-*.jar test-order-service/target/lib test-order-service/Dockerfile sartifacts/test-order-service
- cp -r test-product-service/target/test-product-service-*.jar test-product-service/target/lib test-product-service/Dockerfile sartifacts/test-product-service
- cp -r test-user-service/target/test-user-service-*.jar test-user-service/target/lib test-user-service/Dockerfile sartifacts/test-user-service
- cp test-webapp-app/target/app.war test-webapp-app/Dockerfile sartifacts/test-webapp-app
- du -h --max-depth=1 sartifacts
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
paths:
- sartifacts/*
expire_in: 1 day
docker-build:
stage: build
tags:
- imagebuild
script:
- docker build -t $test_order_service ./sartifacts/test-order-service/
- docker build -t $test_product_service ./sartifacts/test-product-service/
- docker build -t $test_user_service ./sartifacts/test-user-service/
- docker build -t $test_webapp_app ./sartifacts/test-webapp-app/
需要注意的是
使用maven插件的方式却是比较方便,特别是对于需要构建一个多模块的maven项目的时候,但我们的这种做法比较清晰明朗。