gitlab-runner CI/CD持续集成 docker部署

896 阅读3分钟

1.运行

1. docker-compose

docker-compose-gitlab-runner.yml

version: '3'
services:
  gitlab-runner:
    image: gitlab/gitlab-runner:v14.6.1
    container_name: runner
    restart: unless-stopped
    privileged: true
    volumes:
      - /home/gitlab-runner/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/bin/docker #宿主机的docker可执行映射到镜像里面 后面build的时候会用到
    environment:
    pull_policy: 
      - if-not-present

docker-compose -f docker-compose-runner.yml up

2. docker run

docker run -it -v /data/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner:v14.9.0

注意

1. 启动提示下面信息是正常的,需要开始配置

ERROR: Failed to load config stat /etc/gitlab-runner/config.toml: no such file or directory builds=0

2.配置

1. 在gitlab的 对应的项目里查看 设置 url 和 token 信息

image.png

image.png

2.注册

docker exec -it [id] bash
gitlab-runner register

  • 根据提示依次输入 url 和 token ,(该信息在项目的setting -> CI/CD -> runners里 配置)
  • 由于已经把外部宿主服务器的docker 传到runner,所以执行类型选择shell 方式既可以操作docker
  • 如果需要单独运行容器- 可以选择类型为docker

3.执行run

gitlab-runner run

4.查看

image.png

3.常用命令

gitlab-runner register  #默认交互模式下使用,非交互模式添加 --non-interactive
gitlab-runner list      #此命令列出了保存在配置文件中的所有运行程序
gitlab-runner verify    #此命令检查注册的runner是否可以连接,但不验证GitLab服务是否正在使用runner。 gitlab-runner verify --delete --name=node2 # 删除配置  记得如果删除失败,必须在原有项目的CI/CD 移除关联的配置

4.优化生成的配置

vi /home/gitlab-runner/config/config.toml
# 添加 挂载了宿主机的docker缓存,提高效率
volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
# 防止Runner重复拉取镜像
pull_policy = "if-not-present"
# 进入容器 重启
docker exec it runner  gitlab-runner restart

5.关键字

1.全局配置关键字

default 工作关键字的自定义默认值。 stages 流水线阶段的名称和顺序。 variables 为管道中的所有作业定义 CI/CD 变量。 workflow 控制运行什么类型的管道。 before_script 覆盖在作业之前执行的一组命令。

2.使用作业关键字配置的作业:

before_script 覆盖在作业之前执行的一组命令。 cache 应在后续运行之间缓存的文件列表。 image 使用 Docker 镜像。 only 控制何时创建工作。 script 由运行程序执行的 Shell 脚本。 stage 定义作业阶段。 services 使用 Docker 服务镜像。 variables 在工作级别定义工作变量。 tags 用于选择跑步者的标签列表。

6 .gitlab-ci.yml 配置

在项目 CI/CD 里面进行编辑

image.png

点击commit 进行提交,提交后触发构建

共享数据问题

不同的docker 构建 都是独立的沙盒,需要通过关键字 cache 和 artifacts共享数据

注意

  • only用来指定分支,不支持variables变量定义,否则会一直Checking pipeline status 无限等待

7.vue 构建

.gitlab-ci.yml


variables:
  DOCKER_NAME: vue_test  # 镜像名称
  DOCKER_IMAGE: vue_test:1.0  # 镜像完整版本
  RUNNER_SHELL_TAG: myrunner3  # gitlab-runner定义的shell tag
  RUNNER_DOCKER_TAG: docker1  # gitlab-runner定义的docker tag
stages:
  - build
  - deploy
cache:
  paths:
    - node_modules/
    - dist/
 
build_node:
  stage: build
  image: node:14-alpine
  script:
    - echo "============ npm 打包 ============"
    # 修改源
    - npm config set registry https://registry.npmmirror.com --global
    - npm install
    - npm run build
    - cp -rf dist/* ./
    - pwd
    - ls
  artifacts: # 配合cache 实现 多个job 共享dist
    expire_in: 1 week
    paths:
      - dist/
  tags:
    - $RUNNER_DOCKER_TAG

build_deploy:
  stage: deploy
  script:
    - echo "============ dockerfile生成 ============"
    - pwd
    - ls
    - docker build -t $DOCKER_IMAGE . 
    - echo "============ docker运行 ============"
    - docker stop -f $DOCKER_NAME  || true
    - docker rm -f $DOCKER_NAME  || true
    - docker run --rm -it -d -p 8081:8080 --name=$DOCKER_NAME $DOCKER_IMAGE
  tags:
    - $RUNNER_SHELL_TAG

Dockerfile

FROM nginx:alpine

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /usr/share/nginx/html

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories

RUN apk update \
    && apk upgrade \
    && apk --update add logrotate \
    && apk add --no-cache openssl \
    && apk add --no-cache bash

RUN apk add --no-cache curl

RUN set -x ; \
    addgroup -g 82 -S www-data ; \
    adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1

# ARG PHP_UPSTREAM_CONTAINER=php-fpm
# ARG PHP_UPSTREAM_PORT=9000

# Create 'messages' file used from 'logrotate'
RUN touch /var/log/messages

# Copy 'logrotate' config file
# COPY logrotate/nginx /etc/logrotate.d/

COPY ./dist /usr/share/nginx/html 
COPY ./nginx.conf /etc/nginx
# CMD ["nginx", "-g", "'daemon off;'"]
# ADD ./startup.sh /opt/startup.sh
# RUN sed -i 's/\r//g' /opt/startup.sh
# CMD ["/bin/bash", "/opt/startup.sh"]

EXPOSE 8080

nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;
# daemon off;

events {
  worker_connections  2048;
  multi_accept on;
  use epoll;
}

http {
  server_tokens off;
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  open_file_cache off; # Disabled for issue 619
  charset UTF-8;

  keepalive_timeout  65; # 加长时长
  keepalive_requests 10000;# 加长时长
  underscores_in_headers on; 
  log_format  main  'clientIp: $remote_addr - $remote_user [$time_local] "[$request]" '
                    '$status $body_bytes_sent "[$http_referer]" '
                    '"$http_user_agent" "$http_x_forwarded_for"'
                      '$upstream_addr [time::{$upstream_response_time || $request_time}] ';
  log_format log404 '$status [$time_local] $remote_addr $host$request_uri $sent_http_location';

  #打开 gzip
  gzip on;
  gzip_min_length 1k;
  gzip_buffers 4 16k;
  gzip_comp_level 5;
  gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg 
              image/gif image/png;
  gzip_vary on;
  gzip_disable "MSIE [1-6]\.";
  gzip_static on;
  
  add_header Cache-Control no-cache;  # 这里是有配置ip才生效,域名需要单独配置
  index  index.html index.htm;

  error_page 401 402 403 404 /404.html;
  error_page 500 502 503 /50x.html;

  types_hash_max_size 2048;
  client_max_body_size 100M;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  access_log  /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  # ssl协议统一设置
  ssl_protocols TLSv1 TLSv1.2 TLSv1.3;
  ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout 5m;
  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_verify_depth 10;

  # 实际读取的配置路径
  server {
      listen       8080;
      server_name localhost;  

          location / {
              root   /usr/share/nginx/html;
              try_files $uri $uri/ /index.html;
          } 
  }
}

8.node构建

.gitlab-ci.yml

variables:
  DOCKER_NAME: node_test  # 镜像名称
  DOCKER_IMAGE: node_test:1.0  # 镜像完整版本
  RUNNER_SHELL_TAG: myrunner  # gitlab-runner定义的shell tag
stages:
  - deploy
 
before_script:
  - echo "先停止和删除老的容器"
  - docker stop -f $DOCKER_NAME  || true
  - docker rm -f $DOCKER_NAME  || true
 
cache: #缓存文件夹,不删除
  paths:
    - node_modules/
 
deploy_master:
  stage: deploy
  script:
    - docker build -t $DOCKER_IMAGE .
    - docker run --rm -it -d -p 3330:3000 --name=$DOCKER_NAME $DOCKER_IMAGE
  only:
    - master
  tags:
    - $RUNNER_SHELL_TAG

Dockerfile

FROM node:11.6.0
RUN mkdir -p /home/Service
WORKDIR /home/Service
 
COPY . /home/Service
RUN yarn install
 
EXPOSE 3000
 
CMD [ "node", "index.js" ]

index.js

const express = require('express')
const app = express()
 
app.get('/', (req, res) => {
  res.send({a:1222})
})
 
app.listen(3000, () => {
  console.log("3000端口启动了")
})

package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "test",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  }
}

9.参考项目

github.com/mjsong07/do…