阅读 735

docker&gitlab-ci实现一机多用和前端自动化

image

我们开发的流程一般是新建一个开发分支,然后开发,开发完打包部署到测试环境让测试测。但是这里有个痛点,尤其在大的团队中,我们一般会很多人共用一台测试机,这样就导致了一个问题,一旦有人在使用这个机器,那么其他人就无法使用该机器,因为切了分支就导致另外一个人的代码被切掉了,这样就导致测试机器不够用。而docker的出现,可以很好的解决这个问题。

备注:看本文需要对docker和gitlab-ci有所理解。关于这方面的知识不懂的,需要去学习下。

思路

我们在每个分支上开发准备提测的时候,就生成一个该分支特有docker镜像,该镜像基于nginx的,它会完成代码的打包和部署(到nginx上),以此来实现不同的分支代码在不同的docker容器上运行的目的,从而实现一个机器可以运行多个分支的代码的目的。

第一步: 编写Dockerfile

因为我们需要用到nginx,所以我们的镜像是基于nginx的,如果我们还要做到打包的操作,还需要用到node,假设我们的项目是在/home/test.liweiji.com下(当然这里是一个git仓库,我们需要先切换我们的分支并拉取我们自己的代码):

Dockerfile:

# 基于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.conf

# 这里根据你运行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下

# 生成镜像,不同的分支用不同的tag
docker build -t <image_name>:<tag> .
# 运行容器,端口映射大家灵活配置,这里的例子是8080,不同的分支可以用不同的端口
docker run --name <container_name> -p 8080:80 -idt <image_name>:<tag>
复制代码

这样我们就实现了不同的分支代码打包到不同的docker镜像中了。我们可以使用docker ps查看是不是在运行我们的docker容器了。

备注:如果没有运行,则说明出错了,但是docker run指令并不会告诉我们具体出错的原因,我们可以需要通过docker logs <container_name>来查看出错信息

通过上面两步,我们就可以实现了打包不同的分支代码到不同的docker镜像,让测试通过不同的镜像,测不同的分支代码。

但是这个方案还不够完善,还需要开发者跑到测试机去切分支拉代码,打包镜像运行容器。那么有什么方法让这些操作自动完成呢,答案是肯定的,那就是gitlab-ci了。

利用gitlab-ci实现自动化

gitlab-ci可以让我们提交代码后,触发gitlab-runner去运行一系列的操作,比如安装、打包、部署等。


   image 

所以,我们可以通过gitlab-ci来实现:当我们提交我们代码到远端的时候,生成该分支的最新代码对应的镜像,并运行该镜像对应的容器,从而实现自动化。

第一步:注册gitlab-runner

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。 image这里的我们只执行shell命令,所以executor选择shell。

第二步:编写.gitlab-ci.yml

我们需要在.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下看到我们任务的执行了。 image

注意:这里其实正确的任务应该是生成镜像后将镜像上传到镜像仓库,然后让测试去拉取对应分支的镜像运行容器的。我这里这样做是因为gitlab-runner和测试机在同个机器。

遇到问题

问题一:docker运行nginx报403

这个问题有两个原因,一个是权限问题,一个是首页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;
    .....
}
复制代码

问题三:docker: command not found

这个原因是因为.gitlab-ci.yml中的job没配置tags,导致share runner执行,而share runner中没有配置docker。

问题四:su: user gitlab-runner does not exist

这个原因是我们的runner指定了user为gitlab-runner但是我们的机器并没有创建这个用户,所有有两种方式解决:

  1. useradd gitlab-runner
  2. 杀掉gitlab-ci-multi-runner进程,并以其他用户运行,这里换成root运行
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镜像生成和容器运行的自动化,从而避免用户手动操作。


关注下面的标签,发现更多相似文章
评论