有幸這幾年待過(guò)的公司devops
都做的比較完善,每天享受著一鍵編譯打包發(fā)布的快感。最近閑著無(wú)事,嘗試著在Win10
筆記本電腦上搭建一套自動(dòng)構(gòu)建平臺(tái)玩一玩,在這里記錄下過(guò)程。
目標(biāo)和基本環(huán)境
- 目前公司使用的是
gitlab
,功能豐富,對(duì)于一般的公司足夠使用。所以使用gitlab
作為代碼倉(cāng)庫(kù),用gitlab ci
組件組建持續(xù)編譯工具。 - 公司配的是
Win10
電腦,所以整體工具系統(tǒng)的搭建環(huán)境就是:win10
+docker
+gitlab
+gitlab runner
。雖然本文使用的是win10 docker
環(huán)境,但相信在mac
或linux
環(huán)境下也是一樣的。 - 這次只實(shí)現(xiàn)代碼提交到
gitlab
后的自動(dòng)編譯打包,部署等到下次有機(jī)會(huì)再研究。
整體架構(gòu)
image.png
- 這個(gè)簡(jiǎn)易的CI系統(tǒng)整體需要搭建兩個(gè)服務(wù),
gitlab
和gitlab runner
。 - 開(kāi)發(fā)人員除了代碼本身,還需要在項(xiàng)目中編寫一個(gè)
gitlab-ci.yml
文件,告訴ci
系統(tǒng)如何編譯這個(gè)項(xiàng)目,具體包含幾個(gè)ci task
。 - 在成功
git push
代碼之后,gitlab-runner
會(huì)從gitlab
上拉取需要執(zhí)行ci任務(wù)的項(xiàng)目,根據(jù)gitlab-ci.yml
中的定義執(zhí)行具體的編譯任務(wù),并產(chǎn)出交付物,提供下載或執(zhí)行后續(xù)的部署任務(wù)。
前置準(zhǔn)備
Win10 Docker安裝
- 在旗艦版
Win10
上開(kāi)啟Hyper-V
特性,安裝好docker
運(yùn)行環(huán)境,應(yīng)該是各位Windows User
的基本功,這里就不贅述了。
Docker Compose安裝
- 為了更方便的使用
docker
,我們用Docker Compose
來(lái)組織鏡像部署,安裝參考:https://docs.docker.com/compose/install/
使用Docker搭建Gitlab
編寫docker-compose.yml
- 首先我們需要一個(gè)
gitlab
,在這我使用sameersbn/gitlab
鏡像,組織的docker-compose
進(jìn)行gitlab
部署。 - 直接貼出編寫好的
yml
:
version: '2'
services:
redis:
restart: always
image: sameersbn/redis:4.0.9-2
command:
- --loglevel warning
volumes:
- redis-data:/var/lib/redis:Z
postgresql:
restart: always
image: sameersbn/postgresql:10-2
volumes:
- postgresql-data:/var/lib/postgresql:Z
environment:
- DB_USER=gitlab
- DB_PASS=password
- DB_NAME=gitlabhq_production
- DB_EXTENSION=pg_trgm
gitlab:
restart: always
image: sameersbn/gitlab:12.3.5
depends_on:
- redis
- postgresql
ports: #gitlab docker與宿主電腦的端口映射
- "10080:80" #宿主電腦的10080端口映射到docker的80端口
- "10022:22" #同上
volumes:
- gitlab-data:/home/git/data:Z
environment:
- DEBUG=false
- DB_ADAPTER=postgresql
- DB_HOST=postgresql
- DB_PORT=5432
- DB_USER=gitlab
- DB_PASS=password
- DB_NAME=gitlabhq_production
- REDIS_HOST=redis
- REDIS_PORT=6379
- TZ=Asia/Kolkata
- GITLAB_TIMEZONE=Kolkata
- GITLAB_HTTPS=false
- SSL_SELF_SIGNED=false
- GITLAB_HOST=10.130.72.51
- GITLAB_PORT=10080
- GITLAB_SSH_PORT=10022
- GITLAB_RELATIVE_URL_ROOT=
- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphanumeric-string
- GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
- GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alphanumeric-string
- GITLAB_ROOT_PASSWORD=
- GITLAB_ROOT_EMAIL=
- GITLAB_NOTIFY_ON_BROKEN_BUILDS=true
- GITLAB_NOTIFY_PUSHER=false
- GITLAB_EMAIL=notifications@example.com
- GITLAB_EMAIL_REPLY_TO=noreply@example.com
- GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com
- GITLAB_BACKUP_SCHEDULE=daily
- GITLAB_BACKUP_TIME=01:00
- SMTP_ENABLED=false
- SMTP_DOMAIN=www.example.com
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=587
- SMTP_USER=mailer@example.com
- SMTP_PASS=password
- SMTP_STARTTLS=true
- SMTP_AUTHENTICATION=login
- IMAP_ENABLED=false
- IMAP_HOST=imap.gmail.com
- IMAP_PORT=993
- IMAP_USER=mailer@example.com
- IMAP_PASS=password
- IMAP_SSL=true
- IMAP_STARTTLS=false
- OAUTH_ENABLED=false
- OAUTH_AUTO_SIGN_IN_WITH_PROVIDER=
- OAUTH_ALLOW_SSO=
- OAUTH_BLOCK_AUTO_CREATED_USERS=true
- OAUTH_AUTO_LINK_LDAP_USER=false
- OAUTH_AUTO_LINK_SAML_USER=false
- OAUTH_EXTERNAL_PROVIDERS=
- OAUTH_CAS3_LABEL=cas3
- OAUTH_CAS3_SERVER=
- OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false
- OAUTH_CAS3_LOGIN_URL=/cas/login
- OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate
- OAUTH_CAS3_LOGOUT_URL=/cas/logout
- OAUTH_GOOGLE_API_KEY=
- OAUTH_GOOGLE_APP_SECRET=
- OAUTH_GOOGLE_RESTRICT_DOMAIN=
- OAUTH_FACEBOOK_API_KEY=
- OAUTH_FACEBOOK_APP_SECRET=
- OAUTH_TWITTER_API_KEY=
- OAUTH_TWITTER_APP_SECRET=
- OAUTH_GITHUB_API_KEY=
- OAUTH_GITHUB_APP_SECRET=
- OAUTH_GITHUB_URL=
- OAUTH_GITHUB_VERIFY_SSL=
- OAUTH_GITLAB_API_KEY=
- OAUTH_GITLAB_APP_SECRET=
- OAUTH_BITBUCKET_API_KEY=
- OAUTH_BITBUCKET_APP_SECRET=
- OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=
- OAUTH_SAML_IDP_CERT_FINGERPRINT=
- OAUTH_SAML_IDP_SSO_TARGET_URL=
- OAUTH_SAML_ISSUER=
- OAUTH_SAML_LABEL="Our SAML Provider"
- OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient
- OAUTH_SAML_GROUPS_ATTRIBUTE=
- OAUTH_SAML_EXTERNAL_GROUPS=
- OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL=
- OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME=
- OAUTH_SAML_ATTRIBUTE_STATEMENTS_USERNAME=
- OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME=
- OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME=
- OAUTH_CROWD_SERVER_URL=
- OAUTH_CROWD_APP_NAME=
- OAUTH_CROWD_APP_PASSWORD=
- OAUTH_AUTH0_CLIENT_ID=
- OAUTH_AUTH0_CLIENT_SECRET=
- OAUTH_AUTH0_DOMAIN=
- OAUTH_AUTH0_SCOPE=
- OAUTH_AZURE_API_KEY=
- OAUTH_AZURE_API_SECRET=
- OAUTH_AZURE_TENANT_ID=
volumes:
redis-data:
postgresql-data:
gitlab-data:
- 關(guān)鍵點(diǎn):
-
sameersbn
的gitlab
部署,需要用到redis
,postgresql
和gitlab
,所以docker-compose.yml
中包含了這三個(gè)組件。 - 每個(gè)組件都設(shè)置了
volumes
,表示將容器內(nèi)的存儲(chǔ)地址映射到本地硬盤路徑,這樣容器就可以保存運(yùn)行時(shí)的數(shù)據(jù)狀態(tài)。 -
gitlab
中配置了端口映射,訪問(wèn)本機(jī)10080
端口將會(huì)打開(kāi)gitlab
主頁(yè)。 -
gitlab.environment
中主要把GITLAB_HOST
配置成測(cè)試用的域名,或者本機(jī)的ip
地址,因?yàn)楹罄m(xù)gitlab runner
需要通過(guò)這個(gè)地址與gitlab
通訊。其他配置可以看需要修改。
-
啟動(dòng)gitlab
-
將寫好的
docker-compose.yml
保存至一個(gè)文件夾中,如:D:\docker\gitlab\docker-compose.yml
,在命令行中進(jìn)入D:\docker\gitlab\
路徑,執(zhí)行docker-compose up
image.png -
運(yùn)行完成后,通過(guò)ip訪問(wèn)本機(jī)
10080
端口,便可看到gitlab
主頁(yè):
image.png 使用
root
帳號(hào)即可登錄。
使用Docker部署Gitlab Runner
gitlab ci配置頁(yè)
- 打開(kāi)管理中心 > 概覽 > Runner,這里能看到目前配置的
gitlab runner
:
image.png - 我們主要關(guān)注點(diǎn)是配置
runner
使用的url
和token
。
編寫Runner docker-compose并執(zhí)行
version: '3'
services:
runner:
image: 'gitlab/gitlab-runner:v11.4.2'
container_name: gitlab-runner
restart: always
privileged: true
volumes:
- ./config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
- 關(guān)鍵點(diǎn):在
volumes
需要指定docker.sock
,這個(gè)與docker
執(zhí)行的上下文環(huán)境有關(guān),這里不作太多說(shuō)明。 - 同樣的,把文件保存到一個(gè)單獨(dú)目錄,執(zhí)行
docker-compose up
:
image.png
注冊(cè)Gitlab Runner
- 運(yùn)行
docker exec -it gitlab-runner gitlab-runner register
命令,將docker
中的gitlab-runner
注冊(cè)到gitlab
上:
image.png - 依次輸入
gitlab
配置頁(yè)面上的url
,token
,runner
的描述,runner
的tag
(多個(gè)可以用逗號(hào)隔開(kāi)),executor
類型使用docker
,默認(rèn)的鏡像使用docker
。 -
注冊(cè)完成后,在gitlab管理頁(yè)面上就能看到runner:
image.png
創(chuàng)建SpringBoot項(xiàng)目,對(duì)接gitlab-ci
在Gitalb中創(chuàng)建Project
- 創(chuàng)建
Project
并提交Springboot
項(xiàng)目代碼,這里不贅述過(guò)程。
編寫.gitlab-ci.yml配置文件
- 在項(xiàng)目源碼根目錄下,創(chuàng)建
.gitlab-ci.yml
文件,這文件描述了ci
過(guò)程的各個(gè)任務(wù)和需要的資源。
image: docker:latest #1
variables: #2
MAVEN_OPTS: "-Dmaven.repo.local=.m2"
DOCKER_DRIVER: overlay2
cache: #3 緩存maven repository
key: maven-repository-cache
paths:
- .m2
services: #4 使用docker鏡像執(zhí)行任務(wù)
- docker:dind
stages: #5 定義CI過(guò)程有幾個(gè)stage
- package
maven-package: #6 定義一個(gè)task
image: maven:3.5-jdk-8-alpine
tags: # 此任務(wù)在具有哪個(gè)tag上的runner執(zhí)行
- maven
stage: package # 此task對(duì)應(yīng)哪個(gè)stage
script:
- mvn clean package -Dmaven.test.skip=true
artifacts: # CI交付物
paths:
- target/*.jar
expire_in: 1 day # 一天后過(guò)期
- 關(guān)鍵點(diǎn):
-
stage
:定義ci過(guò)程有幾個(gè)階段,gitlab-ci
會(huì)按順序執(zhí)行每個(gè)stage
。 -
task
定義maven-package
:-
stage
:指定這個(gè)task
屬于哪個(gè)階段。同一個(gè)階段下的所有task
并發(fā)執(zhí)行。 -
tag
:指定此task要在具有哪個(gè)tag的runner上執(zhí)行,可以實(shí)現(xiàn)需要不同編譯環(huán)境的任務(wù)在特定runner
上運(yùn)行,如ios app
編譯需要在mac
環(huán)境下的runner
運(yùn)行。 -
image
:此任務(wù)使用哪個(gè)鏡像進(jìn)行ci
任務(wù),這里使用帶有maven-jdk
的鏡像。 -
script
:ci
任務(wù)的執(zhí)行腳本,springboot
項(xiàng)目使用mvn
命令進(jìn)行編譯打包。
-
-
提交代碼,觸發(fā)gitlab-ci
- 編寫好項(xiàng)目代碼和
.gitlab-ci.yml
,Push至gitlab,就會(huì)觸發(fā)ci過(guò)程:
image.png -
CI
任務(wù)的詳細(xì)過(guò)程,可以在這個(gè)頁(yè)面中下載到CI
交付物:
image.png
優(yōu)化點(diǎn)和后續(xù)
- 目前
maven
編譯使用的是公共maven
鏡像,默認(rèn)連接的是中央倉(cāng)庫(kù),我們可以繼承它做一個(gè)連接到公司私服的maven
鏡像,提供給ci
任務(wù)進(jìn)行編譯。 - 這個(gè)示例
ci
只做了編譯,后續(xù)可以對(duì)接k8s
實(shí)現(xiàn)自動(dòng)部署,這樣一整套CI/CD
工具就完整了。