Coup de Grace

基于gitlab与docker的ci

2017-03-24更新,gitlab 9.0.0中这部分功能大家谨慎使用.

我回滚到了gitlab/gitlab-runner:v1.10.5才正常工作.

最近需要实践一下Gitlab based的CI与CD

Gitlab 8.0以后的版本自带CI,不需要到Services里面去启用了.


准备工作

  1. 安装Docker
  2. 安装Runner - Docker.
mkdir -p /srv/gitlab-runner/config
docker pull gitlab/gitlab-runner

运行Runner

docker run -d --name gitlab-runner --restart always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner:Z \
  gitlab/gitlab-runner:latest

注册到gitlab

docker exec -it gitlab-runner gitlab-runner register

写yml脚本

http://yourgitlab/ci/lint检测自己的脚本是否科学.

下面是我的脚本

image: maven:3.3.9-jdk-8
before_script:
  - mvn clean
stages:
  - install
  - ut
  - it
install:
  script:
    - mvn install -Dmaven.test.skip=true
  stage: install
  only:
    - develop
    - master
ut:
  script:
    - mvn test
  stage: ut
  only:
    - develop
    - master
it:
  script:
    - mvn integration-test
  stage: it
  only:
    - develop
    - master
after_script:
  - mvn clean

工程里如何配置

插件是如下三个:

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <mainClass>com.xxx.Application</mainClass>
            <layout>WAR</layout>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>repackage</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <excludes>
                <exclude>**/*IT.java</exclude>
            </excludes>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <configuration>
            <includes>
                <include>**/*IT.java</include>
            </includes>
        </configuration>
        <executions>
            <execution>
                <phase>integration-test</phase>
                <goals>
                    <goal>integration-test</goal>
                    <goal>verify</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

对RD的基本要求:

遇到什么问题

runner默认的镜像中maven是从中央库拉jar包,这不行.

最开始思路有了点问题,尝试着自建一个mvn镜像push到docker hub,但是查看了maven官方镜像的Dockerfile是下面这样的:

FROM openjdk:7-jdk

ARG MAVEN_VERSION=3.3.9
ARG USER_HOME_DIR="/root"

RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
  && curl -fsSL http://apache.osuosl.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz \
    | tar -xzC /usr/share/maven --strip-components=1 \
  && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn

ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"

COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.sh
COPY settings-docker.xml /usr/share/maven/ref/

VOLUME "$USER_HOME_DIR/.m2"

ENTRYPOINT ["/usr/local/bin/mvn-entrypoint.sh"]
CMD ["mvn"]

那么我们-v把目录挂载到每个docker-in-docker容器中.

换言之,将自己的settings.xml置入宿主机的/root/.m2即可解决问题.

那么索性将jar包下载地址放入/root/.m2,这样只需要挂载一个目录

也就是修改settings.xml

 <localRepository>/root/.m2</localRepository>

我们在准备工作里的/srv/gitlab-runner/config派上了用处,里面在运行初始化配置后会生成 config.toml

那么修改如下,来利用重复镜像与maven配置和repo:

# 调节一下 runner 数量
concurrent = 5
# 调节一下共享目录
[runners.docker]
    volumes = ["/cache","/root/.m2:/root/.m2"]
    pull_policy = "if-not-present"

另外当持续集成进行时你在宿主机docker ps就能看到生成的docker-in-docker实例.

成果

每次push或者merge request都会触发,这部分可以自行设置.

另外merge request在持续集成成功之前是无法完成的.

这部分也可以通过docker logs命令来看到

添加构建状态徽标

在CI/CD pipline选项里面看得到添加代码

我目前是这么写的

## 构建状态
- master [![build status](http://yourgitlab/group/project/badges/master/build.svg)](http://yourgitlab/group/projec/commits/master)
- develop [![build status](http://yourgitlab/group/projec/badges/develop/build.svg)](http://yourgitlab/group/projec/commits/develop)

配合git flow,可以很清晰看到主要分支状态

可以优化的点


持续集成阶段拓扑,后续应该什么样?

stages: 
    - install 
    - ut
    - it
    - build_image
    - push_image
    - deploy

大概是这样的规划

那么持续集成的部分结束,持续交付择日继续.

2017-01-03更新

上文我的思路没错,不过上了kubernetes之后.最后这一步deploy是不需要的

我们运行到把镜像push到registry就算CD终止.


done.