1. 程式人生 > >【持續整合】GitLab CI + Docker 實現持續整合

【持續整合】GitLab CI + Docker 實現持續整合

GitLab CI + Docker 實現持續整合

一、持續整合(Continuous Integration, CI)的基本概念

概述

在傳統軟體的開發中,程式碼的整合工作通常是在所有人都將工作完成後在專案即將結束進行時,而這往往會花費大量的時間和精力。而持續整合是一種將整合階段放在軟體開發階段的做法,以便更加有規律地構建,測試和整合程式碼。

“持續整合並不能消除 Bug,而是讓它們非常容易發現和改正。”

持續整合可以在開發人員提交了新程式碼後,立刻進行構建、單元測試。從而我們可以根據測試結果以確定新的程式碼或者環境配置與原來的以及其他開發人員的程式碼或者環境配置能否正確地整合在一起。

持續交付 & 持續部署

持續交付(Continuous Delivery):頻繁地將軟體的新版本,交付給質量團隊或者使用者,以供評審。如果評審通過,程式碼就進入生產階段。

持續部署(Continuous Deployment):是持續交付的下一步,指的是程式碼評審以後,自動部署到生產環境。

二、GitLab 持續整合起步

從 GitLab 8.0 開始,GitLab CI 就已經整合在 GitLab 中,我們只需要在專案中新增一個 .gitlab-ci.yml 檔案,然後新增一個 Runner,即可進行持續整合。而且隨著 GitLab 的升級,GitLab 也變得越來越強大。

.gitlab-ci.yml

.gtilab-ci.yml 檔案存放與專案於倉庫的根目錄,用以來定義 GitLab CI/CD 中的 Pipeline。其實無非是一個配置檔案,理解起來挺簡單的,我們主要是需要了解 Pipeline 的概念以及如何配置一個 .gitlab-ci.yml

Pipeline & Stages & Jobs

一個 Pipeline 大概相對於一個構建任務,裡面可以包含多個流程,如安裝依賴、執行測試、編譯、部署測試伺服器、部署生產伺服器等流程,Git 提交時會觸發 Pipeline。而一個 Pipeline 中又可以包含一至多個 Stage,即用來定義安裝依賴、執行測試之類的流程的。然後,一個 Stage 中又包含了一至多個 Job

,Jobs 表示一個 Stage 中具體的構建工作,即某個 Stage 裡面執行的工作。我們可以在 Stages 裡面定義這些 Job,它們之間的關係如下圖所示:

注意:

  • Stages 會按 .gitlab-ci.yml 中配置的順序執行,當前面的 Stage 執行完畢後才會繼續執行後面的 Stage,如果一個 Stage 失敗,那麼後面的 Stage 不會執行,該構建任務失敗。
  • Stage 中的 Jobs 會並行執行,當這個 Stage 中所有的 Job 都執行完畢,該 Stage 才算執行成功。換而言之,只要有一個 Job 執行失敗,整個 Pipeline 也就失敗了。
stages:
 - build
 - test
 - deploy
 
build:
  stage: build
  script: 
    - "execute-script-for-build"
    - "do something...""
  only:
    - master
  tags:
    - ruby
    - postage

test:
  stage: test
  script:
  
......

上面配置將一次 pipeline 分成了三個階段:build、test、deploy。下面介紹配置檔案中的節點:

  • stages: 定義構建的階段;
  • build、test、...:定義 jobs_name,即在 stages 中定義的 stage 階段,一般在 stage 節點註明所屬的 stage;
  • script:Runner 執行的指令碼或命令,該節點是必須的。
  • 其他節點:stage 中還有許多其他節點,例如 only、tags 等,但並不是 required ,其具體作用可在文件中瞭解。

GitLab Runner

當我們理解完上面的概念後,我們還沒了解最重要的東西——上面的任務由誰來構建呢?答案就是 Gitlab-runner 了!

為什麼不用 GitLab CI 來執行這些構建任務呢?

一般來說,構建任務任務都會佔用很多的系統資源(譬如編譯程式碼),而 GitLab CI 又是 GitLab 的一部分,如果由 GitLab CI 來執行構建任務的話,在執行構建任務的時候, GitLab 的效能會大幅下降。

GitLab CI 最大的作用是管理各個專案的構建狀態,因此,執行構建任務這種浪費資源的事情就交給 GitLab Runner 來做啦!

因為 GitLab Runner 可以安裝到不同的機器上,所以在構建任務執行期間並不會影響到 GitLab 的效能。

三、持續整合的實現

接下來介紹 GitLab 對 Spring Boot 程式的持續整合,當然 GitLab 不止支援 Java 應用服務,肯定也支援其他編譯語言,這裡主要只是像演示一下過程,過程基本上是相通的。

搭建 GitLab 服務

這不是本次的重點,所以就簡要介紹下咯。
利用 Docker 和 Docker Compose 快速搭建 GitLab 服務,docker-compose.yml 檔案如下:

version: '3'
services:
    web:
      image: 'twang2218/gitlab-ce-zh:10.5'
      restart: always
      hostname: '192.168.253.139'
      environment:
        TZ: 'Asia/Shanghai'
        GITLAB_OMNIBUS_CONFIG: |
          external_url 'http://192.168.253.139:8080'
          gitlab_rails['gitlab_shell_ssh_port'] = 2222
          unicorn['port'] = 8888
          nginx['listen_port'] = 8080
      ports:
        - '8080:8080'
        - '8443:443'
        - '2222:22'
      volumes:
        - /usr/local/docker/gitlab/config:/etc/gitlab
        - /usr/local/docker/gitlab/data:/var/opt/gitlab
        - /usr/local/docker/gitlab/logs:/var/log/gitlab

啟動完畢後,訪問 http://ip:8080,初始化安裝完成後效果如下:

設定初始化密碼後重新整理,就可以看見登入介面了,登入!

配置 SSH 免密登入

ssh-keygen -t rsa -P 'youname'

複製使用者目錄下的 .ssh 資料夾下的公鑰,將其複製到 GitLab 的

構建 Docker Runner

環境準備

  • 建立工作目錄 /usr/lcoal/docker/runner
  • 建立構建目錄 /usr/local/docker/runner/enviroment
  • 下載 jdk-8u152-linux-x64.tar.gz 並複製到 /usr/local/docker/runner/environment

Dockerfile

usr/lcoal/docker/runner/environment 目錄下建立 Dockerfile

FROM gitlab/gitlab-runner:v11.0.2

RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' > /etc/apt/sources.list && \
    echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> /etc/apt/sources.list && \
    echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' >> /etc/apt/sources.list && \
    echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' >> /etc/apt/sources.list && \
    apt-get update -y && \
    apt-get clean

RUN apt-get -y install apt-transport-https ca-certificates curl software-properties-common && \
    curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add - && \
    add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" && \
    apt-get update -y && \
    apt-get install -y docker-ce

COPY daemon.json /etc/docker/daemon.json

WORKDIR /usr/local/bin
RUN wget https://raw.githubusercontent.com/topsale/resources/master/docker/docker-compose

RUN chmod +x docker-compose

RUN mkdir -p /usr/local/java
WORKDIR /usr/local/java
COPY jdk-8u152-linux-x64.tar.gz /usr/local/java
RUN tar -zxvf jdk-8u152-linux-x64.tar.gz && \
    rm -fr jdk-8u152-linux-x64.tar.gz

RUN mkdir -p /usr/local/maven
WORKDIR /usr/local/maven
RUN wget https://raw.githubusercontent.com/topsale/resources/master/maven/apache-maven-3.5.3-bin.tar.gz

RUN tar -zxvf apache-maven-3.5.3-bin.tar.gz && \
    rm -fr apache-maven-3.5.3-bin.tar.gz


ENV JAVA_HOME /usr/local/java/jdk1.8.0_152
ENV MAVEN_HOME /usr/local/maven/apache-maven-3.5.3
ENV PATH $PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin

WORKDIR /

daemon.json

/usr/local/docker/runner/environment 目錄下建立 daemon.json,用於配置加速器和倉庫地址

{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ],
  "insecure-registries": [
    "ip:port"
  ]
}

新建 Git 專案

新建一個 Git 專案,將其克隆到本地

註冊 Runner

docker exec -it gitlab-runner gitlab-runner register

# 輸入 GitLab 地址
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://192.168.75.146:8080/

# 輸入 GitLab Token
Please enter the gitlab-ci token for this runner:
1Lxq_f1NRfCfeNbE5WRh

# 輸入 Runner 的說明
Please enter the gitlab-ci description for this runner:
可以為空

# 設定 Tag,可以用於指定在構建規定的 tag 時觸發 ci
Please enter the gitlab-ci tags for this runner (comma separated):
可以為空

# 選擇 runner 執行器,這裡我們選擇的是 shell
Please enter the executor: virtualbox, docker+machine, parallels, shell, ssh, docker-ssh+machine, kubernetes, docker, docker-ssh:
shell

以上互動中,GitLab 地址和 Token 令牌可以在 GitLab 的專案的設定中找到:

當上述步驟完成後,重新整理當前頁面,可以看見當前頁面下多出來一個 runner:

完善專案

在這裡我只簡單地做了個小 dome,大概這麼簡單:

專案中用到的 .gitlab-ci.ymlDockerfiledocker-compose.yml 如下:
.gitlab-ci.yml

stages:
  - build
  - run
  - clean

build:
  stage: build
  script:
    - /usr/local/maven/apache-maven-3.5.3/bin/mvn clean package
    - cp target/ci-test-project-1.0.0-SNAPSHOT.jar docker
    - cd docker
    - docker build -t ci-test-project .

run:
  stage: run
  script:
    - cd docker
    - docker-compose down
    - docker-compose up -d

clean:
  stage: clean
  script:
    - docker rmi $(docker images -q -f dangling=true)

Dockerfile

FROM openjdk:8-jre

RUN mkdir /app

COPY ci-test-project-1.0.0-SNAPSHOT.jar /app/app.jar

ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/app.jar"]

EXPOSE 8080

docker-compose.yml

version: '3.1'
services:
  itoken-config:
    restart: always
    image: ci-test-project
    ports:
      - 8080:8080

提交專案

完成 demo 的之後就將專案提交到 GitLab 上,push 完成之後,點選專案的 CI/CD 可以看見一下頁面

再點選進入就可以看見具體的作業了,自行體會

當專案出現所有 jobs 全部通過時,也就是持續整合初步完善了,這時我們可以開啟瀏覽器訪問 ip:8080 可以看見瀏覽器上顯示

Hello GitLab

此時我們可以嘗試修改專案中的程式碼再提交,比如簡單地將 retuen "Hello GitLab" 改成 return "Hello World" 再提交一遍程式碼,等 jobs 通過後,再重新整理瀏覽器,我們可以看見

Hello World

至此,這個小 Demo 也就完成了。

四、參考

  • https://docs.gitlab.com/ee/ci/yaml/
  • https://www.cnblogs.com/newP/p/5735366.html
  • https://www.funtl.com/zh/spring-cloud-itoken-ci/
  • https://www.mindtheproduct.com/2016/02/what-the-hell-are-ci-cd-and-devops-a-cheatsheet-for-the-rest-of-us/