使用GitLab、Jenkins、Docker建立快速持續化整合交付部署方案(一)
摘要
本系列文章將要完成的:
- 安裝GitLab、Jenkins、Docker等一系列基礎環境
- 建立自己的 Docker Registry,私有的Docker映象服務,用於儲存我們自己的Docker映象倉庫(Repository)
- 使用GitLab進行程式碼管理,並聯動Jenkins進行自動化打包,生成Docker Image,推送到自己的Repository
- 使用Docker Compose在目的機上進行整合環境部署
本系列文章不會包含:Linux、GitLab、Jenkins、Docker等基礎概念和知識,不包含Docker swarm、叢集、單元測試和自動化測試。
文章索引
- GitLab、Jenkins、Docker 初始環境安裝(本文)
- 製作 Docker映象 及 Docker Compose 的使用
- 使用 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的基本知識我就不在這裡講了,有興趣的可以瞭解下我之前寫的文章:
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中)
- 確認自身作業系統版本:注意Docker官方並不支援 Ubuntu 14.10 和 15.04,所以建議發行版儘量選擇LTS版。
1
2
# uname -r
3.13.0-86-generic
官方也不支援kernal低於3.10的版本。對於核心低於3.10版本的系統,或是升級核心,或是升級作業系統。
- 更新源
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。
- 安裝
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 |
現在你已經進入容器了,這是一個幾乎完全脫離宿主機的環境(除已掛在的資料卷),其中自帶的命令非常有限,你可以在裡面再安裝一些除錯工具。
附贈一段可以在阿里雲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了。
只要不刪除這個容器,下次你進入這個容器還可以繼續使用這些工具。
你應該只在容器中安裝不會影響原本服務的工具,這些工具應該只作為除錯檢視用,不能影響正常服務,並且可以被隨時刪除。
不要在容器內儲存重要資料(除已掛在的資料卷位置)。容器應該是狀態不重要的,可以隨時刪除隨時新建。你不應該容器內部儲存配置檔案,你應該將除錯確認的配置檔案移出容器並妥善儲存。
小結
至此,我們的基本環境已經準備好了。