基于 Docker + Nginx + Gitlab-runner 实现前端自动化部署流程

本篇会用到Docker,Gitlab-runner等相关工具,如果对其不是特别了解,可以参考下相关文档:

在早期部署前端项目时,我们通常会通过ftp把前端代码直接传输到指定的物理机上,或者通过ssh登陆到指定的物理机上,然后拉取指定仓库的前端代码在本地经行打包构建,构建完成之后在通过ssh将打包之后的文件上传到ngnix指定的目录下面,这样就算部署成功啦。在实际开发中,通常会基于Docker + Nginx + Gitlab-runner 来实现前端项目的部署。接下来,我们一步一步完整的去实现整个流程:

流程图

                        +-------------------+
                        |                   |
                        |   GitLab Server   |
                        |                   |
                        +--------+----------+
                                 |
                                 | 1. 推送代码或触发CI/CD事件
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |   GitLab Runner   |
                        |                   |
                        +--------+----------+
                                 |
                                 | 2. 下载代码仓库
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |     GitLab CI      |
                        |                   |
                        +--------+----------+
                                 |
                                 | 3. 解析.gitlab-ci.yml 文件
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |    Job Executor   |
                        |                   |
                        +--------+----------+
                                 |
                                 | 4. 配置gitlab-runner环境
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |    Docker Engine  |
                        |                   |
                        +--------+----------+
                                 |
                                 | 5. 构建Docker镜像
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |     Docker        |
                        |                   |
                        +--------+----------+
                                 |
                                 | 6. 运行容器
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |  Testing / Build  |
                        |                   |
                        +--------+----------+
                                 |
                                 | 7. 运行测试/构建项目
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |     Docker        |
                        |                   |
                        +--------+----------+
                                 |
                                 | 8. 部署到生产环境
                                 |
                                 v
                        +--------+----------+
                        |                   |
                        |    Production     |
                        |                   |
                        +-------------------+

  1. 开发人员推送代码或触发CI/CD事件(如代码合并请求的开启或更新)。
  2. GitLab Server接收到事件后,将任务分配给可用的GitLab Runner。
  3. GitLab Runner下载代码仓库(包括.gitlab-ci.yml文件)到Runner主机上。
  4. GitLab CI解析.gitlab-ci.yml文件中定义的Job并配置Runner环境。
  5. Runner使用Docker Engine启动Docker容器,并根据.gitlab-ci.yml文件中的构建定义,构建一个包含构建环境和依赖的Docker镜像。
  6. 在Docker容器中运行测试和构建项目,可能包括编译代码,运行单元测试,打包应用程序等。
  7. 如果测试和构建成功,Runner将上传生成的构建物(例如dist文件)到GitLab Server,以供后续的部署步骤使用。
  8. Runner使用Docker容器,根据CI/CD的定义,将应用程序部署到生产环境中。

这个流程图涵盖了GitLab Runner、CI/CD和Docker之间的工作流程,从代码推送到应用程序的构建、测试和部署。请注意,实际流程可能因为项目的需求和配置而有所不同。

linux上安装docker

由于过程较为复杂并且也有很多详细的教程这里就不在赘述,安装过程需要注意两点:第一点是要求内核版本不低于 3.10,第二点是启动docker前,一定要关闭防火墙 因为Docker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!具体安装细节可参考这篇教程:Linux安装Docker完整教程

安装gitlab-runner并注册

一、docker拉取gitlab/gitlab-runner镜像

docker pull gitlab/gitlab-runner:latest

二、创建gitlab-runner容器

如果已经创建了容器,直接注册就行

docker run -d --name gitlab-runner 
  --restart always 
  -v /var/run/docker.sock:/var/run/docker.sock 
  gitlab/gitlab-runner:latest

三、获取 Registration token

项目主页 -> Sttings -> CI/CD -> Runners Expand

在这里插入图片描述

四、register runner

// 进入runner容器
docker exec -it [runner容器ID] /bin/bash
// 执行注册命令
gitlab-runner register

然后就会有以下自定义选项需要我们手动输入:

  1. Enter the GitLab instance URL (for example, gitlab.com/): 需要和代码仓库的域名保持一致
  2. Enter the registration token: xxx
  3. Enter a description for the runner: xxx
  4. Enter tags for the runner (comma-separated): xxx
  5. Enter optional maintenance note for the runner: xxx
  6. Enter an executor: ssh, virtualbox, docker-ssh+machine, instance, parallels, shell, docker-ssh, docker+machine, kubernetes, custom, docker: docker
  7. Enter the default Docker image (for example, ruby:2.7): alpine:latest
  8. 注册成功以后,就会在我们的项目中看到一个正在运行的 runner

在这里插入图片描述

要注意:以下选项默认不会勾选,我们要手动勾选上,否则代码提交以后,CI一直处于pedding状态,不会运行。

在这里插入图片描述

Runner has never contacted this instance

如果注册成功后进入gitlab查看runner提示 Runner has never contacted this instance 可以尝试如下的解决方式:

确认GitLab Runner已正确配置并已连接到GitLab实例。可以使用以下命令检查GitLab Runner的状态:

gitlab-runner status

如果GitLab Runner未运行,则可以使用以下命令启动它:

gitlab-runner start

确认GitLab Runner的注册令牌已正确输入。可以使用以下命令检查GitLab Runner的注册状态:

gitlab-runner verify

如果注册令牌不正确,则可以使用以下命令重新注册GitLab Runner:

gitlab-runner register

Cannot connect to the Docker daemon at unix:///var/run/docker.sock

出现这样的问题可能是在创建容器的时候一些配置文件问题,我们需要找到注册 runner 所对应的 config.toml 文件 补充如下代码

volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]

补充配置文件

Gitlab-runner 在项目中注册成功以后,我们提交代码就可以自动触发CI/CD啦,当然,还有个前提是需要创建.gitlab-ci.yml用于指定CI/CD的具体工作。同时还需要配置以下几个文件:

nginx

ngnix 的配置文件

# gzip设置
gzip on;
gzip_vary on;

gzip_comp_level 6;
gzip_buffers 16 8k;

gzip_min_length 1000;
gzip_proxied any;
gzip_disable "msie6";
#gzip_http_version 1.0;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;

server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        # 其作用是按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。
        try_files $uri /index.html;
        add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }

    location ~ .*\.(js)$ {
        root   /usr/share/nginx/html;
        add_header Cache-Control max-age=2592000;
        if ($request_filename ~* .*\initial.js$) {
            add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
        }
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dockerfile

构建一个ngnix镜像

FROM nginx:1.17.7-alpine
# MAINTAINER 7up
WORKDIR /usr/share/nginx/html
RUN rm -rf *
ARG BUILD_DIR=./dist
COPY $BUILD_DIR .
# COPY /dist/ /usr/share/nginx/html
COPY /nginx.conf /etc/nginx/conf.d/default.conf
# ADD ./dist/app.tar.gz .
RUN chown -R nginx *

创建.gitlab-ci.yml文件

具体配置可以参考 docs

# 变量
variables:
  IMAGE_NAME: 'front-develops-demo-image:latest'
  CONTAINER_NAME: 'front-develops-demo-container'

# 阶段
stages:
    - build
    - deploy

# 缓存 node_modules 减少打包时间,默认会清除 node_modules 和 dist 
cache:
  key: ${CI_BUILD_REF_NAME}
  paths:
    - node_modules/
    - dist/

# 拉取项目,打包
build:
    image: node:16.20-alpine
    stage: build
    tags:
      - dev
    script:
      - echo "=============== 开始打包任务  ==============="
      - npm config set registry https://registry.npm.taobao.org/
      - npm install -g pnpm
      - pnpm install --no-frozen-lockfile
      - pnpm run build
      - echo "=============== 执行结束 ==================="

#部署
deploy:
  image: docker
  stage: deploy
  tags:
    - dev
  script:
    - echo "=============== 开始部署任务  ==============="
    - docker build --build-arg BUILD_DIR=./dist -t $IMAGE_NAME .
    - if [ "$(docker ps -aq --filter name=$CONTAINER_NAME)" ]; then docker rm -f $CONTAINER_NAME;fi
    - docker run -d -p 9000:80 --name=$CONTAINER_NAME $IMAGE_NAME
    - echo "=============== 执行结束 ==================="

至此,准备工作就已经完成了,然后我们修改一点代码,然后提交到git仓库,此时就会自动触发CI/CD任务。然后流水线执行完成以后,就可以直接访问ip:9000查看前端页面。

这里需要注意几点:

  • 当注册runner时指定了对应的tags(例如:dev)则需要在.gitlab.yml里面定义了 tags:- dev才能触发对应的stage执行,否者的话stage会一直处于pending的状态。
  • 当注册runner时没有指定了对应的tags但是在.gitlab.yml里面定义了 tags:- xxx对应的stage也会一直处于pending的状态。
  • 如果都没有指定tag那么stage会在push的时候被执行。

docker-compose

因为我们这里只有一个镜像,在 deploy 里面写起来不是很麻烦,但是如果是需要管理很多容器呢,有没有比较好的方式呢,答案是有的我们可以使用:docker-compose

用户通过一个docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目,可以实现对Docker容器集群的快速编排。
docker-compose模板文件默认路径是当前目录下的 docker-compose.yml,可以使用.yml或.yaml作为文件扩展名。我们可以基于docker-comose对上面的.gitlab-ci.yml文件的deploy阶段进行改造:

新建一个deploy.sh 补充以下内容:

#!/bin/sh
docker build --build-arg BUILD_DIR=./dist -t front-develops-demo-image:latest . &&
docker-compose down &&
docker-compose up -d

解释一下其中用到的命令:

--build-arg 选项用于传递构建参数,-t选项用于指定镜像的名称和标签。在这个例子中,镜像的名称为 front-develops-demo-image,标签为 latest.表示当前目录

docker-compose down &&:这个命令使用Docker Compose关闭正在运行的容器。&&表示只有在前面的命令成功完成后才会执行后面的命令。

docker-compose up -d:这个命令使用Docker Compose启动并运行指定的容器。-d选项表示以守护进程模式运行容器。

我们删除掉之前定义变量的部分,同时修改关于deploy阶段的部分代码,同时也需要修改使用的image 修改之后的文件内容如下:

# 阶段
stages:
  - build
  - deploy

# 缓存 node_modules 减少打包时间,默认会清除 node_modules 和 dist 
cache:
  key: ${CI_BUILD_REF_NAME}
  paths:
    - node_modules/
    - dist/

# 拉取项目,打包
// 省略部分代码
# 部署
deploy:
  image: docker/compose:latest
  stage: deploy
  tags:
    - dev
  script:
    - sh ./deploy.sh

docker/compose:latest 这个镜像和 docker 镜像的区别:

docker/compose:latest镜像包含了预先安装和配置了 Docker Compose 的基础镜像,并且还包含了用于执行和管理 Compose 项目的工具。可以使用 docker-compose 命令来管理和运行多个 Docker 容器,同时定义它们之间的关系和设置。

docker:latest 镜像是 Docker 官方发布的用于运行 Docker 引擎的镜像,其中包含了 Docker 引擎和相关的工具,可以用来构建、运行和管理容器。

总结而言,docker/compose:latest 镜像主要用于运行 Docker Compose,而 docker:latest 镜像主要用于运行 Docker 引擎本身。

新建一个 docker-compose.yml

version: '2'
services:
  latest:
    container_name: front-develops-demo-container
    image: front-develops-demo-image:latest
    ports:
      - '9000:80'

解释一下其中用到的命令:

version: '2':指定了 Compose 文件的版本,这个版本使用的是 Docker Compose 工具的第二个版本。

services:定义了应用程序的各个组件,即服务。在这个文件中,只有一个服务被定义,名称为 “latest”。

ports:指定了容器内部端口和主机端口之间的映射关系。在这个文件中,将容器内部的 80 端口映射到了主机上的 9000 端口。

通过这个 Docker Compose 文件,开发者可以轻松地启动、停止、重启和管理多个 Docker 容器,以及定义容器之间的网络连接、数据共享、环境变量等配置信息。

merge_request

如果我们想在代码被合并之后触发对应的stage,那么我们就需要在对应的stage使用rules这里字段,具体代码如下:

job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: manual
      allow_failure: true

规则部分是一个包含一个条件的规则集合,条件是"$CI_PIPELINE_SOURCE"等于"merge_request_event"。如果条件满足,该规则将触发手动执行作业,并且允许失败(allow_failure: true)。这意味着即使作业执行失败,构建仍将继续进行而不会中断。
在这里插入图片描述
更多详细的配置可以参考这篇文章:【GitLab CI/CD】:条件、分支(rules)

环境管理

我们可以在一个项目里面注册多个 runner 并且通过不同的 tag 来区分不同的环境,然后在.gitlab.yml 里面通过 CI_MERGE_REQUEST_TARGET_BRANCH_NAME 变量来获取合并的目标分支 当我们把代码合并到 dev 就可以触发 tag 为 dev 的那个 runner 也就可以构建 dev 环境的代码,同理当我们把代码合并到 test 就可以触发 tagtest 的那个 runner 也就可以构建 test 环境的代码,这样就可以简单的实现一个多环境部署的方案。具体代码如下:
在这里插入图片描述

# 拉取项目,打包
build:
  image: node:16.20-alpine
  stage: build
  tags:
    - ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
  script:
    - echo "===============目标分支为: ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME} ==============="
    - echo "=============== 开始打包任务  ==============="
    - npm config set registry https://registry.npm.taobao.org/
    - npm install -g pnpm
    - pnpm install --no-frozen-lockfile
    - pnpm run build:${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
    - echo "=============== 执行结束 ==================="
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: on_success
      allow_failure: true

总结

至此大体实现了整个自动化部署流程的步骤,包括 GitLab Server 接收代码推送或触发 CI/CD 事件,将任务分配给可用的 GitLab RunnerGitLab Runner 下载代码仓库并配置 Runner 环境,使用 Docker Engine 启动 Docker 容器并构建包含构建环境和依赖的 Docker 镜像,运行测试和构建项目,上传构建物到 GitLab Server,最后将应用程序部署到生产环境。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值