咱们开发的流程通常是新建一个开发分支,而后开发,开发完打包部署到测试环境让测试测。可是这里有个痛点,尤为在大的团队中,咱们通常会不少人共用一台测试机,这样就致使了一个问题,一旦有人在使用这个机器,那么其余人就没法使用该机器,由于切了分支就致使另一我的的代码被切掉了,这样就致使测试机器不够用。而docker的出现,能够很好的解决这个问题。css
备注:看本文须要对docker和gitlab-ci有所理解。关于这方面的知识不懂的,须要去学习下。html
咱们在每一个分支上开发准备提测的时候,就生成一个该分支特有docker镜像,该镜像基于nginx的,它会完成代码的打包和部署(到nginx上),以此来实现不一样的分支代码在不一样的docker容器上运行的目的,从而实现一个机器能够运行多个分支的代码的目的。node
由于咱们须要用到nginx,因此咱们的镜像是基于nginx的,若是咱们还要作到打包的操做,还须要用到node,假设咱们的项目是在/home/test.liweiji.com下(固然这里是一个git仓库,咱们须要先切换咱们的分支并拉取咱们本身的代码):nginx
Dockerfile:git
# 基于node镜像
FROM node
# 设置工做路径 相似cd /home/test.liweiji.com
WORKDIR /home/test.liweiji.com
# 打包到/home/test.liweiji.com/dist目录下,固然是否是dist看本身项目
RUN npm install \
&& npm run build
# 基于nginx镜像
FROM nginx
# 通常nginx的默认配置咱们没法直接使用,因此须要用到本身的nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
复制代码
nginx.confdocker
# 这里根据你运行docker的用户来定,设置不对,会出现403
user root;
events {
use epoll;
worker_connections 102400;
}
http {
# 这个不能少,否则会致使静态样式没法起效
include mime.types;
# 下面的配置根据本身的项目而定
server {
listen 80;
server_name test.liweiji.com;
location / {
add_header Access-Control-Allow-Origin *;
root /home/test.liweiji.com/dist;
break;
}
}
}
复制代码
咱们登陆到测试机,而后进入到/home/test.liweiji.com下shell
# 生成镜像,不一样的分支用不一样的tag
docker build -t <image_name>:<tag> .
# 运行容器,端口映射你们灵活配置,这里的例子是8080,不一样的分支能够用不一样的端口
docker run --name <container_name> -p 8080:80 -idt <image_name>:<tag>
复制代码
这样咱们就实现了不一样的分支代码打包到不一样的docker镜像中了。咱们可使用docker ps查看是否是在运行咱们的docker容器了。npm
备注:若是没有运行,则说明出错了,可是docker run指令并不会告诉咱们具体出错的缘由,咱们能够须要经过docker logs <container_name>来查看出错信息bash
经过上面两步,咱们就能够实现了打包不一样的分支代码到不一样的docker镜像,让测试经过不一样的镜像,测不一样的分支代码。app
可是这个方案还不够完善,还须要开发者跑到测试机去切分支拉代码,打包镜像运行容器。那么有什么方法让这些操做自动完成呢,答案是确定的,那就是gitlab-ci了。
gitlab-ci可让咱们提交代码后,触发gitlab-runner去运行一系列的操做,好比安装、打包、部署等。
因此,咱们能够经过gitlab-ci来实现:当咱们提交咱们代码到远端的时候,生成该分支的最新代码对应的镜像,并运行该镜像对应的容器,从而实现自动化。
gitlab-ci真正的任务执行是由runner负责的,因此咱们须要在特定的机器注册runner,咱们经过gitlab-ci-multi-runner来注册runner。至于如何安装gitlab-ci-multi-runner,这里就不在讲,你们去google下。
运行gitlab-ci-multi-runner register
来注册runner,咱们按照步骤一步一步输入url、token、description、tag、executor等,咱们根据咱们gitlab网站上的setting->pipeline上找到url和token。 这里的咱们只执行shell命令,因此executor选择shell。
咱们须要在.gitlab-ci.yml中定义咱们要作的一系列操做,咱们这里须要上面所说的二个步骤:生成最新镜像和运行容器。可是为了保证每次打包都是最新代码,咱们须要有个清理的任务,因此有三个步骤:
# gitlab-cli各类变量查看https://docs.gitlab.com/ee/ci/variables/
# 执行job的阶段 按顺序串行执行
stages:
- clean
- build
- run
# 清理镜像
job1:
stage: clean
only:
- /^liweiji.*$/ # liweiji下的分支
tags:
- test
script:
- docker stop test:$CI_COMMIT_REF_NAME
- docker rm test:$CI_COMMIT_REF_NAME
- docker image rm test:$CI_COMMIT_REF_NAME
allow_failure: true #这里要容许失败,否则第一次清理是没有镜像会报错,致使后面任务没法执行
# 自定义阶段build的job流程
job2: # 自定义名字
stage: build # 指定这阶段操做的名称
only: # 指定那些分支会进入该处理流程
- /^liweiji.*$/ # liweiji下的分支
tags:
# 指定哪些runner执行script里面的操做,由于咱们上面注册runner的时候输入了test,因此这里就是test,固然你想其余runner也执行,这里就添加其余runner的tag
- test
script:
# docker build, $CI_COMMIT_REF_NAME是分支名,变量能够查看https://docs.gitlab.com/ee/ci/variables/
- cd page/public-sale
- echo `docker build -t test:$CI_COMMIT_REF_NAME . | awk -F "Successfully built " '{print $2}'`
job3:
stage: run
only:
- /^liweiji.*$/ # liweiji下的分支
tags:
- test
script:
# $CI_COMMIT_REF_NAME是分支名
- docker run --name test:$CI_COMMIT_REF_NAME -p 8000:80 -idt test:$CI_COMMIT_REF_NAME
复制代码
咱们的runner有两种类型,Specific Runners和Shared Runners,咱们一提交代码,若是.gitlab-ci.yml的job中不指定tag的话,则会执行Shared Runners,指定的话就执行tag对应的Specific Runners。
若是任务成功,咱们就能够在咱们gitlab网站的pipelines下看到咱们任务的执行了。
注意:这里其实正确的任务应该是生成镜像后将镜像上传到镜像仓库,而后让测试去拉取对应分支的镜像运行容器的。我这里这样作是由于gitlab-runner和测试机在同个机器。
这个问题有两个缘由,一个是权限问题,一个是首页index.html不存在,咱们遇到的是第一个缘由。其实上面也讲过,是由于咱们用root权限运行docker,可是nginx.conf里面没有配置user为root,因此nginx.conf的开头须要这样配置:
user root;
复制代码
这个缘由也是nginx配置致使的,由于咱们nginx本身从新配置了,因此有些配置没作好。这里nginx若是未配置mime.types的话,默认只有application/octet-stream,因此css资源能下载可是不能起效且有Resource interpreted as Stylesheet but transferred with MIME type text/plain的警告,解决办法就是在nginx.conf的http标签下添加include mime.types;
http {
include mime.types;
.....
}
复制代码
这个缘由是由于.gitlab-ci.yml中的job没配置tags,致使share runner执行,而share runner中没有配置docker。
这个缘由是咱们的runner指定了user为gitlab-runner可是咱们的机器并无建立这个用户,全部有两种方式解决:
gitlab-ci-multi-runner run --working-directory /home/gitlab-runner --config /etc/gitlab-runner/config.toml --service root--syslog --user root
复制代码
docker是一个独立的容器,相互之间隔离,咱们能够给各个docker镜像部署nginx和代码,从而利用docker实现不一样开发分支下不一样的代码运行,从而实现一机多分支代码运行。gitlab-ci能够实现自动化任务,好比安装、打包、部署等一系列任务,那么咱们就能够利用gitlab-ci来实现docker镜像生成和容器运行的自动化,从而避免用户手动操做。