有幸这几年待过的公司devops
都做的比较完善,每天享受着一键编译打包发布的快感。最近闲着无事,尝试着在Win10
笔记本电脑上搭建一套自动构建平台玩一玩,在这里记录下过程。
目标和基本环境
- 目前公司使用的是
gitlab
,功能丰富,对于一般的公司足够使用。所以使用gitlab
作为代码仓库,用gitlab ci
组件组建持续编译工具。 - 公司配的是
Win10
电脑,所以整体工具系统的搭建环境就是:win10
+docker
+gitlab
+gitlab runner
。虽然本文使用的是win10 docker
环境,但相信在mac
或linux
环境下也是一样的。 - 这次只实现代码提交到
gitlab
后的自动编译打包,部署等到下次有机会再研究。
整体架构
- 这个简易的CI系统整体需要搭建两个服务,
gitlab
和gitlab runner
。 - 开发人员除了代码本身,还需要在项目中编写一个
gitlab-ci.yml
文件,告诉ci
系统如何编译这个项目,具体包含几个ci task
。 - 在成功
git push
代码之后,gitlab-runner
会从gitlab
上拉取需要执行ci任务的项目,根据gitlab-ci.yml
中的定义执行具体的编译任务,并产出交付物,提供下载或执行后续的部署任务。
前置准备
Win10 Docker安装
- 在旗舰版
Win10
上开启Hyper-V
特性,安装好docker
运行环境,应该是各位Windows User
的基本功,这里就不赘述了。
Docker Compose安装
- 为了更方便的使用
docker
,我们用Docker Compose
来组织镜像部署,安装参考:https://docs.docker.com/compose/install/
使用Docker搭建Gitlab
编写docker-compose.yml
- 首先我们需要一个
gitlab
,在这我使用sameersbn/gitlab
镜像,组织的docker-compose
进行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:
- 关键点:
-
sameersbn
的gitlab
部署,需要用到redis
,postgresql
和gitlab
,所以docker-compose.yml
中包含了这三个组件。 - 每个组件都设置了
volumes
,表示将容器内的存储地址映射到本地硬盘路径,这样容器就可以保存运行时的数据状态。 -
gitlab
中配置了端口映射,访问本机10080
端口将会打开gitlab
主页。 -
gitlab.environment
中主要把GITLAB_HOST
配置成测试用的域名,或者本机的ip
地址,因为后续gitlab runner
需要通过这个地址与gitlab
通讯。其他配置可以看需要修改。
-
启动gitlab
-
将写好的
docker-compose.yml
保存至一个文件夹中,如:D:\docker\gitlab\docker-compose.yml
,在命令行中进入D:\docker\gitlab\
路径,执行docker-compose up
-
运行完成后,通过ip访问本机
10080
端口,便可看到gitlab
主页:
使用
root
帐号即可登录。
使用Docker部署Gitlab Runner
gitlab ci配置页
- 打开管理中心 > 概览 > Runner,这里能看到目前配置的
gitlab runner
:
- 我们主要关注点是配置
runner
使用的url
和token
。
编写Runner docker-compose并执行
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
- 关键点:在
volumes
需要指定docker.sock
,这个与docker
执行的上下文环境有关,这里不作太多说明。 - 同样的,把文件保存到一个单独目录,执行
docker-compose up
:
注册Gitlab Runner
- 运行
docker exec -it gitlab-runner gitlab-runner register
命令,将docker
中的gitlab-runner
注册到gitlab
上:
- 依次输入
gitlab
配置页面上的url
,token
,runner
的描述,runner
的tag
(多个可以用逗号隔开),executor
类型使用docker
,默认的镜像使用docker
。 -
注册完成后,在gitlab管理页面上就能看到runner:
创建SpringBoot项目,对接gitlab-ci
在Gitalb中创建Project
- 创建
Project
并提交Springboot
项目代码,这里不赘述过程。
编写.gitlab-ci.yml配置文件
- 在项目源码根目录下,创建
.gitlab-ci.yml
文件,这文件描述了ci
过程的各个任务和需要的资源。
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镜像执行任务
- docker:dind
stages: #5 定义CI过程有几个stage
- package
maven-package: #6 定义一个task
image: maven:3.5-jdk-8-alpine
tags: # 此任务在具有哪个tag上的runner执行
- maven
stage: package # 此task对应哪个stage
script:
- mvn clean package -Dmaven.test.skip=true
artifacts: # CI交付物
paths:
- target/*.jar
expire_in: 1 day # 一天后过期
- 关键点:
-
stage
:定义ci过程有几个阶段,gitlab-ci
会按顺序执行每个stage
。 -
task
定义maven-package
:-
stage
:指定这个task
属于哪个阶段。同一个阶段下的所有task
并发执行。 -
tag
:指定此task要在具有哪个tag的runner上执行,可以实现需要不同编译环境的任务在特定runner
上运行,如ios app
编译需要在mac
环境下的runner
运行。 -
image
:此任务使用哪个镜像进行ci
任务,这里使用带有maven-jdk
的镜像。 -
script
:ci
任务的执行脚本,springboot
项目使用mvn
命令进行编译打包。
-
-
提交代码,触发gitlab-ci
- 编写好项目代码和
.gitlab-ci.yml
,Push至gitlab,就会触发ci过程:
-
CI
任务的详细过程,可以在这个页面中下载到CI
交付物:
优化点和后续
- 目前
maven
编译使用的是公共maven
镜像,默认连接的是中央仓库,我们可以继承它做一个连接到公司私服的maven
镜像,提供给ci
任务进行编译。 - 这个示例
ci
只做了编译,后续可以对接k8s
实现自动部署,这样一整套CI/CD
工具就完整了。