GitLab+Docker快速搭建CI/CD自動(dòng)化部署

什么是持續(xù)集成(Continuous integration)?
CI
在持續(xù)集成環(huán)境中,開(kāi)發(fā)人員將會(huì)頻繁得提交代碼到主干。這些新提交在最終合并到主線之前,都需要通過(guò)編譯和自動(dòng)化測(cè)試進(jìn)行驗(yàn)證。這樣做是基于之前持續(xù)集成過(guò)程中很重視自動(dòng)化測(cè)試驗(yàn)證結(jié)果,以保障所有得提交在合并主干之后得質(zhì)量問(wèn)題,對(duì)可能出現(xiàn)得一些問(wèn)題進(jìn)行預(yù)計(jì)。
持續(xù)交付(Continuous Delivery)
持續(xù)交付就是講我們得應(yīng)用發(fā)布出去的過(guò)程。這個(gè)過(guò)程可以確保我們盡量可能快的實(shí)現(xiàn)交付。這就意味著除了自動(dòng)化測(cè)試,我們還需要有自動(dòng)化的發(fā)布流,以及通過(guò)一個(gè)按鍵就可以隨時(shí)隨地實(shí)現(xiàn)應(yīng)用的部署上線
通過(guò)持續(xù)交付,可以決定每天,每周,每?jī)芍馨l(fā)布一次,這完全可以根據(jù)自己的業(yè)務(wù)進(jìn)行設(shè)置。
但是,如果你真的希望體驗(yàn)持續(xù)交付的優(yōu)勢(shì),就需要先進(jìn)行小批量發(fā)布,盡快部署到生產(chǎn)線,以便在出現(xiàn)問(wèn)題時(shí)方便進(jìn)行故障排除。
持續(xù)部署(Continuous Deployment)
如果我們想更加深入一步的話,就是持續(xù)部署了。通過(guò)這個(gè)方式,任何修改通過(guò)了所有已有的工作流就會(huì)直接和客戶見(jiàn)面。沒(méi)有人為干預(yù)(沒(méi)有一鍵部署按鈕),只有當(dāng)一個(gè)修改在工作流中構(gòu)建失敗才能阻止它部署到產(chǎn)品線。
持續(xù)部署是一個(gè)很優(yōu)秀的方式,可以加速與客戶的反饋循環(huán),但是會(huì)給團(tuán)隊(duì)帶來(lái)壓力,因?yàn)椴辉儆?發(fā)布日"了。開(kāi)發(fā)人員可以專注于構(gòu)建軟件,他們看到他們修改在他們完成工作后幾分鐘就上線了?;旧?,當(dāng)開(kāi)發(fā)人員在主分支合并一個(gè)提交時(shí),這個(gè)分支將被構(gòu)建,測(cè)試,如果一切順利,則部署到生產(chǎn)環(huán)境中。
持續(xù)集成需求
持續(xù)集成是通過(guò)平臺(tái)串聯(lián)各個(gè)開(kāi)發(fā)環(huán)節(jié),實(shí)現(xiàn)和沉淀工作自動(dòng)化的方法。 線上代碼和代碼倉(cāng)庫(kù)不同步,影響迭代和團(tuán)隊(duì)協(xié)作。 靜態(tài)資源發(fā)布依賴人工,浪費(fèi)開(kāi)發(fā)人力。 缺少自動(dòng)化測(cè)試,產(chǎn)品質(zhì)量得不到保障 文案簡(jiǎn)單修改上線,需要技術(shù)介入。

Gitlab
Gitlab是一個(gè)開(kāi)源的版本管理系統(tǒng),實(shí)現(xiàn)一個(gè)自托管的Git項(xiàng)目倉(cāng)庫(kù),可通過(guò)Web界面進(jìn)行訪問(wèn)公開(kāi)的或者私人項(xiàng)目。它擁有與Github類似的功能,能夠?yàn)g覽源碼,管理缺陷和注釋,可以管理團(tuán)隊(duì)對(duì)倉(cāng)庫(kù)的訪問(wèn),它非常易于瀏覽提交的版本并提供一個(gè)文件歷史庫(kù)。團(tuán)隊(duì)成員可以利用內(nèi)置的簡(jiǎn)單的聊天程序進(jìn)行交流。它還提供一個(gè)代碼片段收集功能可以實(shí)現(xiàn)代碼復(fù)用。
GitLab對(duì)于系統(tǒng)性能有要求,所以我們需要將克隆出來(lái)的虛擬機(jī)的內(nèi)存提高到至少2G以上。
Gitlab安裝
方法一:
sudo docker run --detach \
--hostname localhost \
--publish 443:443 --publish 8084:8084 --publish 222:22 \
--name gitlab \
--restart always \
--volume /home/docker/gitlab/config:/etc/gitlab \
--volume /home/docker/gitlab/logs:/var/log/gitlab \
--volume /home/docker/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
localhost:主機(jī)名,即虛擬機(jī)的ip,8084可以自己定義端口號(hào),restart重啟方式,volume目錄掛載,gitlab/gitlab-ce:latest鏡像名。
方法二:
docker pull twang2218/gitlab-ce-zh
等待其拉取,然后在 /home下新建docker目錄,再在其下新建gitlab目錄,進(jìn)入gitlab目錄,在當(dāng)前目錄下新建docker-compose.yml配置文件,編寫內(nèi)容如下。
version: '3'
services:
web:
image: 'twang2218/gitlab-ce-zh' #gitlab鏡像
restart: always
privileged: true #權(quán)限
hostname: '' #主機(jī)名,即虛擬機(jī)的ip
environment:
TZ: 'Asia/Shanghai'
GITLAB_OMNIBUS_CONFIG: |
external_url '' #主機(jī)名,即虛擬機(jī)的ip
gitlab_rails['gitlab_shell_ssh_port'] = 2222
unicorn['port'] = 8888
nginx['listen_port'] = 8084
ports:
- '8084:8084'
- '8443:443'
- '2222:22'
volumes:
- './config:/etc/gitlab'
- './logs:/var/log/gitlab'
- './data:/var/opt/gitlab'
執(zhí)行docker-compose up,然后進(jìn)入等待時(shí)間,等它下好了去通過(guò)自己設(shè)置的虛擬機(jī)的ip和端口號(hào)訪問(wèn)。

如果安裝過(guò)程中有報(bào)錯(cuò)權(quán)限問(wèn)題,那么加上privileged: true
查看方式:
root@iZm5ebvlfc3n55vzckl9ifZ:# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ddc7d0e214ef twang2218/gitlab-ce-zh "/assets/wrapper" 30 hours ago Up 6 hours (healthy) 80/tcp, 0.0.0.0:8084->8084/tcp, 0.0.0.0:2222->22/tcp, 0.0.0.0:8443->443/tcp gitlab_web_1
通過(guò)虛擬主機(jī)的ip+端口訪問(wèn),此時(shí)需要設(shè)置管理員密碼,賬號(hào)為root,密碼最少為8位。
登錄成功后,如下:

項(xiàng)目創(chuàng)建
點(diǎn)擊 + 號(hào) --> 新建項(xiàng)目

輸入項(xiàng)目名稱及描述信息,設(shè)置可見(jiàn)等級(jí):私有,內(nèi)部,公開(kāi)。

初始化項(xiàng)目
我們可以選擇通過(guò)增加一個(gè)README的方式來(lái)初始化項(xiàng)目,如下:


創(chuàng)建項(xiàng)目的時(shí)候有一個(gè)問(wèn)題,在自己最開(kāi)始定義了端口號(hào),創(chuàng)建項(xiàng)目的時(shí)候會(huì)沒(méi)有端口號(hào),這時(shí)候clone項(xiàng)目的時(shí)候會(huì)訪問(wèn)不了,這時(shí)候我們?cè)谧铋_(kāi)始安裝定義目錄里面config目錄下找到gitlab.rb,編輯它,搜索external_url,沒(méi)有就添加external_url:主機(jī)ip+端口號(hào),有就修改就行了。這時(shí)候我們就可以去克隆項(xiàng)目了。當(dāng)然我們也可以通過(guò)下面方法去把項(xiàng)目推送到gitlab上面:


Gitlab-Runner
安裝
sudo docker run -d --name gitlab-runner --restart always \
-v /home/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
映射/var/run/docker.sock這個(gè)文件是為了讓容器可以通過(guò)/var/run/docker.sock與Docker守護(hù)進(jìn)程通信,管理其他Docker容器 -v /home/gitlab-runner/config:/etc/gitlab-runner是將runner的配置文件映射到宿主機(jī)/home/gitlab-runner/config方便調(diào)整和查看配置
安裝完成我們需要去注冊(cè)Gitlab-Runner。
運(yùn)行docker ps查看:
root@iZm5ebvlfc3n55vzckl9ifZ:/home/docker/gitlab# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed6c7a038263 gitlab/gitlab-runner:latest "/usr/bin/dumb-init …" 24 hours ago Up 24 hours gitlab-runner
ddc7d0e214ef twang2218/gitlab-ce-zh "/assets/wrapper" 30 hours ago Up 6 hours (healthy) 80/tcp, 0.0.0.0:8084->8084/tcp, 0.0.0.0:2222->22/tcp, 0.0.0.0:8443->443/tcp gitlab_web_1
注冊(cè)
docker run --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \
--url "" \
--registration-token "" \
--description "first-register-runner" \
--tag-list "vue3-app" \
--run-untagged="true" \
--locked="false" \
--access-level="not_protected"
注冊(cè)需要輸出url,token,描述,tag,執(zhí)行器等,url和token怎么來(lái)的呢?在設(shè)置->CI/CD->Runner里面,我這里面注冊(cè)了一個(gè)專用的和共享的Runner,正常情況我們用專用Runner就可以了。共享版Runner是登錄root賬戶在頭部小扳手圖片里面的Runner得到url和token,然后去注冊(cè)。這里面的tag值會(huì)在編寫.gitlab-ci.yml時(shí)用到。

運(yùn)行流水線
在項(xiàng)目根目錄里面創(chuàng)建一個(gè).gitlab-ci.yml,編寫代碼如下:
image: node:alpine
stages: # 分段
- install
- eslint
- build
- deploy
cache: # 緩存
paths:
- node_modules
job_install:
tags:
- vue3-app
stage: install
script:
- npm install
job_build:
tags:
- vue3-app
stage: build
script:
- npm run build
參數(shù)說(shuō)明:
stages:pipeline的階段列表,定義整個(gè)pipeline階段 stage:定義某個(gè)job的所在階段 image:指定一個(gè)基礎(chǔ)Docker進(jìn)行作為基礎(chǔ)運(yùn)行環(huán)境,比如:node,python,java tags:用于指定Runner,tags的取值范圍是在該項(xiàng)目可惜可見(jiàn)的runner tags中,也就是前面我們?cè)O(shè)置的那個(gè)tag only/except:知道當(dāng)前任務(wù)條件 when:實(shí)現(xiàn)在發(fā)生故障時(shí)仍能運(yùn)行的作業(yè) cache:講當(dāng)前工作環(huán)境目錄中的一些文件,文件夾存儲(chǔ)起來(lái),用于在各個(gè)任務(wù)初始化的時(shí)候恢復(fù) environment:指定部署相關(guān)任務(wù)的環(huán)境,并非真實(shí)環(huán)境,是對(duì)要部署到某環(huán)境的任務(wù)的歸類。方便在gitlab上聚合以便進(jìn)行回滾和重新部署操作 artifacts:保留文檔。在每次 job 之前runner會(huì)清除未被 git 跟蹤的文件。為了讓編譯或其他操作后的產(chǎn)物可以留存到后續(xù)使用,添加該參數(shù)并設(shè)置保留的目錄,保留時(shí)間等。被保留的文件將被上傳到gitlab以備后續(xù)使用。 dependencies:任務(wù)依賴。指定job的前置job。添加該參數(shù)后,可以獲取到前置job的artifacts。注意如果前置 job 執(zhí)行失敗,導(dǎo)致沒(méi)能生成artifacts,則 job 也會(huì)直接失敗。
編寫好上面代碼后推送到gitlab后就會(huì)自己執(zhí)行里面的語(yǔ)句:

部署
在項(xiàng)目中創(chuàng)建一個(gè)Dockerfile,代碼如下:
FROM node:latest as builder
WORKDIR /app
COPY package.json
RUN npm install --registry=http://registry.npm.taobao.org
COPY ..
RUN npm run build
FROM nginx:latest
COPY --from=builder /app/dist /usr/share/nginx/html
.gitlab-ci.yml修改如下:
image: node:alpine
stages: # 分段
- install
- eslint
- build
- deploy
cache: # 緩存
paths:
- node_modules
job_install:
tags:
- vue3-app
stage: install
script:
- npm install
job_build:
tags:
- vue3-app
stage: build
script:
- npm run build
job_deploy:
image: docker
stage: deploy
script:
- docker build -t appimages
- if [ $(docker ps -aq --filter name=app-container) ]; then docker rm -f app-container;fi
- docker run -d -p 8082:80 --name app-container appimages
if語(yǔ)句判斷:使用docker命令去搜索docker容器里面是否有一個(gè)name為app-container的容器,如果有就銷毀掉,銷毀掉是為了使用新的容器重新運(yùn)行。
這里image:docker不寫的話會(huì)報(bào)錯(cuò):

代碼推送后,流水線工作,到第三步就會(huì)出下報(bào)錯(cuò):


解決辦法,在runner配置文件中配置docker命令:
"/usr/bin/docker:/usr/bin/docker", "/var/run/docker.sock:/var/run/docker.sock"
在gitlab-runner->config-vim config.toml,找到注冊(cè)runner所對(duì)應(yīng)的token,在volumes數(shù)組里面加入上面命令:
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "first-register-runner"
url = ""
token = ""
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "alpine:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache","/usr/bin/docker:/usr/bin/docker", "/var/run/docker.sock:/var/run/docker.sock"]
shm_size = 0
我們?cè)谌ブ匦逻\(yùn)行失敗的Jobs,這時(shí)候發(fā)現(xiàn)成功了:

然后通過(guò)前面注冊(cè)的端口號(hào)去訪問(wèn),可以正常訪問(wèn)項(xiàng)目。
原文
juejin.cn/post/6967972435064782879
