1. 程式人生 > >使用GitLab、Jenkins、Docker建立快速持續化整合交付部署方案(一)

使用GitLab、Jenkins、Docker建立快速持續化整合交付部署方案(一)

摘要

本系列文章將要完成的:

  • 安裝GitLab、Jenkins、Docker等一系列基礎環境
  • 建立自己的 Docker Registry,私有的Docker映象服務,用於儲存我們自己的Docker映象倉庫(Repository)
  • 使用GitLab進行程式碼管理,並聯動Jenkins進行自動化打包,生成Docker Image,推送到自己的Repository
  • 使用Docker Compose在目的機上進行整合環境部署


本系列文章不會包含:Linux、GitLab、Jenkins、Docker等基礎概念和知識,不包含Docker swarm、叢集、單元測試和自動化測試。

文章索引

  1. GitLab、Jenkins、Docker 初始環境安裝(本文)
  2. 製作 Docker映象 及 Docker Compose 的使用
  3. 使用 Webhook 自動觸發 Jenkins 進行 Docker映象製作並儲存到私有映象倉庫,以及目的機部署

環境版本

  • Ubuntu 14.04 LTS
  • GitLab Community Edition 8.13.1
  • Docker 1.11, Docker Compose V1,Docker Registry V2
  • Jenkins 2.19 LTS

GitLab安裝

簡介

關於Git的基本知識我就不在這裡講了,有興趣的可以瞭解下我之前寫的文章:

我也講講Git

GitLab與GitHub十分相似,區別並不是很大。對於想要了解GitHub的可以參見:我再講講GitHub

比較不同的一點,GitHub中的Pull Request,在GitLab中叫做Merge Request。其實並沒有區別,Pull就是要Merge嘛。

GitLab同樣需要生成證書等一系列操作,與GitHub相同,其實都是Git工作流中的必需項。這些內容在剛才提到的連結中都有講,不在針對GitLab進行描述。

安裝

安裝的方法很多,根據天朝的網路情況,這裡選擇從清華大學的TUNA映象站下載Gitlab Community Edition:

https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce/

目的機為Ubuntu 14.04,所以這裡建議:

 

1

2

3

4

# curl https://packages.gitlab.com/gpg.key 2> /dev/null | sudo apt-key add - &>/dev/null

# echo 'deb https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu trusty main' >> /etc/apt/sources.list.d/gitlab-ce.list

# apt-get update

# apt-get install gitlab-ce

如果要在公司內部安裝的話,可能會下載一天的速度都不如拿個U盤拷的情況,所以直接去TUNA的HTTPS伺服器上,摳對應的安裝包,在家裡下載完,之後拿個U盤拷貝更靠譜更靠譜:(https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/trusty/main/g/gitlab-ce/)

使用 dpkg -i 對deb包進行安裝。

注意,GitLab對系統的其他包依賴特別嚴重,對nginx、postgresql、redis、git等都有嚴重的依賴。所以建議安裝GitLab的伺服器即作為程式碼倉庫專用伺服器,上面不要隨意安裝任何其他工具或軟體,不要在宿主機上跑其他的服務。Docker除外。

配置

  • 域名

開啟/etc/gitlab/gitlab.rb檔案.

修改伺服器地址:

 

1

external_url 'http://your_domain_or_ip.com'

  • 郵箱

新增如下程式碼以配置郵箱。

建議配置郵箱系統。GitLab使用使用者名稱和使用者郵箱區分使用者,均不可重複。管理員新建郵箱時不能指定使用者密碼,GitLab會向註冊郵箱中傳送第一次修改密碼郵件。之後使用者找回密碼憑據也是使用郵箱。

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

gitlab_rails['smtp_enable'] = true

gitlab_rails['smtp_address'] = "smtp.qq.com"

gitlab_rails['smtp_port'] = 465

gitlab_rails['smtp_user_name'] = "[email protected]"

gitlab_rails['smtp_password'] = "your_smtp_user_password"

gitlab_rails['smtp_authentication'] = "login"

gitlab_rails['smtp_ssl'] = true

gitlab_rails['smtp_enable_starttls_auto'] = true

gitlab_rails['smtp_tls'] = true

 

# If your SMTP server does not like the default 'From: [email protected]' you

# can change the 'From' with this setting.

gitlab_rails['gitlab_email_from'] = '[email protected]'

gitlab_rails['gitlab_email_reply_to'] = '[email protected]'

如果你對Postfix比較熟悉的話,也可以使用GitLab自帶的Postfix做郵箱系統。對於初學者,建議使用其他郵箱的SMTP服務。

之後執行 gitlab-ctl reconfigure 生效配置

  • 註冊登入

對於非對公眾開放的GitLab系統來說,關閉註冊系統是必要的。

在Admin Area,點選右側的 齒輪,點選 Setting,取消勾選 Sign-up Restrictions。注意頁面很長,修改完之後到最下方點選儲存。

安裝Docker

一些概念

Docker的定義和一些基本概念就不在這裡講了。這裡只講一下為什麼要使用Docker,以及為什麼會可以與GitLab無衝突的安裝到同一臺機器上。

Docker容器即是實質的虛擬環境,容器內包含整個服務所需的所有依賴環境,且執行在其自己的虛擬環境中的,相當於最小化的虛擬機器,他的狀態不會影響宿主機,反過來宿主機的狀態也不會影響到容器。只有容器被設定的埠和儲存才能與外部環境通訊,剩下的完全是個黑盒,外界看不到,也不關心。

Docker部署簡單,容器從映象建立,而映象內包含所需的所有依賴,做到了一個映象直接部署,就像遊戲機一樣,插卡即玩,不再需要修改伺服器的系統配置。在一定程度上避免了部署人員胡亂搞最後還得開發人員動手的問題。

注意Docker映象是無狀態的,而容器是 有狀態 但應是 狀態不重要 的,容器在執行時生成的資料是被儲存在容器內的,這就是說容器內的程序生成的臨時檔案仍然被存放在容器內,並且當整個容器被刪除時也會跟著刪除。如果生成的檔案包含重要資料,則需要把對應生成的目錄指向宿主機目錄或者資料卷容器。

資料卷容器與普通容器沒有區別,只不過裡面不包含應用程序,只為了儲存資料而存在的容器。資料卷容器也是唯一一種 狀態重要 的,不要手賤把資料卷刪除了。

對於手殘黨還是把資料掛載到硬碟上吧。

安裝Docker環境

Docker的安裝十分簡單。

官方文件:https://docs.docker.com/engine/installation/linux/ubuntulinux/

要把鯨魚放冰櫃,總共分三步:確認自身作業系統核心版本、更新源、安裝包。

(注意以下操作均在root使用者下執行,非root使用者請自行sudo或su -。 # 表示提示符,這麼做的原因是防止有小白一股腦把大片程式碼複製貼上到shell中)

  1. 確認自身作業系統版本:注意Docker官方並不支援 Ubuntu 14.10 和 15.04,所以建議發行版儘量選擇LTS版。

     

    1

    2

    # uname -r

    3.13.0-86-generic

    官方也不支援kernal低於3.10的版本。對於核心低於3.10版本的系統,或是升級核心,或是升級作業系統。

  2. 更新源

     

     

    1

    2

    # apt-get update

    # apt-get install apt-transport-https ca-certificates

     

    更新作業系統證書庫和apt對https支援。

     

    1

    # apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

    新增對應源到本地。

    比如Trusty 14.04 (LTS)的源是:deb https://apt.dockerproject.org/repo ubuntu-trusty main,那麼執行

     

    1

    2

    # echo 'deb https://apt.dockerproject.org/repo ubuntu-trusty main' > /etc/apt/sources.list.d/docker.list

    # apt-get update

    在這一步你也可以選擇其他源,比如阿里的Docker源,不過版本會變得不確定,官方會提供最新的穩定版,現在是1.12,而阿里對Ubutnu提供的是1.11,對CentOS提供的是1.10。雖然我們暫時不會使用新版的一些新特性,但還請注意版本差異會導致一些特性或語義有重大差異,比如swarm。

  3. 安裝

     

     

    1

    # apt-get install docker-engine

     

    注意,阿里雲ECS上被定製的源和發行版可能不叫 docker-engine 而是直接叫 docker,要注意。

針對大陸使用者的的一些調整。

我們畢竟是在牆內,去docker hub上拉映象是十分不現實的,幾M的檔案拖幾個小時之後報個錯是很無奈的事情,所以就像我們經常修改apt和yum的source mirror一樣,我們要修改docker的registry-mirror

對於使用阿里雲ECS容器服務的使用者,可以使用其自帶的加速器配置,內網加速器不僅不消耗出口流量,而且也沒有頻寬限制。

地址:加速器

這個頁面藏得很深,很難找到。

其他使用者可以考慮daocloud

Ubuntu 14.04 對於registry-mirror很容易修改,我們只要在/etc/default/docker這個檔案中新增上引數即可,比如:

 

1

DOCKER_OPTS="$DOCKER_OPTS --registry-mirror=https://aliyuncssucks.mirror.aliyuncs.com"

而對於支援systemctl的新版Ubuntu和CentOS,我們要修改對應的docker.service中的ExecStart。

 

1

2

3

4

5

6

7

8

9

ExecStart=/usr/bin/docker-current daemon \

          --exec-opt native.cgroupdriver=systemd \

          $OPTIONS \

          $DOCKER_STORAGE_OPTIONS \

          $DOCKER_NETWORK_OPTIONS \

          $ADD_REGISTRY \

          $BLOCK_REGISTRY \

          $INSECURE_REGISTRY \

          --registry-mirror https://aliyuncssucks.mirror.aliyuncs.com

相關文件:https://docs.docker.com/engine/admin/systemd/

官方還有另一種修改方式,依靠Daemon configuration file。

看起來應該是更方便的方法,但是沒有嘗試過。有試過的朋友可以留言介紹下,

相關文件:https://docs.docker.com/engine/reference/commandline/dockerd/

至此Docker就安裝完成了。

安裝Jenkins

(關於Docker映象的製作,參見第二章)

Jenkins簡介

Jenkins是一個用Java編寫的開源的持續整合工具,可以於GitLab等程式碼管理工具聯動,觸發一定條件之後,實現自動進行測試、編譯、部署等一系列動作。

使用Docker獲得Jenkins映象

我們接下來就要依靠Docker來繼續在這臺GitLab伺服器上安裝Jenkins服務了。

jenkins官網:https://jenkins.io/

我們這裡選擇Docker平臺的LTS版本,他會把我們引導到 hub.docker.com 的 jenkinsci/jenkins 頁面,並告訴我們Docker Pull Command

 

1

# docker pull jenkinsci/jenkins

注意他的介紹寫錯了,hub.docker.com寫著是weekly releases,但其實github和真實下下來的都是LTS版,但github上的weekly releases又會指回這個頁面。

What were they thinking! Never mind.

注意我們可不能pull下來直接用!因為jenkins預設要使用兩個埠:8080和50000,而8080這個埠已經被GitLab占上了。

我們也不必把Jenkins的Dockerfile下下來自己改。別忘了Docker的映象是分層儲存的,我們只要在Jenkins上繼續搭建一個Dockerfile就可以了。

自己生成一個Dockerfile,內容:

 

1

2

3

4

5

6

7

8

9

FROM jenkinsci/jenkins

 

MAINTAINER modified

 

COPY etc/ /etc/

 

ENV JENKINS_OPTS --httpPort=8081

EXPOSE 8081:8081

EXPOSE 50000:50000

其中,本地目錄etc/下方的是兩個時區檔案。

預設的JENKINS_OPTS –httpPort是8080,我們修改成8081,之後將8081埠映射出來。

之後執行

 

1

docker build -t 'jenkins-catscarlet-modified' /the_dir_where_you_save_dockerfile/

系統就會製作一個屬於我們自己的,埠為8081的jenkins。

使用docker images檢視

 

1

2

3

4

# docker images

REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE

jenkins-catscarlet-modified                           latest              f093f22502fe        9 days ago          714.5 MB

jenkinsci/jenkins                                     latest              17c5cc713911        13 days ago         714.5 MB

準備Jenkins的環境

新建目錄/var/jenkins,你也可以自己選擇儲存路徑,或者自己製作一個數據卷容器。

給予這個目錄許可權。Jenkins在Dockerfile中描述的使用者許可權如下:

 

1

2

3

4

ARG user=jenkins

ARG group=jenkins

ARG uid=1000

ARG gid=1000

當然手懶可以直接來個777。安全問題自己解決。

啟動jenkins

啟動容器

 

1

docker run -d -v /var/jenkins_home:/var/jenkins_home -p 8081:8081 -p 50000:50000 jenkins-catscarlet-modified

使用docker ps來檢視容器執行情況。

開啟瀏覽器,訪問你的8081埠來檢視。能開啟頁面,配置個賬號密碼就行了。本章節只是為了熟練我們對Docker的一些基礎操作。我們會在後面的文章中繼續講Jenkins

你需要儲存的資料完全儲存在 /var/jenkins_home 中。你可以隨時刪除這個容器(注意是容器,不是映象或Dockerfile),並重建新的容器,你的資料不會丟失。

基於nsenter的Docker容器內管理工具

容器是一個絕對的黑盒環境,這意味著當我們遇到容器內配置有問題時,會遭遇一牆之隔:明知道是容器內的配置有問題,我們卻不知道配置檔案在哪、怎麼寫的、怎麼寫錯了。不像傳統虛擬機器,有個介面入口能讓我們登入。

所以我們需要一個工具進入容器內,nsenter能滿足我們的需求。

安裝util-linux

nsenter是包含在util-linux 2.23及之後版本中的工具,如果你的發行版預設自帶版本低於2.23,你需要手動安裝新版。已知Ubuntu 14.04 仍然使用 util-linux 2.20。

 

1

2

3

4

5

6

7

8

9

10

11

12

# apt-cache policy util-linux

util-linux:

  Installed: 2.20.1-5.1ubuntu20.7

  Candidate: 2.20.1-5.1ubuntu20.7

  Version table:

 *** 2.20.1-5.1ubuntu20.7 0

        500 http://mirrors.aliyun.com/ubuntu/ trusty-updates/main amd64 Packages

        500 http://mirrors.aliyuncs.com/ubuntu/ trusty-updates/main amd64 Packages

        100 /var/lib/dpkg/status

     2.20.1-5.1ubuntu20 0

        500 http://mirrors.aliyun.com/ubuntu/ trusty/main amd64 Packages

        500 http://mirrors.aliyuncs.com/ubuntu/ trusty/main amd64 Packages

在這裡選擇個版本https://www.kernel.org/pub/linux/utils/util-linux/,之後下載util-linux-version.tar.xz,解壓,configure、make nsenter && cp nsenter /usr/local/bin。

基本用法

nsenter 啟動一個新的shell程序, 同時會把這個新程序切換到和目標程序相同的名稱空間,這樣就相當於進入了容器內部。為此我們需要獲取容器的第一個程序的 PID

 

1

# PID=$(docker inspect --format "{{ .State.Pid }}" <container>)

之後根據獲取的PID進入容器

 

1

$ nsenter --target $PID --mount --uts --ipc --net --pid

使用shell簡化步驟

新建一個檔案getInDocker.sh並給予執行許可權:

 

1

2

3

4

5

6

7

8

9

10

11

12

#!/bin/bash

ID=$1;

 

PID=$(docker inspect --format "{{ .State.Pid }}" $ID )

if [ $PID = 0 ]; then

    echo "PID is 0, exit."

    exit 1

fi

echo "Going into:"

docker ps -f id=$ID

echo "PID:$PID"

nsenter --target $PID --mount --uts --ipc --net --pid

使用方式:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

# ./getInDocker.sh b7738b319cd8

Going into:

CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS                                                        NAMES

b7738b319cd8        jenkins-catscarlet-modified      "/bin/tini -- /usr/lo"   7 days ago          Up About an hour    0.0.0.0:8081->8081/tcp, 8080/tcp, 0.0.0.0:50000->50000/tcp   distracted_euler

PID:14441

 

[email protected]:/# ls -l --color

total 64

drwxr-xr-x   2 root root 4096 Nov  9 16:36 bin

drwxr-xr-x   2 root root 4096 Sep 12 04:09 boot

drwxr-xr-x   5 root root  360 Nov 23 08:15 dev

drwxr-xr-x  83 root root 4096 Nov 16 00:56 etc

drwxr-xr-x   2 root root 4096 Sep 12 04:09 home

drwxr-xr-x  13 root root 4096 Nov  8 18:53 lib

drwxr-xr-x   2 root root 4096 Nov  4 18:29 lib64

drwxr-xr-x   2 root root 4096 Nov  4 18:28 media

drwxr-xr-x   2 root root 4096 Nov  4 18:28 mnt

drwxr-xr-x   2 root root 4096 Nov  4 18:28 opt

dr-xr-xr-x 181 root root    0 Nov 23 08:15 proc

drwx------   2 root root 4096 Nov  4 18:28 root

drwxr-xr-x   3 root root 4096 Nov  4 18:28 run

drwxr-xr-x   2 root root 4096 Nov  4 18:30 sbin

drwxr-xr-x   2 root root 4096 Nov  4 18:28 srv

dr-xr-xr-x  13 root root    0 Nov 23 08:15 sys

drwxrwxrwt   7 root root 4096 Nov 23 08:15 tmp

drwxr-xr-x  38 root root 4096 Nov  9 16:37 usr

drwxr-xr-x  26 root root 4096 Nov  9 16:36 var

[email protected]:/#

現在你已經進入容器了,這是一個幾乎完全脫離宿主機的環境(除已掛在的資料卷),其中自帶的命令非常有限,你可以在裡面再安裝一些除錯工具。

附贈一段可以在阿里雲ECS上直接複製貼上的程式碼(非阿里雲使用者可以把aliyuncs改成aliyun,或者把整段改為其他源。注意發行版版本號):

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

cat <<EOF> /etc/apt/sources.list

 

deb http://mirrors.aliyuncs.com/ubuntu/ trusty main restricted universe multiverse

deb http://mirrors.aliyuncs.com/ubuntu/ trusty-security main restricted universe multiverse

deb http://mirrors.aliyuncs.com/ubuntu/ trusty-updates main restricted universe multiverse

deb http://mirrors.aliyuncs.com/ubuntu/ trusty-proposed main restricted universe multiverse

deb http://mirrors.aliyuncs.com/ubuntu/ trusty-backports main restricted universe multiverse

deb-src http://mirrors.aliyuncs.com/ubuntu/ trusty main restricted universe multiverse

deb-src http://mirrors.aliyuncs.com/ubuntu/ trusty-security main restricted universe multiverse

deb-src http://mirrors.aliyuncs.com/ubuntu/ trusty-updates main restricted universe multiverse

deb-src http://mirrors.aliyuncs.com/ubuntu/ trusty-proposed main restricted universe multiverse

deb-src http://mirrors.aliyuncs.com/ubuntu/ trusty-backports main restricted universe multiverse

 

EOF

 

apt-get update

 

apt-get install net-tools tcpdump vim lrzsz

這段程式碼會在你的容器內配置阿里雲ECS源,並安裝一些工具。你現在可以在容器內執行ifconfig、netstat、tcpdump、vi、rz、sz了。

只要不刪除這個容器,下次你進入這個容器還可以繼續使用這些工具。

你應該只在容器中安裝不會影響原本服務的工具,這些工具應該只作為除錯檢視用,不能影響正常服務,並且可以被隨時刪除。

不要在容器內儲存重要資料(除已掛在的資料卷位置)。容器應該是狀態不重要的,可以隨時刪除隨時新建。你不應該容器內部儲存配置檔案,你應該將除錯確認的配置檔案移出容器並妥善儲存。

小結

至此,我們的基本環境已經準備好了。