Gitlab CI 本地开发部署
gitlab ci 本地开发部署
整体架构说明
组件一共 3 部分:
- GitLab‑CE:代码仓库 + CI 调度中心(docker 部署)
- GitLab‑Runner:执行流水线任务,采用docker执行器(docker executor),挂载宿主机/var/run/docker.sock,job 会新建容器运行;
- 项目代码:项目根目录编写 .gitlab‑ci.yml。
环境前提:
- 服务器:Linux (CentOS7 / Ubuntu22.04),内存 ≥4G,推荐 6G;
- 已装好 docker、docker‑compose;
- 关闭防火墙或者放行 80、443、2222 端口。
阶段 1:部署 GitLab‑CE(服务端)
1.1 编写 docker‑compose.yml
version: '3.8'
services:
gitlab:
image: gitlab/gitlab-ce:17.1.0-ce.0
container_name: gitlab
restart: always
hostname: gitlab.local
ports:
- "80:80"
- "443:443"
- "2222:22"
volumes:
- ./config:/etc/gitlab
- ./logs:/var/log/gitlab
- ./data:/var/opt/gitlab
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.local'
gitlab_rails['gitlab_shell_ssh_port'] = 2222;
# 设置最大并发CI任务,测试环境设2即可
gitlab_rails['sidekiq_concurrency'] = 2;
1.2 启动容器
cd /opt/gitlab
docker-compose up -d
启动等待时间很长,大约 5‑10 分钟,所有组件初始化完毕。查看状态:
docker logs -f gitlab
1.3 获取初始管理员密码
# 进入容器查看root初始密码
docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
复制密码,有效期 24 小时,登录后第一时间修改。
1.4 本地 hosts 解析(非常关键,否则 Runner 克隆代码失败)
- Linux 服务器端 /etc/hosts 添加:
127.0.0.1 gitlab.local
- 如果你自己电脑浏览器访问,本机 hosts 文件同样添加服务器 IP:
服务器IP gitlab.local
浏览器访问: http://gitlab.local ,使用root和上面密码登录,新建普通用户,然后新建项目。
阶段 2:部署 GitLab‑Runner
2.1 创建 runner 目录,编写 docker‑compose.yml
version: '3.8'
services:
gitlab-runner:
image: gitlab/gitlab-runner:alpine
container_name: gitlab-runner
restart: always
volumes:
- ./config:/etc/gitlab-runner
# 核心:挂载宿主机docker,让job可以创建容器
- /var/run/docker.sock:/var/run/docker.sock
privileged: true
environment:
- TZ=Asia/Shanghai
启动 runner 容器:
cd /opt/gitlab-runner
docker-compose up -d
2.2 获取注册 Runner 所需要的参数
- 打开 GitLab 网页 → 进入你的项目 → 设置 → CI/CD → 运行程序 (Runner);
- 取消勾选【启用共享运行程序】;
- 获取两个值:
- GitLab 实例 URL:http://gitlab.local/
- 注册令牌(registration‑token)。
2.3 执行 runner 注册命令(重点)
进入 runner 容器内部执行注册:
docker exec -it gitlab-runner gitlab-runner register
按照下面依次填写:
# 1. 输入gitlab实例地址
Enter the GitLab instance URL (for example, https://gitlab.com/):
http://gitlab.local/
# 2. 粘贴项目里的注册token
Enter the registration token: 粘贴你的token
# 3. 填写runner描述,随便写:local-test-runner
Enter a description for the runner: local-test-runner
# 4. 标签(后面.gitlab‑ci.yml通过标签匹配runner):docker,test
Enter tags for the runner (comma‑separated): docker,test
# 5. 可选:是否仅针对受保护分支,测试环境填 false
Enter whether the runner should pick up jobs which are not tagged [true/false]: false
# 6. 选择执行器 executor 这里必须选 docker
Enter the executor: docker
# 7. CI job默认基础镜像,根据你的项目填写,这里以golang举例,PHP就填php:8.3‑cli‑alpine
Enter the default Docker image (for example, ruby:2.7): golang:1.23-alpine
注册完成后,页面刷新,Runner 显示绿色,代表就绪。
查看 runner 配置文件(确认配置)
cat /opt/gitlab-runner/config/config.toml
config.toml 配置文件如下
concurrent = 1
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "gitlab-runner-test"
url = "http://gitlab.local/"
id = 2
token = "xfGsxCefUwH2Fq5sU-Fs"
token_obtained_at = 2026-07-16T02:13:16Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
AssumeRoleMaxConcurrency = 0
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "golang:1.26-alpine3.23"
privileged = true # 开启 Docker 特权模式,挂载宿主机的docker.sock,实现 Docker‑in‑Docker(DinD),容器内部可以再启动 docker 容器
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] # 将宿主机的 Docker 守护进程套接字挂载进容器,实现宿主机 Docker 复用(DinD 经典用法)
volume_keep = false
shm_size = 0
network_mtu = 0
extra_hosts = ["gitlab.local:host-gateway"] # 给容器的 /etc/hosts 添加域名解析:host‑gateway是 Docker 内置特殊值,指向宿主机 IP,在 CI 容器里访问域名 gitlab.local 会解析到宿主机 IP,适用于内网 GitLab 场景,容器里可以访问宿主机上的 GitLab 服务
pull_policy = ["if-not-present"] # 镜像本地存在就不拉取,加快构建速度,测试环境非常实用
阶段 3:编写 CI 配置文件 .gitlab‑ci.yml(项目代码里)
在项目根目录新建 .gitlab‑ci.yml,示例以 Go 项目举例
# 指定runner标签,匹配刚刚注册的标签
default:
tags:
- docker
- test
# 流水线分阶段:构建、单元测试、部署
stages:
- build
- test
- deploy
# 构建阶段
build_app:
stage: build
image: golang:1.23-alpine
script:
- go version
- go mod tidy
- go build -o myapp main.go
artifacts:
paths:
- myapp # 将编译产物保存,后面阶段可以下载
# 单元测试阶段
unit_test:
stage: test
image: golang:1.23-alpine
script:
- go test ./... -v
# 部署阶段(仅main分支执行)
deploy_dev:
stage: deploy
image: alpine:latest
only:
- main
script:
- echo "开始部署到测试服务器"
- ls -l myapp
阶段 4:查看流水线运行结果
- GitLab 页面 → CI/CD → 流水线 (Pipelines);
- 提交代码之后自动触发流水线;
- 可以点进 job 查看日志,看每一条命令执行情况;
- 绿色对勾:执行成功;
- 红色:失败,查看日志排错。
常见踩坑总结(本地环境高频问题)
- GitLab 内存不足:sidekiq 进程挂掉,任务一直 pending,必须内存≥4G;
- gitlab.local 解析失败:服务器和本地电脑都要配置 hosts,不能只用 127.0.0.1;
- Runner 无法拉取镜像:在config.toml里配置[[runners.docker.tls_verify]]关闭私有仓库 https 校验;
- 执行器选错:runner 注册 executor 一定选 docker,不要选 shell;
- 标签不匹配:.gitlab‑ci.yml里 tags 必须和 runner 注册时填写的 tags 一致,否则 Job 排队不执行。
PHP语言的 .gitlab-ci.yml (Laravel 版,可直接使用)示例
# 匹配runner标签
default:
tags:
- docker
- test
# 缓存composer依赖,不同分支共用缓存
cache:
paths:
- vendor/
- composer.lock
key:
files:
- composer.lock
policy: pull-push
# 流水线阶段定义
stages:
- install
- lint
- test
- deploy-dev
# 1.安装依赖
composer_install:
stage: install
image: php:8.3-cli-alpine
before_script:
# 安装系统依赖、php扩展
- apk update && apk add --no-cache git curl openssh-client
- docker-php-ext-install pdo_mysql
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
script:
- composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
- composer install --optimize-autoloader --no-scripts
artifacts:
paths:
- vendor/
- composer.lock
# 2.代码语法检查 php‑cs‑fixer
php_lint:
stage: lint
image: php:8.3-cli-alpine
before_script:
- apk add git
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
script:
- composer global require friendsofphp/php-cs-fixer
- ~/.composer/vendor/bin/php-cs-fixer fix --dry-run --diff .
dependencies:
- composer_install
# 3.单元测试 PHPUnit
phpunit_test:
stage: test
image: php:8.3-cli-alpine
before_script:
- apk add git
- docker-php-ext-install pdo_mysql
script:
- php artisan test
dependencies:
- composer_install
# 4.部署到测试服务器 develop分支自动部署
deploy_dev:
stage: deploy-dev
image: alpine:latest
only:
- develop
before_script:
- apk add --no-cache openssh-client rsync
# GitLab CI后台配置环境变量 DEPLOY_SERVER、DEPLOY_USER、DEPLOY_PASS、DEPLOY_DIR
script:
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- echo "$DEPLOY_PASS" | ssh-add -
- ssh-keyscan $DEPLOY_SERVER >> ~/.ssh/known_hosts
# 同步代码至服务器,排除 .git、.gitlab‑ci.yml
- rsync -av --delete --exclude=".git" --exclude=".gitlab-ci.yml" ./ $DEPLOY_USER@$DEPLOY_SERVER:$DEPLOY_DIR
# 远程执行命令,清理缓存
- ssh $DEPLOY_USER@$DEPLOY_SERVER "cd $DEPLOY_DIR && php artisan optimize && php artisan migrate --force"
dependencies:
- composer_install
避坑要点
-
本地测试环境
gitlab‑runner的config.toml 里:
pull_policy = ["if-not-present"],镜像本地存在就不会重复下载,加快构建; -
若不想每次自动部署 main 分支,给 deploy 阶段加上:
when: manual,只有手动点击流水线任务才执行部署;
php 扩展按需增加,比如redis:docker-php-ext-install redis。

浙公网安备 33010602011771号