在本文中,我将介绍如何基于 GitLab 和 GitLab Runner 进行 CI/CD 部署。GitLab 是一个强大的 Git 仓库管理系统,提供了完整的 CI/CD 管理功能。GitLab Runner 是一个用于运行 CI/CD 作业的轻量级容器化工具。我们将使用 Docker 容器来运行 GitLab 和 GitLab Runner。
配置 GitLab
首先,我们需要配置 GitLab。我们可以使用 Docker Compose 来快速创建 GitLab 容器。以下是一个基本的 Docker Compose 配置文件示例:
代码语言:javascript复制vbnetCopy codeversion: '3'
services:
web:
image: 'gitlab/gitlab-ce:latest'
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.example.com'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
ports:
- '80:80'
- '443:443'
- '2222:22'
volumes:
- '/srv/gitlab/config:/etc/gitlab'
- '/srv/gitlab/logs:/var/log/gitlab'
- '/srv/gitlab/data:/var/opt/gitlab'
在这个配置文件中,我们定义了一个名为 web 的服务,使用 gitlab/gitlab-ce 镜像创建。我们还定义了主机名、端口和挂载卷,以及一些环境变量。
要启动 GitLab 容器,请运行以下命令:
代码语言:javascript复制Copy codedocker-compose up -d
现在我们可以在浏览器中访问 http://gitlab.example.com 来访问 GitLab。
注册 GitLab Runner
接下来,我们需要注册 GitLab Runner。我们可以使用 Docker 容器来运行 GitLab Runner。
首先,我们需要创建一个名为 gitlab-runner 的 Docker 网络:
代码语言:javascript复制luaCopy codedocker network create gitlab-runner
然后,我们可以使用 Docker 容器来运行 GitLab Runner:
代码语言:javascript复制bashCopy codedocker run -d --name gitlab-runner --restart always
-v /srv/gitlab-runner/config:/etc/gitlab-runner
-v /var/run/docker.sock:/var/run/docker.sock
--network gitlab-runner
gitlab/gitlab-runner:latest
在这个命令中,我们使用 gitlab/gitlab-runner 镜像来创建 GitLab Runner 容器。我们还将配置文件和 Docker 套接字挂载到容器中,以便 GitLab Runner 可以访问它们。最后,我们将容器添加到 gitlab-runner 网络中。
接下来,我们需要在 GitLab 中注册 GitLab Runner。在 GitLab 中,转到 Administration -> Runners 页面,点击 Register Runner 按钮。在注册表单中,输入 GitLab Runner 的名称和描述,并选择 Runner 类型和标签。在 Runner 可执行程序输入框中输入 docker,并在 Runner Token 输入框中输入 GitLab Runner 的 token。点击 Register Runner 按钮完成注册。
现在,我们已经成功注册了 GitLab Runner,并可以在 GitLab 中创建 CI/CD 作业。
创建 CI/CD现在我们可以创建 CI/CD 作业了。以下是一个简单的示例:
代码语言:javascript复制yamlCopy codestages:
- build
- test
- deploy
build_job:
stage: build
script:
- docker build -t myimage .
artifacts:
paths:
- myimage.tar.gz
test_job:
stage: test
script:
- docker load -i myimage.tar.gz
- docker run myimage npm test
deploy_job:
stage: deploy
script:
- docker load -i myimage.tar.gz
- docker tag myimage myregistry/myimage
- docker push myregistry/myimage
在这个示例中,我们定义了三个阶段:build、test 和 deploy。在 build 阶段,我们使用 Docker 构建一个名为 myimage 的镜像,并将其保存为 myimage.tar.gz 文件。在 test 阶段,我们加载 myimage.tar.gz 文件,并运行该镜像中的 npm test 命令。在 deploy 阶段,我们加载 myimage.tar.gz 文件,并将其重新标记为 myregistry/myimage,并将其推送到一个 Docker registry 中。
我们可以将以上的 YAML 代码保存为 .gitlab-ci.yml
文件,并将其提交到 GitLab 仓库。当我们提交代码时,GitLab Runner 会自动执行 CI/CD 作业。
完整示例
以下是一个更完整的示例,它使用 Docker Compose 文件和多个 GitLab Runner 运行器来运行一个完整的 CI/CD 流水线:
docker-compose.yml
代码语言:javascript复制yamlCopy codeversion: '3'
services:
app:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: development
db:
image: postgres:12-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "80:80"
gitlab:
image: gitlab/gitlab-ce:latest
restart: always
hostname: gitlab.example.com
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.example.com'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
ports:
- "80:80"
- "443:443"
- "2222:22"
volumes:
- ./gitlab/config:/etc/gitlab
- ./gitlab/logs:/var/log/gitlab
- ./gitlab/data:/var/opt/gitlab
runner1:
image: gitlab/gitlab-runner:latest
restart: always
volumes:
- ./runner1/config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
networks:
- gitlab-runner
runner2:
image: gitlab/gitlab-runner:latest
restart: always
volumes:
- ./runner2/config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
networks:
- gitlab-runner
networks:
gitlab-runner:
driver: bridge
nginx.conf
代码语言:javascript复制perlCopy codeworker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://app:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
.gitlab-ci.yml
代码语言:javascript复制yamlCopy codestages:
- build
- test
- deploy
build:
image: docker:latest
services:
- docker:dind
stage: build
script:
- docker build -t myapp .
- docker save myapp:latest | gzip > myapp.tar.gz
artifacts:
paths:
- myapp.tar.gz
test:
image: node:14
stage: test
script:
- apt-get update && apt-get install -y git
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/${CI_PROJECT_PATH}
- cd ${CI_PROJECT_NAME}
- npm install
- npm test
deploy:
image: docker:latest
services:
- docker:dind
stage: deploy
script:
- docker load < myapp.tar.gz
- docker tag myapp:latest registry.example.com/myapp:latest
- docker push registry.example.com/myapp:latest
该示例使用 Docker Compose 文件启动了四个容器:
- app:运行我们的应用程序。
- db:运行 PostgreSQL 数据库。
- nginx:运行 Nginx 反向代理,将流量转发到我们的应用程序。
- gitlab:运行 GitLab CE。
我们在 .gitlab-ci.yml 文件中定义了三个工作流程:
- build:构建 Docker 镜像并将其打包成 tar.gz 文件,该文件将被传递到下一个阶段的 artifacts 中。
- test:检查应用程序是否可以运行,并运行测试。
- deploy:从先前构建的 tar.gz 文件中加载 Docker 镜像,并将其推送到注册表。
为了实现我们的 CI/CD 流程,我们还需要为 GitLab Runner 配置两个项目级别的 Runner。在上面的 Docker Compose 文件中,我们定义了两个 Runner:
- runner1:与 Docker 守护进程连接,并且可以执行任何类型的构建任务。
- runner2:具有与 runner1 相同的配置,但是使用了一个不同的配置目录。
通过为 GitLab Runner 分配标签,我们可以将特定的 Runner 分配给特定的作业。例如,在我们的 .gitlab-ci.yml 文件中,我们使用 runner1 执行构建和部署作业:
代码语言:javascript复制yamlCopy codebuild:
image: docker:latest
services:
- docker:dind
stage: build
tags:
- runner1
script:
- docker build -t myapp .
- docker save myapp:latest | gzip > myapp.tar.gz
artifacts:
paths:
- myapp.tar.gz
deploy:
image: docker:latest
services:
- docker:dind
stage: deploy
tags:
- runner1
script:
- docker load < myapp.tar.gz
- docker tag myapp:latest registry.example.com/myapp:latest
- docker push registry.example.com/myapp:latest
最后,我们需要在 GitLab 中为我们的项目启用 CI/CD:
- 打开 GitLab 仪表板并导航到您的项目。
- 点击设置按钮。
- 选择 CI/CD 选项卡。
- 在“Runners”部分下,添加 runner1 和 runner2 两个 Runner。
- 保存更改。