Gitlab CI 学习笔记
1 VMware和Linux系统的安装
安装VMware
VMware下载地址:
百度网盘地址 提取码:n2h4
VMware激活码:
YG5H2-ANZ0H-M8ERY-TXZZZ-YKRV8
安装过程简单,省略
安装CentOS-7
在VMware中新建虚拟机,[安装程序光盘映像文件(ISO)]选择为下载的iso文件即可,安装过程简单省略
2 GitLab CI的安装
2.1 docker 的安装
安装路径
win7和win8安装docker使用的是DockerToolbox,其他操作系统直接到Docker官网上下载
docker服务启动
点击Docker Quickstart Terminal
启动docker服务,启动成果如下图所示:
docker安装发现的问题:
第一次启动docker服务时,docker服务将从github下载最新的boot2docker.iso
文件,如果一直下载失败,可先关闭互联网连接,再启动docker服务,此时将不再从github上更新文件。
2.2 gitlab的安装
Docker 命令安装方法
下载 gitlab-ce 镜像
docker pull gitlab/gitlab-ce
windows docker 启动 gitlab-ce 镜像
初始化配置文件路径和 volume
mkdir C:/DockerData/gitlab-ce/etc
mkdir C:/DockerData/gitlab-ce/log
mkdir C:/DockerData/gitlab-ce/data
docker volume create gitlab-logs
docker volume create gitlab-data
启动命令
docker run --detach --name gitlab --restart always --hostname localhost --publish 10443:443 --publish 10080:80 --publish 1022:22 --volume C:/DockerData/gitlab-ce/etc:/etc/gitlab --volume gitlab-logs:/var/log/gitlab --volume gitlab-data:/var/opt/gitlab gitlab/gitlab-ce
linux docker 启动 gitlab-ce 镜像
创建 gitlab 配置目录
mkdir /home/gitlab/config
mkdir /home/gitlab/logs
mkdir /home/gitlab/data
启动命令
docker run -d -p 10443:443 -p 10080:80 -p 1022:22 --name gitlab --restart always -v /home/gitlab/config:/etc/gitlab -v /home/gitlab/logs:/var/log/gitlab -v /home/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce
# 设置打开文件数量上限
docker run -d -p 443:443 -p 80:80 --name gitlab2 --restart=on-failure:3 --ulimit nofile=65536:131072 -v /mtx/storage/gitlab/config:/etc/gitlab -v /mtx/storage/gitlab/logs:/var/log/gitlab -v /mtx/storage/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce
GUI 工具安装方法
- 首先启动docker服务
- 打开docker GUI工具
Kitematic (Alpha)
- 搜索框中输入gitlab
- 选择
gitlab-ce
点击create
,下载镜像文件 - 点击
START
启动镜像文件 - 访问gitlab页面
http://IP:port
,IP地址为docker服务使用的默认IP地址,port端口在镜像参数中设置,前面docker启动参数中:-p 10443:443 -p 10080:80 -p 1022:22,将docker容器的443端口映射为主机的10443端口,将80端口映射为10080端口,将22端口映射为10022端口,则访问路径为http://IP:10080, - 系统启动后,root用户的默认密码存储在/home/gitlab/config/initial_root_password 中,登录后应立即修改密码,24小时后密码失效
- 修改gitlab配置中的host地址,否则创建项目的的克隆地址错误:
- /home/gitlab/data/gitlab-rails/etc/gitlab.yml,将host的值改为IP地址
/home/gitlab/config/gitlab.rb,修改external_url 'http://IP'
2.3 gitlab-runner 的安装
Docker 命令安装方法
下载 gitlab-runner 镜像
docker pull gitlab/gitlab-runner
创建 gitlab-runner 配置文件目录
mkdir C:/DockerData/gitlab-runner/config
启动 gitlab-runner
docker run -d --name gitlab-runner --link gitlab --restart always -v /var/run/docker.sock:/var/run/docker.sock -v C:/DockerData/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner:latest
GUI工具安装方法
- 首先启动docker服务
- 打开docker GUI工具
Kitematic (Alpha)
- 搜索框中输入
gitlab-runner
- 选择
gitlab-runner
点击create
,下载镜像文件 - 点击
START
启动镜像文件
2.4 gitlab-runner注册至gitlab
- 获取gitlab注册Runner的
url
和token
- Shared Runner的
url
和token
的获取: - Specific Runner的
url
和token
的获取:
- Shared Runner的
- 注册Runner
docker exec -it gitlab-runner gitlab-runner register
# 输入 GitLab 地址
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://192.168.99.100:8080/
# 输入 GitLab Token
Please enter the gitlab-ci token for this runner:
1Lxq_f1NRfCfeNbE5WRh
# 输入 Runner 的说明
Please enter the gitlab-ci description for this runner:
可以为空
# 设置 Tag,可以用于指定在构建规定的 tag 时触发 ci
Please enter the gitlab-ci tags for this runner (comma separated):
可以为空
# 选择 runner 执行器,这里我们选择的是 shell
Please enter the executor: virtualbox, docker+machine, parallels, shell, ssh, docker-ssh+machine, kubernetes, docker, docker-ssh:
shell
3 GitLab CI 相关知识
3.1 持续集成(Continuous Integration)
在传统软件的开发中,代码的集成工作通常是在所有人都将工作完成后在项目即将结束进行时,而这往往会花费大量的时间和精力。而持续集成可以在开发人员提交了新代码后,立刻进行构建、单元测试。
3.2 GitLab 的持续集成
从 GitLab 8.0 开始,GitLab CI 就已经集成在 GitLab 中,我们只需在项目中添加一个.gitlab-ci.yml
文件,然后添加一个Runner
,即可进行持续集成。
3.3 GitLab-Runner简介
GitLab-Runner就是一个用来执行.gitlab-ci.yml 脚本的工具。
GitLab-CI就像是工人的管理中心,GitLab-Runner就是执行工作的工人,所有工人都要在GitLab-CI里面注册,并表明所服务的项目。当项目发生变化时,GitLab-CI就会通知GitLab-Runner执行项目的.gitlab-ci.yml
脚本。
GitLab-Runner可以分类两种类型:
- Shared Runner(共享型):所有工程都能够用的,且只有系统管理员能够创建。
- Specific Runner(指定型):只有特定的项目可以使用。
3.4 GitLab CI的执行过程
管道(pipeline)
每个push
到GitLab的提交都会产生一个关联的管道(pipeline),若一次push
中包含多个commit
,则管道与最后一个commit
关联,管道(pipeline)就是一个分成不同阶段(stage)的作业(job)的集合。
阶段(stage)
阶段(stage)是批量作业(job)在逻辑上的划分,每个GitLab CI都必须包含至少一个阶段(stage)。多个阶段(stage)是顺序执行的,其中一个阶段(stage)执行失败,后续的都不再执行,这个CI过程执行失败。
整个 CI 过程包含三个阶段:
- 编译(build)
- 测试(test)
- 部署(deploy)
作业(job)
作业(job)是Runner要执行的指令集合,一个阶段(stage)关联至多个作业(job),当一个阶段(stage)执行时,其所关联的所有作业(job)将全部并发执行,作业(job)的状态直接同步到阶段(stage)的状态。
作业(job)是由脚本(script)组成的,为了避免重复的脚本内容,.gitlab-ci.yml
中提供了before_script
和after_script
两个全局配置项,用来执行所有作业(job)的前置脚本和后置脚本。
作业(job)的执行过程中会产生一些缓存数据(cache),默认情况下GitLab-Runner会保存这些数据,供其他作业(job)启动时加载使用,不同作业(job)的不同GitLab-Runner也能彼此共享缓存数据(cache)。
3.5 YAML 语法简介
YAML在开发时是一种标记语言,YAML的配置文件以 .yml
结尾。
基本语法
- 大小写敏感
- 使用缩进表示层级关系,
- 缩进只能使用空格
- 缩进的空格数量不重要,同层级元素的左侧必须对齐
#
表示注释
数据类型
- 对象 :键值对的集合
- 数组 :一组按次序排列的值
- 纯量(scalars):单个的、不可再分的值
对象
key:
key: value
或
key: {key1:value1, key2:value2}
数组
key:
- value1
- value2
纯量
- 布尔值
- 整数
- 浮点数
- 字符串
- Null
- 日期和时间
boolean:
- TRUE #true,True都可以
- FALSE #false,False都可以
float:
- 3.14
- 6.8523015e+5 #可以使用科学计数法
int:
- 123
- 0b1010_0111_0100_1010_1110 #二进制表示
null:
parent: ~ #使用~表示null
string:
- 哈哈
- 'Hello world' #可以使用双引号或者单引号包裹特殊字符
- newline
newline2 #字符串可以拆成多行,每一行会被转化成一个空格
date:
- 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime:
- 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
引用
重复的内容可以使用锚点 &
声明引用名称,使用 *
获取锚点的数据,使用 <<
将获取到的锚点数据合并到当前数据。
default: &default
ip: 127.0.0.1
port: 8888
dev:
db: development
<<: *default
相当于:
default: &default
ip: 127.0.0.1
port: 8888
dev:
db: development
ip: 127.0.0.1
port: 8888
3.6 GitLab CI配置文件简介
从7.12版本开始,GitLab CI使用YAML文件.gitlab-ci.yml
来管理项目配置。
该文件存放于项目仓库的根目录,并且包含了你的项目如何被编译的描述语句。
YAML文件使用一系列约束叙述定义了job启动时所要做的事情。
关键字介绍
名称 | 含义 |
---|---|
script | 由Runner执行的Shell脚本。 |
image | 使用docker镜像,image:name |
service | 使用docker services镜像, services:name |
before_script | 执行作业前运行的脚本 |
after_script | 作业完成后运行的脚本 |
stages | 定义管道中的步骤,依次运行 |
stage | 定义管道中步骤的作业段 |
only | 指定作业限制only:refs,only:kubernetes,only:variables,和only:changes |
tags | 指定执行作业的runner |
allow_failure | 允许job失败 |
when | 什么时候开始工作,on_success(只有当前一个阶段的所有工作都成功时(或者因为它们被标记而被认为是成功的allow_failure)才执行工作 。这是默认值。)、on_failure(仅当前一阶段的至少一个作业失败时才执行作业。)、always(无论先前阶段的工作状态如何,都可以执行工作。)、manual(手动执行作业)和delayed(延迟作业。后面跟start_in,start_in 30minutes(延迟30分钟),不加单位,默认为秒。最长可延迟1小时。) |
cache | 缓存。key:"$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" #为每分支,每步骤启用缓存。 |
artifacts | job成功时附加到作业的文件或目录 |
dependencies | 此job依赖其他jobs,主要作用于作业优先级 |
converage | 给定作业代码覆盖率设置 |
retry | 在发生故障时,可以自动重试作业的次数。 |
parallel | 应该并行运行多少个作业实例 |
trigger | 定义下游管道触发器 |
include | 允许此作业包含外部YAML |
extends | 此作业将继承的配置项 |
pages | 上传作业结果用于gitlab pages |
variables | 作业级别定义作业变量 |
environment | 作业部署到的环境名称 |
job
job是由一系列参数定义了任务启动时所要做的事情。
job名称需保证唯一性,关键字不能为job名称。
job中的stage
属性关联至stages的那个阶段,未设置stage时默认关联至test stage,script
属性为job执行的shell命令。
job1:
# 关联到bulid阶段
stage: build
# 所需执行的脚本
script:
# 执行shell命令
- echo "start job1"
stages and stage
stages 定义了所有 job 可以使用的 stage,默认包含 build、test 和 deploy 三个 stage。
stages 中 stage 的定义顺序为其执行顺序,多个 job 关联至相同的 stage 时,这些 job 将并行执行(在拥有足够Runner情况下)。
stages:
- build
- test
- deploy
job 2:
stage: build
script: make build artifacts
job 3:
stage: test
script: make test
job 4:
stage: deploy
script: make deploy
script
script是一段由Runner执行的shell脚本。
job:
script: "bundle exec rspec"
这个参数也可以使用数组包涵好几条命令:
job:
script:
- uname -a
- bundle exec rspec
script命令中存在YAML特殊字符时需要进行转义,特殊字符有 : { } [ ] , & * #? | - < > = ! % @
image and services
image 指定 docker 镜像的名称
services 指定 docker 服务
#为每个作业定义不同的映像和服务
test:2.1:
image: ruby:2.1
services:
- postgres:9.3
script:
- bundle exec rake spec
before_script and after_script
before_script是用于定义一些在所有任务执行前所需执行的命令, 包括部署工作,可以接受一个数组或者多行字符串。
after_script用于定义所有job执行过后需要执行的命令,可以接受一个数组或者多行字符串。
# 定义全局 before_script:
default:
before_script:
- global before script
# job覆盖全局before_script
job:
before_script:
- execute this instead of global before script
script:
- my command
after_script:
- execute this after my script
only and except
only 定义了 job 需要执行的所在分支或者标签。
except 定义了 job 不会执行的所在分支或者标签。
only和except两个参数说明了job什么时候将会被创建。
使用规则:
- only和except如果都存在在一个job声明中,则所需引用将会被only和except所定义的分支过滤。
- only和except允许使用正则。
- only和except允许使用指定仓库地址,但是不forks仓库。
| 值 | 描述 |
| --- | --- |
| branches | 当一个分支被push上来 |
| tags | 当一个打了tag的分支被push上来 |
| api | 当一个pipline被piplines api所触发调起,详见piplines api |
| external | 当使用了GitLab以外的CI服务 |
| pipelines | 针对多项目触发器而言,当使用CI_JOB_TOKEN并使用gitlab所提供的api创建多个pipelines的时候 |
| pushes | 当pipeline被用户的git push操作所触发的时候 |
| schedules | 针对预定好的pipline而言(每日构建一类,具体请看说明文档
) |
| triggers | 用token创建piplines的时候 |
| web | 在GitLab页面上Pipelines标签页下,你按了run pipline的时候 |
下面的例子,job将会只在issue-开头的refs下执行,反之则其他所有分支被跳过:
job:
# use regexp
only:
- /^issue-.*$/
# use special keyword
except:
- branches
tags
tags 用于指定已经关联的 Runner 执行 job
job:
tags:
- ruby
- postgres
更多配置,参考官方文档
示例
# 定义docker镜像名称
image: xx:1.0
# 定义 stages(阶段)。任务将按此顺序执行。
stages:
- build
- test
- deploy
# 定义 job(任务)
job1:
stage: test
tags:
- XX #只有标签为XX的runner才会执行这个任务
only:
- dev #只有dev分支提交代码才会执行这个任务。也可以是分支名称或触发器名称
- /^future-.*$/ #正则表达式,只有future-开头的分支才会执行
script:
- echo "I am job1"
- echo "I am in test stage"
# 定义 job
job2:
stage: test #如果此处没有定义stage,其默认也是test
only:
- master #只有master分支提交代码才会执行这个任务
script:
- echo "I am job2"
- echo "I am in test stage"
allow_failure: true #允许失败,即不影响下步构建
# 定义 job
job3:
stage: build
except:
- dev #除了dev分支,其它分支提交代码都会执行这个任务
script:
- echo "I am job3"
- echo "I am in build stage"
when: always #不管前面几步成功与否,永远会执行这一步。它有几个值:on_success (默认值)\on_failure\always\manual(手动执行)
# 定义 job
.job4: #对于临时不想执行的job,可以选择在前面加个".",这样就会跳过此步任务,否则你除了要注释掉这个jobj外,还需要注释上面为deploy的stage
stage: deploy
script:
- echo "I am job4"
# 模板,相当于公用函数,有重复任务时很有用
.job_template: &job_definition # 创建一个锚,'job_definition'
image: ruby:2.1
services:
- postgres
- redis
test1:
<<: *job_definition # 利用锚'job_definition'来合并
script:
- test1 project
test2:
<<: *job_definition # 利用锚'job_definition'来合并
script:
- test2 project
#下面几个都相当于全局变量,都可以添加到具体job中,这时会被子job的覆盖
before_script:
- echo "每个job之前都会执行"
after_script:
- echo "每个job之后都会执行"
variables: #变量
DATABASE_URL: "postgres://postgres@postgres/my_database" #在job中可以用${DATABASE_URL}来使用这个变量。常用的预定义变量有CI_COMMIT_REF_NAME(项目所在的分支或标签名称),CI_JOB_NAME(任务名称),CI_JOB_STAGE(任务阶段)
GIT_STRATEGY: "none" #GIT策略,定义拉取代码的方式,有3种:clone/fetch/none,默认为clone,速度最慢,每步job都会重新clone一次代码。我们一般将它设置为none,在具体任务里设置为fetch就可以满足需求,毕竟不是每步都需要新代码,那也不符合我们测试的流程
cache: #缓存
#因为缓存为不同管道和任务间共享,可能会覆盖,所以有时需要设置key
key: ${CI_COMMIT_REF_NAME} # 启用每分支缓存。
#key: "$CI_JOB_NAME/$CI_COMMIT_REF_NAME" # 启用每个任务和每个分支缓存。需要注意的是,如果是在windows中运行这个脚本,需要把$换成%
untracked: true #缓存所有Git未跟踪的文件
paths: #以下2个文件夹会被缓存起来,下次构建会解压出来
- node_modules/
- dist/
验证方式
https://gitlab地址/ci/lint
4 Docker 镜像制作
4.1 Docker 简介
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
4.2 Docker 架构
Docker 的相关概念:
概念 | 说明 |
---|---|
Docker 镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板,就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。 |
Docker 容器(Container) | 容器是独立运行的一个或一组应用,是镜像运行时的实体。 |
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 | |
Docker 客户端(Client) | Docker 客户端通过命令行或者其他工具使用 Docker SDK |
与 Docker 的守护进程通信。 | |
Docker 主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
Docker 仓库(Registry) | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。 |
Docker Hub(https://hub.docker.com | |
) 提供了庞大的镜像集合供使用。 | |
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。 | |
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 | |
Docker Machine | Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。 |
4.3 Docker 镜像命令
docker
深入的了解指定的 Docker 命令使用方法:
docker command --help
docker image
列出本地镜像列表
- REPOSITORY :镜像的仓库源
- TAG :镜像的标签
- IMAGE ID :镜像的ID
- CREATE :镜像的创建时间
- SIZE :镜像的大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
docker search
从docker仓库查询镜像
docker search ubuntu
- NAME :镜像的名称
- DESCRIPTION : 镜像的描述
- STARTS : 点赞的数量
- OFFICIAL :是否为 docker 官方发布
- AUTOMATION :是否自动构建
docker pull
从docker仓库获取新的镜像
docker pull REPOSITORY:TAG
当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull 命令来下载它。
docker rmi
删除本地镜像
docker rmi REPOSITORY:TAG
镜像创建
从 docker 仓库下载的镜像进行定制时有两种修改方式:
- 更新镜像:从已创建的容器中更新镜像,并提交这个镜像
- 构建镜像:使用 Dockerfile 指令来创建新的镜像
更新镜像
首先使用旧的镜像创建一个容器
docker run -i -t centos:latest /bin/bash
在运行的容器内使用shell命令或 apt-get update
命令进行跟新,更新完成后使用 exit
退出容器。
提交镜像文件
docker commit -m="镜像详细描述" -a="作者" 13d9da61e07d centos:latest-commit
参数说明:
- -m : 镜像的详细描述
- -a : 镜像作者名称
- 13d9da61e07d :容器的ID
- centos:latest-commit : 镜像的 DESCRIPTION 和 TAG
构建镜像
首先创建 Dockerfile 文件,填写指令告诉 docker 如何构建镜像。
例如:
FROM centos:6.7
MAINTAINER Fisher "fisher@sudops.com"
RUN /bin/echo 'root:123456' |chpasswd
RUN useradd runoob
RUN /bin/echo 'runoob:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd -D
docker build 命令构建镜像
docker build -t test/centos:6.7 .
参数说明:
- -t :指要创建的镜像名称
- . :Dockerfile文件所在目录,也可使用Dockerfile文件的绝对路径
设置镜像标签
docker tag 镜像ID 用户名称/镜像源名称:标签名称
4.4 Docker 容器指令
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载。
docker ps -a
查看所以 docker 容器信息
docker run
使用 docker 镜像启动一个容器
docker run -i -t centos /bin/bash
参数说明:
- -i :交互式操作
- -t :终端
- -d :后台执行
- -P :将容器内部使用的网络端口随机映射到主机上。
- -p :指定容器的网络端口对应于主机上的端口,主机端口 :容器端口
- -v :指定容器目录挂载的本地目录,主机目录 :容器目录
- --name :指定 docker 镜像的名称
- ubuntu:latest :镜像的描述和镜像的标签
- /bin/bash :放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash
docker stop
停止容器
docker stop 容器ID
docker restart
重启容器
docker restart 容器ID
进入Docker容器
容器使用 -d
参数启动时,可以使用以下指令进入容器:
- docker attach :进入容器后执行
exit
退出时,会导致容器的停止 - docker exec : 进入容器后执行
exit
退出时,容器不会停止
docker attach
使用方法:
docker attach 容器ID
docker exec
使用方法:
docker -i -t 容器ID /bin/bash
docker export
导出容器快照到本地文件。
使用方法:
docker export 容器ID > xxx.tar
docker import
容器快照文件导入为镜像文件。
使用方法:
docker import file xxx/xxx:xxx
docker import url xxx/xxx:xxx
docker rm
删除容器,执行时容器必须是停止状态,否则会报。
使用方法:
docker rm -f 容器ID
docker port
查看容器的端口映射信息。
使用方法:
docker port 容器ID
docker logs
查看容器内部的标准输出。
使用方法:
docker logs -f 容器ID
参数说明:
- -f :输出容器内部的标准输出
docker top
查看容器内部运行进程信息。
使用方法:
docker top 容器ID
docker inspect
查看docker容器的底层信息,返回一个json字符串记录了容器的配置和状态信息。
使用方法:
docker inspect 容器ID
4.5 Docker 容器互联
通常的使用方法是容器网络端口映射,将容器的端口映射到主机的端口上,然后容器之间通过映射到主机上的端口进行相互访问。另外一种就是通过新建网络的方式进行容器互联。
docker network ls
查看 docker 网络信息。
docker network create
创建 docker 网络。
docker network create -d bridge test-net
容器启动时指定 docker 网络
docker run -itd --name test1 --network test-net ubuntu /bin/bash
docker run -itd --name test2 --network test-net ubuntu /bin/bash
这样容器 test1 和容器 test2 就能互联了。
4.6 Docker 容器配置DNS
容器配置DNS有两种办法,全局的DNS修改使用修改配置文件
方法,单个容器的修改使用增加启动参数
方法。
修改配置文件
修改 daemon.json ,重启 docker 服务后生效。
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
增加启动参数
使用方法:
docker run -it --rm host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu
参数说明:
- **-h HOSTNAME 或者 --hostname=HOSTNAME **: 设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。
- --dns=IP_ADDRESS : 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
- --dns-search=DOMAIN : 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com。
4.7 Dockerfile 简介
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
Dockerfile中的简要指令如下图所示:
gitlab-runner的定制
- 创建 docker 目录
- 在 docker 目录创建Dockerfile文件:
FROM gitlab/gitlab-runner:v11.0.2
RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' > /etc/apt/sources.list && \
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> /etc/apt/sources.list && \
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' >> /etc/apt/sources.list && \
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' >> /etc/apt/sources.list && \
apt-get update -y && \
apt-get clean
RUN apt-get -y install apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add - && \
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" && \
apt-get update -y && \
apt-get install -y docker-ce
COPY daemon.json /etc/docker/daemon.json
WORKDIR /usr/local/bin
RUN wget https://raw.githubusercontent.com/topsale/resources/master/docker/docker-compose
RUN chmod +x docker-compose
RUN mkdir -p /usr/local/java
WORKDIR /usr/local/java
COPY jdk-8u152-linux-x64.tar.gz /usr/local/java
RUN tar -zxvf jdk-8u152-linux-x64.tar.gz && \
rm -fr jdk-8u152-linux-x64.tar.gz
RUN mkdir -p /usr/local/maven
WORKDIR /usr/local/maven
RUN wget https://raw.githubusercontent.com/topsale/resources/master/maven/apache-maven-3.5.3-bin.tar.gz
RUN tar -zxvf apache-maven-3.5.3-bin.tar.gz && \
rm -fr apache-maven-3.5.3-bin.tar.gz
ENV JAVA_HOME /usr/local/java/jdk1.8.0_152
ENV MAVEN_HOME /usr/local/maven/apache-maven-3.5.3
ENV PATH $PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin
WORKDIR /
- 在 docker 目录创建 daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com"
],
"insecure-registries": [
"ip:port"
]
}
- docker build gitlab/gitlab-runner:java-test .
4.8 Docker Compose简介
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
Compose 使用的三个步骤:
- 使用 Dockerfile 定义应用程序的环境。
- 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
- 执行 docker-compose up 命令来启动并运行整个应用程序。
5 GitLab CI 持续集成 JAVA 项目
以公司部署的 gitlab 为基础,进行金骏眉项目的持续集成。
以下内容的前提为 gitlab 和 gitlab-runner 的安装以及注册过程已经完成,gitlab-runner 已安装项目编译工具。
持续集成过程的关键内容为:在 gitlab 的项目添加 .gitlab-ci.yml 文件,编写 gitlab-runner 的执行内容。
5.1 Maven 项目
.gitlab-ci.yml 文件示例:
stages:
- build
- test
- deploy
job-build:
stage: build
script:
- git config --global user.email "452437621@163.com"
- git config --global user.name "venus"
- cd /home/gitlab-runner
- test -d demo && (echo "git pull" && cd demo && git pull) || (echo "git clone" && git clone http://192.168.0.105:10080/venus/demo.git )
- cd /home/gitlab-runner/demo
- mvn clean compile
- mvn package -Dmaven.test.skip=true
- echo "build success"
job-test:
stage: test
script:
- mvn test
- echo "test success"
job-deploy:
stage: deploy
script:
- ps -ef |grep java |grep -v grep |awk '{print $2}' | xargs -t -n 1 kill -9
- cd /home/gitlab-runner/demo/target/
- (java -jar demo-0.0.1-SNAPSHOT.jar &)
- echo "build deploy"
5.2 Ant 项目
build.xml 文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<project name="ant_web_hello">
<!-- java源代码目录 -->
<property name="src.dir" location="src" />
<!-- 构建目录 -->
<property name="build.dir" location="build" />
<!-- class文件目录 -->
<property name="build.classes" location="${build.dir}/classes" />
<!-- 打包目录 -->
<property name="build.war" location="${build.dir}/war" />
<!-- tomcat根目录 -->
<property name="tomcat.home" location="C:\Program Files (x86)\apache-tomcat-7.0.100" />
<!-- web 应用的名字,也是打包后war的名字 -->
<property name="web.name" value="ant-demo" />
<!-- web 根目录 -->
<property name="web.root" value="WebContent" />
<property name="web.WEB-INF" location="${web.root}/WEB-INF" />
<property name="web.lib" location="${web.WEB-INF}/lib" />
<property name="mysqldriver" location="${web.lib}/mysql-connector-java-8.0.18.jar" />
<!-- 加载环境变量 -->
<property environment="env" />
<!-- 定义编译时的classpath -->
<path id="compile.path">
<fileset dir="${web.lib}" includes="*.lib">
</fileset>
<fileset dir="${tomcat.home}/lib">
<include name="*.jar" />
</fileset>
</path>
<target name="init" description="初始化">
<mkdir dir="${build.dir}" />
<mkdir dir="${build.classes}" />
<mkdir dir="${build.war}" />
<echo>初始化工作结束!</echo>
</target>
<target name="compile" depends="init" description="编译">
<javac srcdir="${src.dir}" destdir="${build.classes}" includeantruntime="false" fork="true" source="1.8" target="1.8">
<compilerarg line="-encoding UTF-8 " />
<classpath refid="compile.path" />
</javac>
<echo message="编译完成!" />
</target>
<target name="war" depends="compile" description="打包war文件">
<war destfile="${build.war}/${web.name}.war">
<fileset dir="${web.root}" includes="**/*.*" />
<lib dir="${web.lib}" />
<webinf dir="${web.WEB-INF}" />
<classes dir="${build.classes}" />
</war>
<echo>打包完成!</echo>
</target>
<presetdef name="mysql-admin">
<sql userid="root" password="xxx" url="jdbc:mysql://192.168.0.105:3306/mysql?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull" driver="com.mysql.jdbc.Driver" classpath="${mysqldriver}" print="true" encoding="utf-8">
</sql>
</presetdef>
<target name="mysql-init" description="初始化数据库">
<mysql-admin>
<transaction src="student.sql" />
</mysql-admin>
<echo>数据库初始化完成!</echo>
</target>
<target name="mysql-test" depends="mysql-init" description="数据库测试">
<mysql-admin>
<transaction>
use student;
select database();
show tables;
select * from student;
</transaction>
</mysql-admin>
<echo>数据库测试完成!</echo>
</target>
<target name="testenv" description="测试环境变量">
<echo>JAVA_HOME:${env.JAVA_HOME}</echo>
<echo>CLASSPATH:${env.CLASSPATH}</echo>
<echo>tomcat_home:${tomcat.home}</echo>
<echo>${web.lib}</echo>
<echo>${mysqldriver}</echo>
</target>
<target name="deploy" depends="mysql-test,war" description="发布">
<copy todir="${tomcat.home}/webapps">
<fileset dir="${build.war}" includes="*.war" />
</copy>
<echo>已发布到Tomcat!</echo>
</target>
<target name="clean" description="清理">
<delete dir="${build.dir}" />
<delete dir="${tomcat.home}/webapps/${web.name}" />
<delete file="${tomcat.home}/webapps/${web.name}.war" />
<echo>清理完成!</echo>
</target>
</project>
.gitlab-ci.yml 文件示例:
cache:
paths:
- /home/gitlab-runner/ant-demo/
stages:
- clean
- build
- test
- deploy
job-clean:
stage: clean
script:
- test `ps -ef |grep java |grep -v grep |wc -l` -gt 0 && ps -ef |grep java |grep -v grep |awk '{print $2}' | xargs -t -n 1 kill -9 || echo "No java process !"
- echo "clean success"
job-build:
stage: build
script:
- git config --global user.email "452437621@163.com"
- git config --global user.name "venus"
- cd /home/gitlab-runner
- test -d ant-demo && (echo "git pull" && cd ant-demo && git pull) || (echo "git clone" && git clone http://192.168.0.105:10080/venus/ant-demo.git )
- cd /home/gitlab-runner/ant-demo
- sed -i 's#<property name="tomcat.home" location=".*" />#<property name="tomcat.home" location="/usr/local/apache-tomcat-7.0.100" />#g' build.xml
- ant clean
- ant deploy
- echo "build success"
job-test:
stage: test
script:
- cd /home/gitlab-runner/ant-demo/
- ant mysql-init
- ant mysql-test
- echo "test success"
job-deploy:
stage: deploy
script:
- cd /usr/local/apache-tomcat-7.0.100/bin
- ./startup.sh
- echo "deploy success"
6 Gitlab CI 概要汇总
总结以上的内容,重新梳理需要掌握的知识和关键步骤。
6.1 内容梳理
- 安装过程(docker → gitlab → gitlab-runner → 注册 gitlab-runner)
- docker 知识学习(docker 命令、Dockerfile 构建 Docker镜像)
- .gitlab-ci.yml 文件( YAML 语法学习、.gitlab-ci.yml 格式定义)
- gitlab 创建 Java 项目,编写并提交代码,测试 CI 过程(学习 maven 和 ant 命令语法)。
6.1 gitlab-runner 定制过程
定制步骤如下:
- 制作Dockerfile,以及所需的依赖环境的安装文件。
- docker build 构建 gitlab-runner 镜像
docker build -t gitlab/gitlab-runner:maven-demo-v1 .
- 启动 gitlab-runner 容器
docker run -d -p 8888:8888 --name demo --link gitlab --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner:maven-demo-v1
docker run -d -p 8080:8080 --name ant-demo --link gitlab --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner:ant-demo-v1
- gitlab-runner 注册至 gitlab 的项目
docker exec -it a7996d40d9de gitlab-runner register
- gitlab的项目跟新,测试gitlab-runner
git push