feat: 添加 Harbor 和 GitLab 模块,完善系统配置文档
- 新增 Harbor 容器镜像仓库维护模块 - 新增 GitLab 代码托管平台维护模块 - 创建 SYSTEM-CONFIG.md 系统配置概览文档 - 完善 README.md 项目说明文档 - 更新部署脚本支持新模块 - 集成 Ollama AI 模型服务配置信息 主要功能: - Harbor: Docker 镜像仓库管理 (端口 8080/8443) - GitLab: 企业级代码托管 (端口 8890/8929) - 系统配置文档:便于 Claude 和 CI/CD 理解架构 - 统一备份策略和健康监控 - 模块化部署和管理 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1.2.0",
|
||||
"version": "2.0.0",
|
||||
"copyright": "© 2025 灵境万象智能科技有限公司",
|
||||
"timestamp": "2025-10-19T20:24:02.314679",
|
||||
"timestamp": "2025-10-20T21:16:50.588333",
|
||||
"claude_context": "# Claude AI Development Context v1.2\n\n## Project Information\n**Name**: macos\n**Root**: /Users/brunogao/work/codes/tools/macos\n**Copyright**: © 2025 灵境万象智能科技有限公司\n\n## Current Development Phase\n**Phase**: AI-Powered Development\n**Focus**: High-quality enterprise-grade development\n\n## Quality Standards\n**Code Quality**:\n- Type coverage: ≥90%\n- Test coverage: ≥80%\n- Code quality: ≥B级\n\n**Performance**:\n- API response P95: ≤3s\n- Concurrent users: ≥1000\n- CPU usage: ≤70%\n\n**Security**:\n- Zero high-severity vulnerabilities\n- OWASP Top 10 compliance\n- Authentication and authorization complete\n\n## Development Guidelines\n1. **Enterprise-Grade Code**: Industry best practices with comprehensive documentation\n2. **Quality-First**: All quality gates must be passed\n3. **Security-First**: Security by design and default\n4. **Performance-Optimized**: Efficient, scalable code\n5. **Well-Tested**: High test coverage and automated quality checks\n\n## My Role & Approach\n**Role**: Senior Full-Stack Developer specializing in AI-powered systems\n**Approach**:\n- Structured responses with clear progress tracking\n- Ask clarifying questions when requirements are ambiguous\n- Suggest improvements and alternative approaches\n- Focus on practical, maintainable, enterprise-grade solutions\n\n## Quality Assurance\nAll deliverables validated against:\n- Functional requirements ✓\n- Performance benchmarks ✓\n- Security standards ✓\n- Code quality metrics ✓\n- Documentation completeness ✓\n\nLet's build high-quality, enterprise-grade software together!"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
# Claude AI Development Context v1.2
|
||||
|
||||
## Project Information
|
||||
**Name**: macos
|
||||
**Root**: /Users/brunogao/work/codes/tools/macos
|
||||
**Copyright**: © 2025 灵境万象智能科技有限公司
|
||||
|
||||
## Current Development Phase
|
||||
**Phase**: AI-Powered Development
|
||||
**Focus**: High-quality enterprise-grade development
|
||||
|
||||
## Quality Standards
|
||||
**Code Quality**:
|
||||
- Type coverage: ≥90%
|
||||
- Test coverage: ≥80%
|
||||
- Code quality: ≥B级
|
||||
|
||||
**Performance**:
|
||||
- API response P95: ≤3s
|
||||
- Concurrent users: ≥1000
|
||||
- CPU usage: ≤70%
|
||||
|
||||
**Security**:
|
||||
- Zero high-severity vulnerabilities
|
||||
- OWASP Top 10 compliance
|
||||
- Authentication and authorization complete
|
||||
|
||||
## Development Guidelines
|
||||
1. **Enterprise-Grade Code**: Industry best practices with comprehensive documentation
|
||||
2. **Quality-First**: All quality gates must be passed
|
||||
3. **Security-First**: Security by design and default
|
||||
4. **Performance-Optimized**: Efficient, scalable code
|
||||
5. **Well-Tested**: High test coverage and automated quality checks
|
||||
|
||||
## My Role & Approach
|
||||
**Role**: Senior Full-Stack Developer specializing in AI-powered systems
|
||||
**Approach**:
|
||||
- Structured responses with clear progress tracking
|
||||
- Ask clarifying questions when requirements are ambiguous
|
||||
- Suggest improvements and alternative approaches
|
||||
- Focus on practical, maintainable, enterprise-grade solutions
|
||||
|
||||
## Quality Assurance
|
||||
All deliverables validated against:
|
||||
- Functional requirements ✓
|
||||
- Performance benchmarks ✓
|
||||
- Security standards ✓
|
||||
- Code quality metrics ✓
|
||||
- Documentation completeness ✓
|
||||
|
||||
Let's build high-quality, enterprise-grade software together!
|
||||
@@ -10,22 +10,18 @@
|
||||
~/ops/
|
||||
├── logs/ # 统一日志目录
|
||||
├── backups/ # 统一备份目录
|
||||
│ ├── brew/ # Homebrew 备份
|
||||
│ ├── gitea/ # Gitea 备份
|
||||
│ ├── harbor/ # Harbor 备份
|
||||
│ └── gitlab/ # GitLab 备份
|
||||
├── data/ # 运行时数据目录
|
||||
│ ├── gitea/ # Gitea 运行时数据
|
||||
│ ├── harbor/ # Harbor 运行时数据
|
||||
│ └── gitlab/ # GitLab 运行时数据
|
||||
├── brew/ # Homebrew 维护模块
|
||||
│ ├── brew_maintain.sh # 每日维护脚本
|
||||
│ ├── brew_backup.sh # 备份脚本
|
||||
│ ├── brew_restore.sh # 恢复脚本
|
||||
│ ├── com.ljwx.brew.maintenance.plist # 定时任务配置
|
||||
│ └── README.md # Brew 模块详细文档
|
||||
├── gitea/ # Gitea Git 服务器模块
|
||||
│ ├── docker-compose.yml # Docker 服务配置
|
||||
│ ├── gitea-data-protection.sh # 数据保护脚本
|
||||
│ ├── gitea-backup.sh # 快速备份脚本
|
||||
│ ├── gitea-restore.sh # 快速恢复脚本
|
||||
│ ├── .env.example # 环境变量模板
|
||||
│ └── README.md # Gitea 模块详细文档
|
||||
├── [其他模块]/ # 未来可添加的其他模块
|
||||
│ ├── [模块脚本]
|
||||
│ └── README.md
|
||||
├── gitea/ # Gitea 维护模块
|
||||
├── harbor/ # Harbor 维护模块
|
||||
├── gitlab/ # GitLab 维护模块
|
||||
└── README.md # 项目总文档
|
||||
```
|
||||
|
||||
@@ -85,6 +81,64 @@ open http://192.168.1.83:33000
|
||||
|
||||
详细文档请查看 [gitea/README.md](gitea/README.md)
|
||||
|
||||
### 🐙 Harbor 模块 (`harbor/`)
|
||||
|
||||
完整的 Harbor 容器镜像仓库管理解决方案,支持服务部署、自动备份、健康监控和数据迁移功能。
|
||||
|
||||
**功能特性**:
|
||||
- ✅ Docker Compose 快速部署
|
||||
- ✅ 自动备份和安全恢复
|
||||
- ✅ 实时健康监控
|
||||
- ✅ 数据无损迁移支持
|
||||
- ✅ 双重定时任务保障
|
||||
- ✅ macOS 原生集成
|
||||
|
||||
**快速开始**:
|
||||
```bash
|
||||
# 进入 Harbor 模块目录
|
||||
cd harbor/
|
||||
|
||||
# 复制环境配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 启动服务
|
||||
./harbor-data-protection.sh start
|
||||
|
||||
# 访问 Harbor
|
||||
open http://192.168.1.83:8080
|
||||
```
|
||||
|
||||
详细文档请查看 [harbor/README.md](harbor/README.md)
|
||||
|
||||
### 🦊 GitLab 模块 (`gitlab/`)
|
||||
|
||||
完整的 GitLab 代码托管平台管理解决方案,包括服务部署、自动备份、健康监控和数据迁移功能。
|
||||
|
||||
**功能特性**:
|
||||
- ✅ Docker Compose 快速部署
|
||||
- ✅ 自动备份和安全恢复
|
||||
- ✅ 实时健康监控
|
||||
- ✅ 数据无损迁移支持
|
||||
- ✅ GitLab Runner 集成
|
||||
- ✅ macOS 原生集成
|
||||
|
||||
**快速开始**:
|
||||
```bash
|
||||
# 进入 GitLab 模块目录
|
||||
cd gitlab/
|
||||
|
||||
# 复制环境配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 启动服务(首次启动需要较长时间)
|
||||
./gitlab-data-protection.sh start
|
||||
|
||||
# 等待服务启动完成后访问
|
||||
open http://192.168.1.83:8890
|
||||
```
|
||||
|
||||
详细文档请查看 [gitlab/README.md](gitlab/README.md)
|
||||
|
||||
## 🚀 快速部署
|
||||
|
||||
### 一键部署
|
||||
@@ -120,9 +174,23 @@ cd ~/ops/brew
|
||||
**Gitea 模块**:
|
||||
```bash
|
||||
cd ~/ops/gitea
|
||||
./gitea-data-protection.sh setup # 初始化
|
||||
./gitea-data-protection.sh setup # 初始化设置
|
||||
./gitea-data-protection.sh start # 启动服务
|
||||
open http://192.168.1.83:33000 # 访问 Gitea
|
||||
open http://192.168.1.83:33000 # 访问 Gitea
|
||||
```
|
||||
|
||||
**Harbor 模块**:
|
||||
```bash
|
||||
cd ~/ops/harbor
|
||||
./harbor-data-protection.sh start # 启动服务
|
||||
open http://192.168.1.83:8080 # 访问 Harbor
|
||||
```
|
||||
|
||||
**GitLab 模块**:
|
||||
```bash
|
||||
cd ~/ops/gitlab
|
||||
./gitlab-data-protection.sh start # 启动服务
|
||||
open http://192.168.1.83:8890 # 访问 GitLab
|
||||
```
|
||||
|
||||
## 开发指南
|
||||
@@ -139,7 +207,7 @@ open http://192.168.1.83:33000 # 访问 Gitea
|
||||
|
||||
- `logs/`: 所有模块的统一日志目录
|
||||
- `backups/`: 所有模块的统一备份目录
|
||||
- 每个模块包含自己的 README.md 文档
|
||||
- 每个模块包含自己的 README.md 文件
|
||||
- 脚本命名规范:`{模块名}_{功能}.sh`
|
||||
|
||||
### 提交规范
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
# 系统配置概览
|
||||
|
||||
## 概述
|
||||
|
||||
本文档提供了 macOS 工具集中各组件的简明配置信息,便于 Claude 快速了解系统架构和配置参数,为 CI/CD 自动化部署提供参考。
|
||||
|
||||
## 系统架构
|
||||
|
||||
```
|
||||
IP: 192.168.1.83
|
||||
平台: macOS
|
||||
容器运行时: Docker Desktop
|
||||
```
|
||||
|
||||
## 组件配置
|
||||
|
||||
### 🐙 Gitea - Git 服务器
|
||||
|
||||
**基本信息**:
|
||||
- **版本**: 1.21
|
||||
- **类型**: 轻量级 Git 服务器
|
||||
- **端口**: 33000 (HTTP), 32222 (SSH)
|
||||
- **数据库**: SQLite3
|
||||
- **访问地址**: http://192.168.1.83:33000
|
||||
|
||||
**核心配置**:
|
||||
```yaml
|
||||
services:
|
||||
gitea:
|
||||
image: docker.m.daocloud.io/gitea/gitea:1.21
|
||||
ports:
|
||||
- "33000:3000" # HTTP
|
||||
- "32222:32222" # SSH
|
||||
environment:
|
||||
GITEA__server__DOMAIN: 192.168.1.83
|
||||
GITEA__server__ROOT_URL: http://192.168.1.83:33000/
|
||||
GITEA__server__SSH_PORT: 32222
|
||||
GITEA__database__DB_TYPE: sqlite3
|
||||
GITEA__actions__ENABLED: true # 启用 Actions
|
||||
```
|
||||
|
||||
**备份配置**:
|
||||
- **备份间隔**: 6小时
|
||||
- **保留天数**: 30天
|
||||
- **备份目录**: ~/ops/backups/gitea/
|
||||
- **数据目录**: gitea-data (Docker volume)
|
||||
|
||||
**健康检查**:
|
||||
```bash
|
||||
curl -f http://localhost:3000/api/healthz
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🦊 GitLab - 代码托管平台
|
||||
|
||||
**基本信息**:
|
||||
- **版本**: 16.9.1-ce.0
|
||||
- **类型**: 企业级代码托管平台
|
||||
- **端口**: 8890 (HTTP), 8929 (SSH)
|
||||
- **访问地址**: http://192.168.1.83:8890
|
||||
- **初始密码**: admin123
|
||||
|
||||
**核心配置**:
|
||||
```yaml
|
||||
services:
|
||||
gitlab:
|
||||
image: gitlab/gitlab-ce:16.9.1-ce.0
|
||||
ports:
|
||||
- "8890:80" # HTTP Web UI
|
||||
- "8929:22" # SSH
|
||||
environment:
|
||||
GITLAB_OMNIBUS_CONFIG: |
|
||||
external_url 'http://192.168.1.83:8890'
|
||||
gitlab_rails['gitlab_shell_ssh_port'] = 8929
|
||||
shm_size: '1g' # 共享内存
|
||||
```
|
||||
|
||||
**GitLab Runner**:
|
||||
- **镜像**: gitlab/gitlab-runner:latest
|
||||
- **执行器**: Docker
|
||||
- **配置目录**: ./gitlab-runner-config
|
||||
|
||||
**备份配置**:
|
||||
- **备份间隔**: 6小时
|
||||
- **保留天数**: 30天
|
||||
- **备份目录**: ~/ops/backups/gitlab/
|
||||
- **数据目录**: ~/ops/data/gitlab/
|
||||
|
||||
**健康检查**:
|
||||
```bash
|
||||
curl -f http://localhost:80/-/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🏭 Harbor - 容器镜像仓库
|
||||
|
||||
**基本信息**:
|
||||
- **版本**: v2.11.1
|
||||
- **类型**: 企业级容器镜像仓库
|
||||
- **端口**: 8080 (HTTP), 8443 (HTTPS), 8081 (Notary)
|
||||
- **访问地址**: http://192.168.1.83:8080
|
||||
- **默认管理员**: admin / admin
|
||||
|
||||
**核心服务组件**:
|
||||
```yaml
|
||||
services:
|
||||
proxy: # Nginx 反向代理
|
||||
image: goharbor/nginx-photon:v2.11.1
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 8081:8081
|
||||
- 8443:8443
|
||||
|
||||
core: # 核心服务
|
||||
image: goharbor/harbor-core:v2.11.1
|
||||
|
||||
registry: # 镜像存储
|
||||
image: goharbor/registry-photon:v2.11.1
|
||||
|
||||
database: # PostgreSQL 数据库
|
||||
image: goharbor/harbor-db:v2.11.1
|
||||
|
||||
redis: # 缓存服务
|
||||
image: goharbor/redis-photon:v2.11.1
|
||||
|
||||
jobservice: # 任务服务
|
||||
image: goharbor/harbor-jobservice:v2.11.1
|
||||
|
||||
portal: # Web 门户
|
||||
image: goharbor/harbor-portal:v2.11.1
|
||||
|
||||
log: # 日志服务
|
||||
image: goharbor/harbor-log:v2.11.1
|
||||
```
|
||||
|
||||
**备份配置**:
|
||||
- **备份间隔**: 12小时
|
||||
- **保留天数**: 30天
|
||||
- **备份目录**: ~/ops/backups/harbor/
|
||||
- **数据目录**: /Users/brunogao/ops/data/harbor/
|
||||
|
||||
---
|
||||
|
||||
### 🤖 Ollama - AI 模型服务
|
||||
|
||||
**基本信息**:
|
||||
- **版本**: Ollama App (macOS)
|
||||
- **类型**: 本地 AI 模型推理服务
|
||||
- **端口**: 11434 (API)
|
||||
- **访问地址**: http://localhost:11434
|
||||
- **服务状态**: 运行中
|
||||
|
||||
**核心配置**:
|
||||
```bash
|
||||
# 服务进程
|
||||
/usr/local/bin/ollama serve
|
||||
|
||||
# 模型运行器
|
||||
/Applications/Ollama.app/Contents/Resources/ollama runner
|
||||
```
|
||||
|
||||
**已安装模型**:
|
||||
| 模型名称 | 参数规模 | 大小 | 类型 |
|
||||
|---------|---------|------|------|
|
||||
| deepseek-r1:70b | 70.6B | 42GB | 推理模型 |
|
||||
| llama3.3:latest | 70.6B | 42GB | 推理模型 |
|
||||
| qwen2.5-coder:32b | 32.8B | 19GB | 编程模型 |
|
||||
| qwen3:32b | 32.8B | 20GB | 推理模型 |
|
||||
| qwen3:latest | 8.2B | 5.2GB | 推理模型 |
|
||||
| ljwx-stock:latest | 6.9B | 4.0GB | 股票模型 |
|
||||
| deepseek-llm:latest | 7B | 4.0GB | 推理模型 |
|
||||
| llama2:latest | 7B | 3.8GB | 推理模型 |
|
||||
| ljwx-health:latest | 6.7B | 3.8GB | 健康模型 |
|
||||
|
||||
**嵌入模型**:
|
||||
| 模型名称 | 参数规模 | 大小 | 用途 |
|
||||
|---------|---------|------|------|
|
||||
| bge-m3:latest | 566.70M | 1.2GB | 文本嵌入 |
|
||||
| bge-large:latest | 334.09M | 670MB | 文本嵌入 |
|
||||
| snowflake-arctic-embed2:latest | 566.70M | 1.2GB | 文本嵌入 |
|
||||
|
||||
**API 端点**:
|
||||
```bash
|
||||
# 获取模型列表
|
||||
GET http://localhost:11434/api/tags
|
||||
|
||||
# 生成对话
|
||||
POST http://localhost:11434/api/generate
|
||||
{
|
||||
"model": "qwen3:latest",
|
||||
"prompt": "Hello, how are you?"
|
||||
}
|
||||
|
||||
# 嵌入生成
|
||||
POST http://localhost:11434/api/embeddings
|
||||
{
|
||||
"model": "bge-m3:latest",
|
||||
"prompt": "Your text here"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ 目录结构
|
||||
|
||||
```
|
||||
~/ops/
|
||||
├── logs/ # 统一日志目录
|
||||
│ ├── gitea-protection.log
|
||||
│ ├── gitlab-protection.log
|
||||
│ ├── harbor-protection.log
|
||||
│ └── brew_maintain.log
|
||||
├── backups/ # 统一备份目录
|
||||
│ ├── gitea/ # Gitea 备份
|
||||
│ ├── gitlab/ # GitLab 备份
|
||||
│ ├── harbor/ # Harbor 备份
|
||||
│ └── brew/ # Homebrew 备份
|
||||
├── data/ # 运行时数据目录
|
||||
│ ├── gitea/ # Gitea 运行时数据
|
||||
│ ├── gitlab/ # GitLab 运行时数据
|
||||
│ └── harbor/ # Harbor 运行时数据
|
||||
└── {各模块目录}/
|
||||
```
|
||||
|
||||
## 🚀 快速部署命令
|
||||
|
||||
### 一键部署
|
||||
```bash
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
### 各组件独立启动
|
||||
```bash
|
||||
# Gitea
|
||||
cd ~/ops/gitea
|
||||
./gitea-data-protection.sh start
|
||||
|
||||
# GitLab
|
||||
cd ~/ops/gitlab
|
||||
./gitlab-data-protection.sh start
|
||||
|
||||
# Harbor
|
||||
cd ~/ops/harbor
|
||||
./harbor-data-protection.sh start
|
||||
|
||||
# Ollama (独立运行)
|
||||
ollama serve
|
||||
```
|
||||
|
||||
## 🔧 常用管理命令
|
||||
|
||||
### 健康检查
|
||||
```bash
|
||||
# Gitea
|
||||
./gitea-data-protection.sh health
|
||||
|
||||
# GitLab
|
||||
./gitlab-data-protection.sh health
|
||||
|
||||
# Harbor
|
||||
./harbor-data-protection.sh health
|
||||
|
||||
# Ollama
|
||||
curl -s http://localhost:11434/api/tags | jq '.models | length'
|
||||
```
|
||||
|
||||
### 备份操作
|
||||
```bash
|
||||
# Gitea
|
||||
./gitea-backup.sh
|
||||
|
||||
# GitLab
|
||||
./gitlab-backup.sh
|
||||
|
||||
# Harbor
|
||||
./harbor-backup.sh
|
||||
```
|
||||
|
||||
### 服务状态检查
|
||||
```bash
|
||||
# Docker 容器状态
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||||
|
||||
# 端口占用检查
|
||||
lsof -i :33000,32222,8890,8929,8080,8443,11434
|
||||
|
||||
# 日志查看
|
||||
tail -f ~/ops/logs/*-protection.log
|
||||
```
|
||||
|
||||
## 🔐 安全配置
|
||||
|
||||
### 防火墙端口
|
||||
- **Gitea**: 33000, 32222
|
||||
- **GitLab**: 8890, 8929
|
||||
- **Harbor**: 8080, 8443, 8081
|
||||
- **Ollama**: 11434 (本地访问)
|
||||
|
||||
### 访问控制
|
||||
- 所有服务都配置在内网环境 (192.168.1.83)
|
||||
- 建议配置 VPN 或防火墙规则限制外部访问
|
||||
- 生产环境建议使用 HTTPS 和 SSL 证书
|
||||
|
||||
## 📊 监控指标
|
||||
|
||||
### 系统监控
|
||||
```bash
|
||||
# Docker 资源使用
|
||||
docker stats
|
||||
|
||||
# 磁盘使用
|
||||
df -h ~/ops/
|
||||
|
||||
# 内存使用
|
||||
free -h
|
||||
```
|
||||
|
||||
### 服务监控
|
||||
- **自动健康检查**: 每 30 秒检查一次
|
||||
- **定时备份**: 按配置间隔自动执行
|
||||
- **日志轮转**: 自动管理日志文件大小
|
||||
|
||||
## 🔄 CI/CD 集成
|
||||
|
||||
### 环境变量配置
|
||||
```bash
|
||||
export GITEA_URL="http://192.168.1.83:33000"
|
||||
export GITLAB_URL="http://192.168.1.83:8890"
|
||||
export HARBOR_URL="http://192.168.1.83:8080"
|
||||
export OLLAMA_URL="http://localhost:11434"
|
||||
```
|
||||
|
||||
### API 访问令牌
|
||||
- **Gitea**: 通过 Web 界面生成 Personal Access Token
|
||||
- **GitLab**: 通过 User Settings > Access Tokens 生成
|
||||
- **Harbor**: 通过管理员账户生成 API Token
|
||||
- **Ollama**: 无需认证,本地访问
|
||||
|
||||
### Docker Registry 配置
|
||||
```bash
|
||||
# 登录 Harbor
|
||||
docker login 192.168.1.83:8080 -u admin -p admin
|
||||
|
||||
# 推送镜像
|
||||
docker tag myapp:latest 192.168.1.83:8080/library/myapp:latest
|
||||
docker push 192.168.1.83:8080/library/myapp:latest
|
||||
```
|
||||
|
||||
## 📝 故障排除
|
||||
|
||||
### 常见问题
|
||||
1. **Docker 服务未启动**: 启动 Docker Desktop
|
||||
2. **端口冲突**: 检查端口占用情况
|
||||
3. **权限问题**: 设置脚本执行权限
|
||||
4. **服务启动慢**: GitLab 首次启动需要 5-15 分钟
|
||||
|
||||
### 恢复流程
|
||||
1. 停止相关服务
|
||||
2. 创建安全备份
|
||||
3. 从备份恢复数据
|
||||
4. 重启服务验证
|
||||
5. 检查数据完整性
|
||||
|
||||
---
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
**文档更新**: 2025-01-20
|
||||
**版本**: v1.0
|
||||
**维护者**: 灵境万象智能科技有限公司
|
||||
|
||||
如需技术支持,请查看:
|
||||
1. 各模块的 README.md 文档
|
||||
2. 日志文件排查问题
|
||||
3. GitHub Issues 或 Pull Request
|
||||
@@ -57,6 +57,8 @@ show_usage() {
|
||||
echo ""
|
||||
echo -e "${BLUE}部署后访问:${NC}"
|
||||
echo " - Gitea: http://192.168.1.83:33000"
|
||||
echo " - Harbor: http://192.168.1.83:8080"
|
||||
echo " - GitLab: http://192.168.1.83:8890"
|
||||
echo " - 日志: ~/ops/logs/"
|
||||
echo " - 备份: ~/ops/backups/"
|
||||
echo ""
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# GitLab 环境变量配置
|
||||
# 复制此文件为 .env 并根据需要修改配置
|
||||
|
||||
# GitLab 基本配置
|
||||
GITLAB_DOMAIN=192.168.1.83
|
||||
GITLAB_HTTP_PORT=8890
|
||||
GITLAB_SSH_PORT=8929
|
||||
|
||||
# 数据目录配置
|
||||
GITLAB_DATA_DIR=~/ops/data/gitlab
|
||||
GITLAB_CONFIG_DIR=~/ops/gitlab/config
|
||||
|
||||
# 备份配置
|
||||
GITLAB_BACKUP_DIR=~/ops/backups/gitlab
|
||||
GITLAB_BACKUP_RETENTION_DAYS=30
|
||||
GITLAB_BACKUP_INTERVAL_HOURS=6
|
||||
|
||||
# 日志配置
|
||||
GITLAB_LOG_DIR=~/ops/logs
|
||||
|
||||
# GitLab 管理员配置 (首次启动时设置)
|
||||
GITLAB_ROOT_PASSWORD=admin123
|
||||
|
||||
# 邮件配置 (可选)
|
||||
# GITLAB_SMTP_ENABLE=true
|
||||
# GITLAB_SMTP_ADDRESS=smtp.gmail.com
|
||||
# GITLAB_SMTP_PORT=587
|
||||
# GITLAB_SMTP_USER_NAME=your-email@gmail.com
|
||||
# GITLAB_SMTP_PASSWORD=your-password
|
||||
# GITLAB_SMTP_DOMAIN=smtp.gmail.com
|
||||
# GITLAB_EMAIL_FROM=your-email@gmail.com
|
||||
|
||||
# GitLab Runner 配置 (可选)
|
||||
# GITLAB_RUNNER_ENABLE=true
|
||||
# GITLAB_RUNNER_NAME=gitlab-runner
|
||||
# GITLAB_RUNNER_TAG=docker
|
||||
|
||||
# 资源限制配置
|
||||
GITLAB_MEMORY_LIMIT=4g
|
||||
GITLAB_CPU_LIMIT=2
|
||||
|
||||
# SSL 配置 (如果需要 HTTPS)
|
||||
# GITLAB_SSL_CERT=/path/to/ssl/cert.pem
|
||||
# GITLAB_SSL_KEY=/path/to/ssl/key.pem
|
||||
|
||||
# 外部数据库配置 (可选)
|
||||
# GITLAB_EXTERNAL_DB_ENABLE=false
|
||||
# GITLAB_DB_HOST=postgres
|
||||
# GITLAB_DB_PORT=5432
|
||||
# GITLAB_DB_NAME=gitlabhq_production
|
||||
# GITLAB_DB_USER=gitlab
|
||||
# GITLAB_DB_PASSWORD=password
|
||||
|
||||
# Redis 配置 (可选)
|
||||
# GITLAB_EXTERNAL_REDIS_ENABLE=false
|
||||
# GITLAB_REDIS_HOST=redis
|
||||
# GITLAB_REDIS_PORT=6379
|
||||
@@ -0,0 +1,198 @@
|
||||
# GitLab CI/CD 配置完成总结
|
||||
|
||||
## 🎉 配置完成状态
|
||||
|
||||
✅ **所有核心组件已配置完成**
|
||||
|
||||
### 已完成的工作
|
||||
|
||||
1. **GitLab 实例配置**
|
||||
- GitLab CE 16.9.1 实例已启动并运行
|
||||
- 网络配置: http://192.168.1.83:8890
|
||||
- SSH 端口: 8929
|
||||
- 数据持久化已配置
|
||||
|
||||
2. **GitLab Runner 服务**
|
||||
- Docker 和 Shell Runner 容器已启动
|
||||
- 配置文件已准备 (`gitlab-runner-config/config.toml`)
|
||||
- 注册脚本已创建 (`register-runner-simple.sh`)
|
||||
|
||||
3. **CI/CD 配置模板**
|
||||
- **完整配置**: `.gitlab-ci.yml.stock` - 适用于生产环境
|
||||
- **简化配置**: `.gitlab-ci.yml.simple` - 适用于快速开始
|
||||
- 包含测试、构建、部署流水线
|
||||
|
||||
4. **环境变量管理**
|
||||
- 自动化配置脚本 (`setup-ci-env.sh`)
|
||||
- 支持开发和生产环境配置
|
||||
- 安全变量配置指南
|
||||
|
||||
5. **测试项目**
|
||||
- 完整的 Node.js 股票 API 项目
|
||||
- 单元测试和集成测试
|
||||
- Docker 容器化支持
|
||||
- 代码覆盖率报告
|
||||
|
||||
## 📁 文件结构
|
||||
|
||||
```
|
||||
gitlab/
|
||||
├── docker-compose.yml # GitLab 和 Runner 服务配置
|
||||
├── .env.example # 环境变量模板
|
||||
├── config/ # GitLab 配置目录
|
||||
├── gitlab-runner-config/ # Runner 配置目录
|
||||
│ └── config.toml # Runner 配置文件
|
||||
├── ci-templates/ # CI/CD 模板目录
|
||||
│ ├── .gitlab-ci.yml.stock # 完整流水线配置
|
||||
│ ├── .gitlab-ci.yml.simple # 简化流水线配置
|
||||
│ └── README.md # 模板使用说明
|
||||
├── scripts/ # 管理脚本目录
|
||||
│ ├── register-runner-simple.sh # Runner 注册脚本
|
||||
│ ├── setup-ci-env.sh # 环境变量配置脚本
|
||||
│ └── gitlab-data-protection.sh # 数据保护脚本
|
||||
├── manual-runner-setup.md # 手动设置指南
|
||||
└── CICD-SUMMARY.md # 本文档
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 访问 GitLab
|
||||
```
|
||||
URL: http://192.168.1.83:8890
|
||||
用户名: root
|
||||
密码: admin123 (首次访问时设置)
|
||||
```
|
||||
|
||||
### 2. 注册 GitLab Runner
|
||||
```bash
|
||||
cd /Users/brunogao/work/codes/tools/macos/gitlab
|
||||
./register-runner-simple.sh
|
||||
```
|
||||
|
||||
### 3. 创建和配置项目
|
||||
```bash
|
||||
# 使用测试项目
|
||||
cd /tmp/test-stock-project
|
||||
./setup-project.sh
|
||||
|
||||
# 或为现有项目添加 CI/CD
|
||||
cp /Users/brunogao/work/codes/tools/macos/gitlab/ci-templates/.gitlab-ci.yml.simple /path/to/your/project/.gitlab-ci.yml
|
||||
```
|
||||
|
||||
### 4. 配置环境变量
|
||||
```bash
|
||||
./setup-ci-env.sh <项目名称> [dev|prod]
|
||||
```
|
||||
|
||||
## 🔧 CI/CD 流水线功能
|
||||
|
||||
### 完整流水线 (.gitlab-ci.yml.stock)
|
||||
- **lint**: 代码质量检查 (ESLint, Flake8)
|
||||
- **test**: 单元测试和集成测试
|
||||
- **build**: Docker 镜像构建和推送
|
||||
- **security**: 安全漏洞扫描
|
||||
- **deploy**: 自动化部署到开发/生产环境
|
||||
|
||||
### 简化流水线 (.gitlab-ci.yml.simple)
|
||||
- **test**: 基础测试
|
||||
- **build**: Docker 构建
|
||||
- **deploy**: 手动部署
|
||||
|
||||
## 📊 特性
|
||||
|
||||
### 开发工具
|
||||
- ✅ 自动化测试
|
||||
- ✅ 代码覆盖率报告
|
||||
- ✅ 代码质量检查
|
||||
- ✅ 安全漏洞扫描
|
||||
- ✅ 容器化构建
|
||||
|
||||
### 部署特性
|
||||
- ✅ 多环境支持 (dev/prod)
|
||||
- ✅ 手动部署审批
|
||||
- ✅ 回滚支持
|
||||
- ✅ 健康检查
|
||||
|
||||
### 监控和日志
|
||||
- ✅ 流水线状态跟踪
|
||||
- ✅ 构建日志
|
||||
- ✅ 测试报告
|
||||
- ✅ 部署历史
|
||||
|
||||
## 🛠️ 自定义配置
|
||||
|
||||
### 修改 Runner 标签
|
||||
编辑 `gitlab-runner-config/config.toml`:
|
||||
```toml
|
||||
[[runners]]
|
||||
name = "your-runner"
|
||||
tags = ["custom-tag1", "custom-tag2"]
|
||||
```
|
||||
|
||||
### 添加自定义流水线阶段
|
||||
```yaml
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
- notify # 新增通知阶段
|
||||
```
|
||||
|
||||
### 环境变量配置
|
||||
在 GitLab 项目设置中:
|
||||
- Settings → CI/CD → Variables
|
||||
- 添加敏感信息 (数据库密码、API keys 等)
|
||||
|
||||
## 🔍 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **GitLab 启动慢**
|
||||
- 首次启动需要 5-10 分钟
|
||||
- 使用 `docker logs gitlab-ce` 查看进度
|
||||
|
||||
2. **Runner 无法注册**
|
||||
- 确认 GitLab 完全启动
|
||||
- 检查网络连接
|
||||
- 验证注册 token
|
||||
|
||||
3. **流水线失败**
|
||||
- 检查 Runner 标签
|
||||
- 验证 `.gitlab-ci.yml` 语法
|
||||
- 查看构建日志
|
||||
|
||||
### 调试命令
|
||||
```bash
|
||||
# 检查服务状态
|
||||
docker ps | grep gitlab
|
||||
|
||||
# 查看日志
|
||||
docker logs gitlab-ce
|
||||
docker logs gitlab-runner
|
||||
|
||||
# 列出 Runner
|
||||
docker exec gitlab-runner gitlab-runner list
|
||||
|
||||
# 测试流水线
|
||||
docker exec gitlab-runner gitlab-runner exec docker test
|
||||
```
|
||||
|
||||
## 📚 参考资源
|
||||
|
||||
- [GitLab CI/CD 官方文档](https://docs.gitlab.com/ee/ci/)
|
||||
- [GitLab Runner 配置](https://docs.gitlab.com/runner/)
|
||||
- [Docker 构建](https://docs.docker.com/build/)
|
||||
- [项目模板](./ci-templates/README.md)
|
||||
|
||||
## 🎯 下一步
|
||||
|
||||
1. **创建实际项目**: 将 CI/CD 配置应用到真实的 stock 项目
|
||||
2. **优化流水线**: 根据项目需求定制 CI/CD 流程
|
||||
3. **集成外部服务**: 添加通知、监控、代码质量工具
|
||||
4. **设置环境管理**: 配置开发、测试、生产环境
|
||||
5. **建立最佳实践**: 制定团队 CI/CD 规范和流程
|
||||
|
||||
---
|
||||
|
||||
🎉 **恭喜!你现在拥有一个完整的 GitLab CI/CD 环境,可以开始进行自动化开发和部署了!**
|
||||
@@ -0,0 +1,434 @@
|
||||
# GitLab 维护模块
|
||||
|
||||
## 概述
|
||||
|
||||
这是 macOS 工具集中的 GitLab 维护模块,提供完整的 GitLab 代码托管平台管理解决方案,包括服务部署、自动备份、健康监控和一键恢复功能。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ **一键部署**: Docker Compose 快速部署 GitLab 服务
|
||||
- ✅ **自动备份**: 双重定时任务保障 (cron + launchd)
|
||||
- ✅ **安全恢复**: 支持一键恢复和安全回滚
|
||||
- ✅ **健康监控**: 实时监控服务状态和数据完整性
|
||||
- ✅ **数据迁移**: 支持从现有 GitLab 无损迁移
|
||||
- ✅ **macOS 集成**: 原生支持 macOS 系统特性
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
gitlab/
|
||||
├── docker-compose.yml # Docker 服务配置
|
||||
├── gitlab-data-protection.sh # 主管理脚本
|
||||
├── gitlab-backup.sh # 快速备份脚本
|
||||
├── gitlab-restore.sh # 快速恢复脚本
|
||||
├── .env.example # 环境变量模板
|
||||
├── config/ # GitLab 配置目录
|
||||
└── README.md # 本文档
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 环境准备
|
||||
|
||||
确保系统已安装:
|
||||
- Docker Desktop for Mac
|
||||
- Git (用于版本控制)
|
||||
|
||||
### 2. 初始化设置
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
cd /path/to/macos/gitlab
|
||||
|
||||
# 复制环境配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 根据需要修改配置(可选)
|
||||
nano .env
|
||||
|
||||
# 初始化设置(自动配置定时任务等)
|
||||
./gitlab-data-protection.sh setup
|
||||
```
|
||||
|
||||
### 3. 启动服务
|
||||
|
||||
```bash
|
||||
# 启动 GitLab 服务
|
||||
./gitlab-data-protection.sh start
|
||||
|
||||
# 等待服务启动(可能需要几分钟)
|
||||
./gitlab-data-protection.sh health
|
||||
```
|
||||
|
||||
### 4. 访问 GitLab
|
||||
|
||||
- **Web 界面**: http://192.168.1.83:8890
|
||||
- **SSH**: git@192.168.1.83:8929
|
||||
|
||||
**首次访问设置**:
|
||||
1. 打开 http://192.168.1.83:8890
|
||||
2. 设置 root 密码(建议使用强密码)
|
||||
3. 创建管理员账户
|
||||
4. 配置基本设置
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 服务管理
|
||||
|
||||
```bash
|
||||
# 启动服务
|
||||
./gitlab-data-protection.sh start
|
||||
|
||||
# 停止服务
|
||||
./gitlab-data-protection.sh stop
|
||||
|
||||
# 重启服务
|
||||
./gitlab-data-protection.sh restart
|
||||
|
||||
# 健康检查
|
||||
./gitlab-data-protection.sh health
|
||||
|
||||
# 查看统计信息
|
||||
./gitlab-data-protection.sh stats
|
||||
```
|
||||
|
||||
### 备份操作
|
||||
|
||||
```bash
|
||||
# 手动备份(自动命名)
|
||||
./gitlab-backup.sh
|
||||
|
||||
# 手动备份(指定名称)
|
||||
./gitlab-backup.sh my-backup-20231019
|
||||
|
||||
# 查看备份文件
|
||||
ls -la ~/ops/backups/gitlab/
|
||||
```
|
||||
|
||||
### 恢复操作
|
||||
|
||||
```bash
|
||||
# 查看可用备份
|
||||
./gitlab-restore.sh
|
||||
|
||||
# 从指定备份恢复
|
||||
./gitlab-restore.sh gitlab-20231019-120000.tar.gz
|
||||
```
|
||||
|
||||
### 高级操作
|
||||
|
||||
```bash
|
||||
# 完整功能菜单
|
||||
./gitlab-data-protection.sh help
|
||||
|
||||
# 重新初始化设置
|
||||
./gitlab-data-protection.sh setup
|
||||
|
||||
# 查看统计信息
|
||||
./gitlab-data-protection.sh stats
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
### 环境变量 (.env)
|
||||
|
||||
| 变量名 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `GITLAB_DOMAIN` | 192.168.1.83 | GitLab 服务器域名 |
|
||||
| `GITLAB_HTTP_PORT` | 8890 | HTTP Web UI 端口 |
|
||||
| `GITLAB_SSH_PORT` | 8929 | SSH 端口 |
|
||||
| `GITLAB_DATA_DIR` | ~/ops/data/gitlab | GitLab 数据目录 |
|
||||
| `GITLAB_CONFIG_DIR` | ~/ops/gitlab/config | GitLab 配置目录 |
|
||||
| `GITLAB_BACKUP_DIR` | ~/ops/backups/gitlab | 备份存储目录 |
|
||||
| `GITLAB_BACKUP_RETENTION_DAYS` | 30 | 备份保留天数 |
|
||||
| `GITLAB_BACKUP_INTERVAL_HOURS` | 6 | 自动备份间隔(小时) |
|
||||
| `GITLAB_ROOT_PASSWORD` | admin123 | root 用户初始密码 |
|
||||
|
||||
### Docker Compose 配置
|
||||
|
||||
主要配置项:
|
||||
- GitLab CE 版本:16.9.1
|
||||
- 内存限制:1GB shm_size
|
||||
- 健康检查:内置 healthcheck
|
||||
- 环境变量:通过 `GITLAB_OMNIBUS_CONFIG` 配置
|
||||
|
||||
## 迁移说明
|
||||
|
||||
### 从现有 GitLab 迁移
|
||||
|
||||
如果已经有运行的 GitLab 实例,可以按照以下步骤无损迁移:
|
||||
|
||||
1. **备份现有数据**
|
||||
```bash
|
||||
# 停止现有服务
|
||||
cd ~/gitlab && docker-compose down
|
||||
|
||||
# 备份数据目录
|
||||
tar -czf gitlab-backup-$(date +%Y%m%d-%H%M%S).tar.gz data/ config/
|
||||
```
|
||||
|
||||
2. **使用新模块**
|
||||
```bash
|
||||
# 部署新模块
|
||||
./init-ops.sh
|
||||
|
||||
# 恢复数据
|
||||
./gitlab-restore.sh gitlab-backup-*.tar.gz
|
||||
```
|
||||
|
||||
3. **验证迁移结果**
|
||||
```bash
|
||||
# 检查服务状态
|
||||
./gitlab-data-protection.sh health
|
||||
|
||||
# 验证仓库数量
|
||||
./gitlab-data-protection.sh stats
|
||||
```
|
||||
|
||||
## 备份机制
|
||||
|
||||
### 自动备份
|
||||
|
||||
系统提供双重保障的自动备份:
|
||||
|
||||
1. **Cron 任务**: 传统 Unix 定时任务
|
||||
2. **Launchd 任务**: macOS 原生定时任务
|
||||
|
||||
默认每 6 小时自动备份一次,保留 30 天的备份文件。
|
||||
|
||||
### 备份内容
|
||||
|
||||
- GitLab 配置目录
|
||||
- GitLab 数据目录(repositories、builds、uploads 等)
|
||||
- PostgreSQL 数据库
|
||||
- Docker Compose 配置文件
|
||||
|
||||
### 备份位置
|
||||
|
||||
```
|
||||
~/ops/backups/gitlab/
|
||||
├── gitlab-20231019-120000.tar.gz # 备份文件
|
||||
├── gitlab-20231019-120000.tar.gz.meta # 备份元数据
|
||||
└── safety-backup-*.tar.gz # 恢复时的安全备份
|
||||
```
|
||||
|
||||
## 恢复机制
|
||||
|
||||
### 安全恢复流程
|
||||
|
||||
1. **停止服务**: 安全停止所有 GitLab 服务
|
||||
2. **安全备份**: 自动创建当前状态的安全备份
|
||||
3. **数据恢复**: 从指定备份恢复数据
|
||||
4. **服务启动**: 重启服务并验证状态
|
||||
5. **完整性检查**: 验证数据完整性
|
||||
|
||||
### 恢回滚
|
||||
|
||||
如果恢复出现问题,可以使用安全备份回滚:
|
||||
|
||||
```bash
|
||||
./gitlab-restore.sh safety-backup-20231019-130000.tar.gz
|
||||
```
|
||||
|
||||
## 监控和日志
|
||||
|
||||
### 健康检查内容
|
||||
|
||||
- Docker 环境状态
|
||||
- GitLab 服务运行状态
|
||||
- 数据卷完整性
|
||||
- 仓库数量统计
|
||||
- 备份状态检查
|
||||
- 定时任务状态
|
||||
|
||||
### 日志文件位置
|
||||
|
||||
```
|
||||
~/ops/logs/
|
||||
├── gitlab-protection.log # 主脚本日志
|
||||
├── gitlab-backup_stdout.log # 备份输出日志
|
||||
└── gitlab-backup_stderr.log # 备份错误日志
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# 查看主日志
|
||||
tail -f ~/ops/logs/gitlab-protection.log
|
||||
|
||||
# 查看定时任务日志
|
||||
tail -f ~/ops/logs/gitlab-backup_*.log
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **Docker 服务未启动**
|
||||
```bash
|
||||
# 启动 Docker Desktop
|
||||
open /Applications/Docker.app
|
||||
```
|
||||
|
||||
2. **端口冲突**
|
||||
```bash
|
||||
# 检查端口占用
|
||||
lsof -i :8890
|
||||
lsof -i :8929
|
||||
```
|
||||
|
||||
3. **权限问题**
|
||||
```bash
|
||||
# 设置脚本权限
|
||||
chmod +x gitlab-*.sh
|
||||
```
|
||||
|
||||
4. **服务启动缓慢**
|
||||
```bash
|
||||
# GitLab 首次启动需要较长时间(5-15分钟)
|
||||
# 检查服务日志
|
||||
docker logs gitlab-ce
|
||||
```
|
||||
|
||||
5. **定时任务未执行**
|
||||
```bash
|
||||
# 检查 launchd 任务
|
||||
launchctl list | grep gitlab
|
||||
|
||||
# 检查 cron 任务
|
||||
crontab -l | grep gitlab
|
||||
```
|
||||
|
||||
### 手动恢复定时任务
|
||||
|
||||
```bash
|
||||
# 重新加载 launchd 任务
|
||||
launchctl unload ~/Library/LaunchAgents/com.ljwx.gitlab.backup.plist 2>/dev/null || true
|
||||
launchctl load -w ~/Library/LaunchAgents/com.ljwx.gitlab.backup.plist
|
||||
|
||||
# 重新设置 cron 任务
|
||||
./gitlab-data-protection.sh setup
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 备份优化
|
||||
|
||||
- 调整备份频率:修改 `GITLAB_BACKUP_INTERVAL_HOURS`
|
||||
- 调整保留策略:修改 `GITLAB_BACKUP_RETENTION_DAYS`
|
||||
- 使用外部存储:修改 `GITLAB_BACKUP_DIR` 到外部磁盘
|
||||
|
||||
### 服务优化
|
||||
|
||||
- 调整 Docker 资源限制
|
||||
- 使用外部数据库(PostgreSQL)
|
||||
- 配置 CDN 或反向代理
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **定期备份**: 确保自动备份正常运行
|
||||
2. **异地备份**: 将重要备份同步到云存储
|
||||
3. **访问控制**: 配置防火墙规则限制访问
|
||||
4. **定期更新**: 定期更新 GitLab 版本
|
||||
5. **监控告警**: 配置服务状态监控
|
||||
6. **强密码**: 为 root 用户设置强密码
|
||||
7. **SSL 配置**: 生产环境建议使用 HTTPS
|
||||
|
||||
## 升级指南
|
||||
|
||||
### GitLab 版本升级
|
||||
|
||||
```bash
|
||||
# 1. 备份当前数据
|
||||
./gitlab-backup.sh pre-upgrade-$(date +%Y%m%d)
|
||||
|
||||
# 2. 停止服务
|
||||
./gitlab-data-protection.sh stop
|
||||
|
||||
# 3. 更新镜像版本
|
||||
# 编辑 docker-compose.yml,修改 image 标签
|
||||
|
||||
# 4. 启动服务
|
||||
./gitlab-data-protection.sh start
|
||||
|
||||
# 5. 验证升级
|
||||
./gitlab-data-protection.sh health
|
||||
```
|
||||
|
||||
## 扩展集成
|
||||
|
||||
### 与 CI/CD 集成
|
||||
|
||||
```bash
|
||||
# CI 脚本示例
|
||||
./gitlab-backup.sh ci-pre-build-$(BUILD_NUMBER)
|
||||
# 执行构建任务
|
||||
./gitlab-restore.sh ci-pre-build-$(BUILD_NUMBER).tar.gz
|
||||
```
|
||||
|
||||
### 与监控系统集成
|
||||
|
||||
```bash
|
||||
# 健康检查 API 调用
|
||||
./gitlab-data-protection.sh health
|
||||
echo $?
|
||||
```
|
||||
|
||||
### GitLab Runner 集成
|
||||
|
||||
```bash
|
||||
# 注册 GitLab Runner
|
||||
docker run -d --name gitlab-runner --restart always \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v ~/ops/gitlab/gitlab-runner-config:/etc/gitlab-runner \
|
||||
gitlab/gitlab-runner:latest
|
||||
|
||||
# 配置 Runner
|
||||
docker exec -it gitlab-runner gitlab-runner register \
|
||||
--url http://192.168.1.83:8890 \
|
||||
--registration-token <YOUR_TOKEN> \
|
||||
--executor docker \
|
||||
--description "Docker Runner" \
|
||||
--tag-list "docker,macos" \
|
||||
--docker-privileged
|
||||
```
|
||||
|
||||
## 常用命令
|
||||
|
||||
### 日常维护
|
||||
|
||||
```bash
|
||||
# 检查服务状态
|
||||
./gitlab-data-protection.sh status
|
||||
|
||||
# 查看资源使用
|
||||
docker stats gitlab-ce
|
||||
|
||||
# 查看服务日志
|
||||
docker logs -f gitlab-ce
|
||||
|
||||
# 清理 Docker 资源
|
||||
docker system prune -f
|
||||
```
|
||||
|
||||
### 用户管理
|
||||
|
||||
```bash
|
||||
# 进入 GitLab 容器
|
||||
docker exec -it gitlab-ce /bin/bash
|
||||
|
||||
# 重置 root 密码
|
||||
docker exec -it gitlab-ce gitlab-rake "gitlab:password:reset[root]"
|
||||
```
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License - 可自由使用和修改
|
||||
|
||||
## 支持
|
||||
|
||||
如有问题或建议,请通过以下方式联系:
|
||||
|
||||
1. 查看日志文件排查问题
|
||||
2. 检查 GitHub Issues
|
||||
3. 提交新的 Issue 或 Pull Request
|
||||
@@ -0,0 +1,63 @@
|
||||
# 简化的 Stock 项目 CI/CD 配置
|
||||
# 适用于快速开始的流水线
|
||||
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
IMAGE_TAG: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
|
||||
|
||||
# 单元测试
|
||||
test:
|
||||
stage: test
|
||||
image: node:18-alpine
|
||||
tags:
|
||||
- docker
|
||||
script:
|
||||
- echo "运行测试..."
|
||||
- if [ -f "package.json" ]; then npm install && npm test; fi
|
||||
- if [ -f "requirements.txt" ]; then pip install -r requirements.txt && python -m pytest; fi
|
||||
coverage: '/Total coverage: \d+\.\d+%/'
|
||||
only:
|
||||
- branches
|
||||
- merge_requests
|
||||
|
||||
# 构建应用
|
||||
build:
|
||||
stage: build
|
||||
image: docker:latest
|
||||
tags:
|
||||
- docker
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- echo "构建应用..."
|
||||
- if [ -f "Dockerfile" ]; then
|
||||
docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY;
|
||||
docker build -t $IMAGE_TAG .;
|
||||
docker push $IMAGE_TAG;
|
||||
else
|
||||
echo "未找到 Dockerfile,跳过构建";
|
||||
fi
|
||||
only:
|
||||
- branches
|
||||
- merge_requests
|
||||
|
||||
# 部署到开发环境
|
||||
deploy:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
tags:
|
||||
- shell
|
||||
script:
|
||||
- echo "部署应用..."
|
||||
- echo "部署到环境: $CI_ENVIRONMENT_NAME"
|
||||
- echo "镜像标签: $IMAGE_TAG"
|
||||
environment:
|
||||
name: development
|
||||
when: manual
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
@@ -0,0 +1,231 @@
|
||||
# Stock 项目 CI/CD 流水线配置
|
||||
# 适用于股票相关项目的自动化构建、测试和部署
|
||||
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
- build
|
||||
- security
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
# Node.js 版本 (如果项目使用 Node.js)
|
||||
NODE_VERSION: "18"
|
||||
# Python 版本 (如果项目使用 Python)
|
||||
PYTHON_VERSION: "3.11"
|
||||
# Docker 镜像名称
|
||||
IMAGE_NAME: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
|
||||
# 缓存目录
|
||||
CACHE_DIR: "$CI_PROJECT_DIR/.cache"
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
- .npm/
|
||||
- .pip-cache/
|
||||
- .venv/
|
||||
- vendor/bundle/
|
||||
key: "$CI_COMMIT_REF_SLUG"
|
||||
|
||||
# 代码质量检查
|
||||
code-quality:
|
||||
stage: lint
|
||||
image: node:$NODE_VERSION
|
||||
tags:
|
||||
- docker
|
||||
script:
|
||||
- |
|
||||
if [ -f "package.json" ]; then
|
||||
echo "检测到 Node.js 项目,运行 ESLint 检查..."
|
||||
npm ci --cache .npm --prefer-offline
|
||||
npm run lint || true
|
||||
fi
|
||||
- |
|
||||
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
||||
echo "检测到 Python 项目,运行 Flake8 检查..."
|
||||
pip install --cache-dir .pip-cache flake8 black
|
||||
flake8 . --max-line-length=88 --extend-ignore=E203,W503 || true
|
||||
black --check . || true
|
||||
fi
|
||||
allow_failure: true
|
||||
only:
|
||||
- branches
|
||||
- merge_requests
|
||||
|
||||
# 单元测试
|
||||
unit-tests:
|
||||
stage: test
|
||||
image: node:$NODE_VERSION
|
||||
tags:
|
||||
- docker
|
||||
services:
|
||||
- postgres:15-alpine
|
||||
- redis:7-alpine
|
||||
variables:
|
||||
POSTGRES_DB: "test_stock_db"
|
||||
POSTGRES_USER: "test_user"
|
||||
POSTGRES_PASSWORD: "test_password"
|
||||
DATABASE_URL: "postgresql://test_user:test_password@postgres:5432/test_stock_db"
|
||||
REDIS_URL: "redis://redis:6379"
|
||||
script:
|
||||
- |
|
||||
if [ -f "package.json" ]; then
|
||||
echo "运行 Node.js 单元测试..."
|
||||
npm ci --cache .npm --prefer-offline
|
||||
npm run test || echo "测试失败,但继续流水线"
|
||||
fi
|
||||
- |
|
||||
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
||||
echo "运行 Python 单元测试..."
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install --cache-dir .pip-cache -r requirements.txt
|
||||
python -m pytest tests/ --junitxml=report.xml --cov=. || echo "测试失败,但继续流水线"
|
||||
fi
|
||||
coverage: '/Total coverage: \d+\.\d+%/'
|
||||
artifacts:
|
||||
reports:
|
||||
junit: report.xml
|
||||
paths:
|
||||
- coverage/
|
||||
expire_in: 1 week
|
||||
only:
|
||||
- branches
|
||||
- merge_requests
|
||||
|
||||
# 构建应用
|
||||
build-app:
|
||||
stage: build
|
||||
image: docker:latest
|
||||
tags:
|
||||
- docker
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- |
|
||||
if [ -f "Dockerfile" ]; then
|
||||
echo "构建 Docker 镜像..."
|
||||
docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
docker build -t $IMAGE_NAME .
|
||||
docker push $IMAGE_NAME
|
||||
echo "镜像构建完成: $IMAGE_NAME"
|
||||
else
|
||||
echo "未找到 Dockerfile,跳过镜像构建"
|
||||
fi
|
||||
- |
|
||||
if [ -f "package.json" ]; then
|
||||
echo "构建 Node.js 应用..."
|
||||
npm ci --cache .npm --prefer-offline
|
||||
npm run build || echo "构建失败,但继续流水线"
|
||||
fi
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
- build/
|
||||
expire_in: 1 week
|
||||
only:
|
||||
- branches
|
||||
- merge_requests
|
||||
|
||||
# 安全扫描
|
||||
security-scan:
|
||||
stage: security
|
||||
image: node:$NODE_VERSION
|
||||
tags:
|
||||
- docker
|
||||
script:
|
||||
- |
|
||||
if [ -f "package.json" ]; then
|
||||
echo "扫描 Node.js 安全漏洞..."
|
||||
npm ci --cache .npm --prefer-offline
|
||||
npm audit --audit-level high || echo "发现安全漏洞,但继续流水线"
|
||||
fi
|
||||
- |
|
||||
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
||||
echo "扫描 Python 安全漏洞..."
|
||||
pip install --cache-dir .pip-cache safety bandit
|
||||
safety check || echo "发现安全漏洞,但继续流水线"
|
||||
bandit -r . -f json || echo "发现安全问题,但继续流水线"
|
||||
fi
|
||||
allow_failure: true
|
||||
only:
|
||||
- branches
|
||||
- merge_requests
|
||||
|
||||
# 部署到开发环境
|
||||
deploy-dev:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
tags:
|
||||
- shell
|
||||
environment:
|
||||
name: development
|
||||
url: http://dev.stock.local
|
||||
before_script:
|
||||
- apk add --no-cache openssh-client
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
- ssh-keyscan -H $DEPLOY_SERVER >> ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
script:
|
||||
- |
|
||||
echo "部署到开发环境..."
|
||||
# 这里可以添加实际的部署脚本
|
||||
# 例如:rsync 文件到服务器,重启服务等
|
||||
ssh $DEPLOY_USER@$DEPLOY_SERVER "
|
||||
cd /opt/stock-app &&
|
||||
docker pull $IMAGE_NAME &&
|
||||
docker-compose -f docker-compose.dev.yml up -d &&
|
||||
docker system prune -f
|
||||
" || echo "部署失败"
|
||||
when: manual
|
||||
only:
|
||||
- develop
|
||||
|
||||
# 部署到生产环境
|
||||
deploy-prod:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
tags:
|
||||
- shell
|
||||
environment:
|
||||
name: production
|
||||
url: https://stock.example.com
|
||||
before_script:
|
||||
- apk add --no-cache openssh-client
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
- ssh-keyscan -H $DEPLOY_SERVER >> ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
script:
|
||||
- |
|
||||
echo "部署到生产环境..."
|
||||
# 生产环境部署脚本
|
||||
ssh $DEPLOY_USER@$DEPLOY_SERVER "
|
||||
cd /opt/stock-app &&
|
||||
docker pull $IMAGE_NAME &&
|
||||
docker-compose -f docker-compose.prod.yml up -d &&
|
||||
docker system prune -f
|
||||
" || echo "部署失败"
|
||||
when: manual
|
||||
only:
|
||||
- main
|
||||
- master
|
||||
|
||||
# 清理任务
|
||||
cleanup:
|
||||
stage: .post
|
||||
image: docker:latest
|
||||
tags:
|
||||
- docker
|
||||
script:
|
||||
- |
|
||||
echo "清理旧的 Docker 镜像..."
|
||||
docker system prune -af --filter "until=72h"
|
||||
docker volume prune -f
|
||||
when: always
|
||||
allow_failure: true
|
||||
@@ -0,0 +1,145 @@
|
||||
# GitLab CI/CD 模板
|
||||
|
||||
本目录包含了适用于不同类型项目的 GitLab CI/CD 配置模板。
|
||||
|
||||
## 模板文件
|
||||
|
||||
### 1. `.gitlab-ci.yml.stock`
|
||||
适用于股票相关项目的完整 CI/CD 流水线配置。
|
||||
|
||||
**特性:**
|
||||
- 支持多语言项目 (Node.js, Python)
|
||||
- 完整的测试流水线 (单元测试、代码质量检查)
|
||||
- Docker 镜像构建和推送
|
||||
- 安全漏洞扫描
|
||||
- 开发和生产环境部署
|
||||
- 缓存优化
|
||||
- 测试覆盖率报告
|
||||
|
||||
**使用方法:**
|
||||
```bash
|
||||
# 复制到你的项目根目录
|
||||
cp .gitlab-ci.yml.stock /path/to/your/project/.gitlab-ci.yml
|
||||
```
|
||||
|
||||
### 2. `.gitlab-ci.yml.simple`
|
||||
简化的 CI/CD 配置,适用于快速开始。
|
||||
|
||||
**特性:**
|
||||
- 基础测试
|
||||
- 简单的 Docker 构建
|
||||
- 手动部署到开发环境
|
||||
- 适合小型项目或原型开发
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
在 GitLab 项目中需要配置以下环境变量:
|
||||
|
||||
### 基础配置
|
||||
- `CI_REGISTRY_PASSWORD`: GitLab Container Registry 密码
|
||||
- `CI_REGISTRY_USER`: GitLab Container Registry 用户名
|
||||
|
||||
### 部署配置 (可选)
|
||||
- `SSH_PRIVATE_KEY`: 部署服务器的 SSH 私钥
|
||||
- `DEPLOY_SERVER`: 部署服务器地址
|
||||
- `DEPLOY_USER`: 部署服务器用户名
|
||||
|
||||
### 数据库配置 (测试环境)
|
||||
- `DATABASE_URL`: 测试数据库连接字符串
|
||||
- `REDIS_URL`: Redis 连接字符串
|
||||
|
||||
## Runner 标签说明
|
||||
|
||||
确保你的 GitLab Runner 配置了以下标签:
|
||||
|
||||
- `docker`: 用于运行 Docker 容器中的任务
|
||||
- `shell`: 用于运行本地的 shell 任务
|
||||
- `build`: 用于构建相关任务
|
||||
- `deploy`: 用于部署相关任务
|
||||
|
||||
## 项目结构建议
|
||||
|
||||
为了让 CI/CD 流水线正常工作,建议项目结构如下:
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── .gitlab-ci.yml # CI/CD 配置文件
|
||||
├── package.json # Node.js 项目配置
|
||||
├── requirements.txt # Python 依赖文件
|
||||
├── Dockerfile # Docker 构建文件
|
||||
├── tests/ # 测试文件目录
|
||||
│ ├── unit/
|
||||
│ └── integration/
|
||||
├── src/ # 源代码目录
|
||||
└── docs/ # 文档目录
|
||||
```
|
||||
|
||||
## 自定义配置
|
||||
|
||||
### 修改构建镜像
|
||||
```yaml
|
||||
build-app:
|
||||
image: your-custom-build-image:latest # 替换为你的构建镜像
|
||||
```
|
||||
|
||||
### 修改测试命令
|
||||
```yaml
|
||||
unit-tests:
|
||||
script:
|
||||
- npm run test:unit # 替换为你的测试命令
|
||||
```
|
||||
|
||||
### 添加自定义阶段
|
||||
```yaml
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
- security
|
||||
- build
|
||||
- deploy
|
||||
- notify # 新增通知阶段
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **Runner 未找到**
|
||||
- 确保 GitLab Runner 正在运行
|
||||
- 检查 Runner 标签是否匹配
|
||||
|
||||
2. **Docker 构建失败**
|
||||
- 检查 Dockerfile 是否存在
|
||||
- 确认 Docker 服务正常运行
|
||||
|
||||
3. **测试失败**
|
||||
- 检查依赖是否正确安装
|
||||
- 确认测试命令是否正确
|
||||
|
||||
4. **权限问题**
|
||||
- 检查 SSH 密钥配置
|
||||
- 确认部署脚本权限
|
||||
|
||||
### 调试技巧
|
||||
|
||||
1. **启用调试模式**
|
||||
```yaml
|
||||
variables:
|
||||
CI_DEBUG_TRACE: "true"
|
||||
```
|
||||
|
||||
2. **查看详细日志**
|
||||
- 在 GitLab UI 中查看流水线日志
|
||||
- 使用 `docker logs` 查看 Runner 日志
|
||||
|
||||
3. **本地测试**
|
||||
```bash
|
||||
# 本地运行 GitLab Runner
|
||||
gitlab-runner exec docker test
|
||||
```
|
||||
|
||||
## 更多资源
|
||||
|
||||
- [GitLab CI/CD 官方文档](https://docs.gitlab.com/ee/ci/)
|
||||
- [GitLab Runner 配置](https://docs.gitlab.com/runner/)
|
||||
- [Docker 构建](https://docs.docker.com/build/)
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"gitlab_workhorse": {
|
||||
"secret_token": "HAUBwt61t5CCKlYHVH5wuEKib6EklpNXQm6W6hcjlPU="
|
||||
},
|
||||
"gitlab_shell": {
|
||||
"secret_token": "e401f785165fb52a065f6f25da3656b3e94ed558de15b005cf47a96a945b19b2c14f7f1d80823a1377392826bc49bb95386e7de2c95ec17d1a81687b3ff4f813"
|
||||
},
|
||||
"gitlab_rails": {
|
||||
"secret_key_base": "91b32c539817dd811f24e20327d85d1cfac6580cadbded91f4d7c6be0e209008f7a30e15c0eee61b8482965a74cf0631d4ba83d10de2bc1d51dcdf322eca2422",
|
||||
"db_key_base": "e91f15af9ab00ae3e4129fc9e85ab1c6edbf6b77b53e05a514f507d5f4e5541cdea116d5b0bd70c15765d5e9c4bb0fb237db41b20cf8140e4124dfb4ba8a6f99",
|
||||
"otp_key_base": "027a58e7a4baee645ad1410be391fd8199245af1948886baf5a5b5c550a145f5ff707de91a2a6f2e0ba7195d0420b97255e736d3a7f1a5a8b736008efa5a3d5f",
|
||||
"encrypted_settings_key_base": "eb01a117b8a3f172f79291141da200e6542d923cc51478cfdc361c1c9863e168a5642d667a5f7c4c615813fedc6bb4090e0a7513d8def2c873466f12c8b6d58e",
|
||||
"openid_connect_signing_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n",
|
||||
"ci_jwt_signing_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"
|
||||
},
|
||||
"gitlab_pages": {
|
||||
"gitlab_secret": "dfll5PcgK6CZCGXHc_PAM5Zqi4jmaqBPzLYgv8oN5pM",
|
||||
"gitlab_id": "5Folrb7jdps33BTzfEUdSxxpA1nBzL87OrFPEizIaUM",
|
||||
"auth_secret": null,
|
||||
"api_secret_key": "Hr2DEfrHdzDWBOlF8H3fB3ftBRWnog5qOo8YawT/4Oo=",
|
||||
"register_as_oauth_app": null
|
||||
},
|
||||
"gitlab_kas": {
|
||||
"api_secret_key": "YmZlMDM3MzBkYWNiN2VjOGUzM2FhZWUzNGU5ODQ3Y2E=",
|
||||
"private_api_secret_key": "MmRjNGVmNDdkMjBlOWJhNGU0ZjhjMzAzMzJlODM2NWQ="
|
||||
},
|
||||
"suggested_reviewers": {
|
||||
"api_secret_key": null
|
||||
},
|
||||
"registry": {
|
||||
"http_secret": "f24388927e3e5bec7185aea252aec196b4564ffa10b7e6e5d26563665546263e6632eb815ae5d82fca2493ece03f812be1c62af0ade7c0ce585975d20094ca29",
|
||||
"internal_certificate": "-----BEGIN CERTIFICATE-----\nMIIFBTCCAu2gAwIBAgIBADANBgkqhkiG9w0BAQsFADBGMQwwCgYDVQQGEwNVU0Ex\nDzANBgNVBAoMBkdpdExhYjESMBAGA1UECwwJQ29udGFpbmVyMREwDwYDVQQDDAhS\nZWdpc3RyeTAeFw0yNTEwMjAxMjQxMTRaFw0zNTEwMTgxMjQxMTRaMEYxDDAKBgNV\nBAYTA1VTQTEPMA0GA1UECgwGR2l0TGFiMRIwEAYDVQQLDAlDb250YWluZXIxETAP\nBgNVBAMMCFJlZ2lzdHJ5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nrvOnATstMDsRAs3WlnG2wGEzKNWxykn6RbJIZa3hVIl8nrJP31O3+Eg9MA12v21+\nYyHvRSyi7RPTJlMfiPgX00kk1zCxPCiipuZft3Dv6P+tEOtsypdZ+/JzMD4Vg32o\nRYBa6QVsfIunvmgY3aHRjWVeuy/JD41jhsd6g0aB4IvN3A6BKIHm7mg9ieWh0q6L\npBSgURz/qaDWyiUSuSa/d/WFBklHRrD4MJwXjwr/MwzUYg5rs59tgrGGewaksF55\nfQlpf6cytdfrlLloD+gFiujQOGwZV2j/qGYp5yiI7T3aIbsM5NhpiJkTMcewkzQV\nT6vHKSF91xeYgUzab403w0iCW2WLkZBs1itAu2UVVDwIlJyNIw/rqwYYxLjT0a6o\nd0vauU/gDj86xToT4LMApy6P5fkdRGd8j6Jl9PE39gSt3uQmKR8ZwvVAWkNXoxwW\nhw0MemM4R6lx6N+HRJqATcqxCwqEy3hUmD5hiDE3duEoe9M1n0VGQu9LBSqwoGiE\nTdwiaczitGP8EkM4kUocP9BCF2trqdeTnHXzTomEgNzgQlEIHsCRX3XoKhMHWiGw\nFUeXRzmpuSoDwKm3tZeqG8jkkerYIpbvI1YizWk1okBY4umjhiWd/b5kToXtf+Cj\nQDeXj19gtpk+sJcyfElotNrFffT2fv0PnYKNUyJv1Z0CAwEAATANBgkqhkiG9w0B\nAQsFAAOCAgEAbH1T5VkiaOU1hNoOD0wMZeY8ve4QjYXbuX4YaxRq4DlGYQrA/j/l\n49a/dBNDvVP16r9EQ4zzo9zVojih0WCPlCodu9VmEJ1953eelqd0f98Qy1K0zMhx\npKG5BuMDpraL9Ebl7fy3+Jw+N090h2XhyIdTzRMpqLCAlwVThaaKdMVZlED4Zr2R\nf+dWPodFYVe91lQJYGPdmwkCA1RjDTIqNSqIQbYPwQS/pXb1ctcjo/mGdraDq0ea\nvNVdiw7PYgcFupT5hiZLT9MTxAjy67FTghaDzYUbQseTDjyP1kVJrqfZjIcD8H7T\nIK4pwm7pevT/tgzPmpNYuEt9udpfgctKuzywS6aZZkdTOB+kKd0Ax8dJ5cB0BuBz\no1xs1P4rAUP6z5w7CqhiF91GGh+SGLGQpxK7MmGZ3XLXVP3CgLM9jeTarpwH0Fb4\nwKUtoYPE4l2cIJha/5RzfpRFeENd7qWw/ksXQ3uck1N9/oIpCXakcGbemAzlrdRW\nZWEcPw9CoCH466nEVhuy53BqJkb49rWijjlG6uFXyWpXGmrV+ZCHP+k8gV+GUpgP\ngM54qn1vKa6eS+zzSkOpkg6gF6iLWz5vk44qiA4zdvLuYWPcuQPZRg0gV4zSADIH\nUVhh50mWYhxkHTmha1v0GXaiDWFcYr75WGG9sT8ZoqWG8awEZ8OWIQo=\n-----END CERTIFICATE-----\n",
|
||||
"internal_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"
|
||||
},
|
||||
"letsencrypt": {
|
||||
"auto_enabled": null
|
||||
},
|
||||
"mattermost": {
|
||||
"email_invite_salt": "c6b4ac2164a14ab9329e439f3a3648e9",
|
||||
"file_public_link_salt": "ff737f0352dd3f999620da44ae5bee8d",
|
||||
"sql_at_rest_encrypt_key": "bd6b544b8dafd49d79e9d41db5941873",
|
||||
"register_as_oauth_app": null
|
||||
},
|
||||
"postgresql": {
|
||||
"internal_certificate": "-----BEGIN CERTIFICATE-----\nMIIFBzCCAu+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBHMQwwCgYDVQQGEwNVU0Ex\nDzANBgNVBAoMBkdpdExhYjERMA8GA1UECwwIRGF0YWJhc2UxEzARBgNVBAMMClBv\nc3RncmVTUUwwHhcNMjUxMDIwMTI0MTE2WhcNMzUxMDE4MTI0MTE2WjBHMQwwCgYD\nVQQGEwNVU0ExDzANBgNVBAoMBkdpdExhYjERMA8GA1UECwwIRGF0YWJhc2UxEzAR\nBgNVBAMMClBvc3RncmVTUUwwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\nAQDCVrNBQt9IMLV0X68kMidxjtXiXOrPzUq/pX1XsyX22Lzqka32Gi7hQTJASlzN\nxA/31MHxciLUyBdVpWbn184vGyhp8N7YEqT0wze4E/9beUzh5Rampc2DKe4lp+QQ\nYDpfjRlfAytB6wjVzXY+y2Jq5NkAq9HL1xP6hD+Q04J63EXpCZTq0zbVUNWlLDF5\nZGUNWeSGRTUnltfIJKM9k666URhVpmJgPPFpZPeQiDr5SpcMoAZ55WfJ81ZdGbSx\npfh0kYxw6hFd4GuZcCDahGK+bSrSKKW6wUsj9Igzaac6H7I4nE5fwMd0GexUXhkD\n6TYV3jpXPEMcng+j8lrSpD0FPtXAuSUBQmeSSg8Q8ncoAZ6hy1CY0RJQ6TapwCYz\nf4D3iEvk5kloooPH1iIaRMVoNXs681X4t6YJ4e/ZEF/11BqalarCSum7Stn+Nacu\nR+6507IEB985PKic7UzX1GrVdi52EsIh8A65yiRBkJ3c8+G9Lsa5Aa3EhMKpvv7a\nboTh8ghGlFe3PlJnwALRdsOf5lH/oJS/XdlmdfZgecQAstLr+/5XGwzN6Sj23oMN\n+g0B/u19Kq7+qTAxHB4EXiXqztMmhPJ10zmcs/vjTOckRvBenQPG2zLVM7uEfYmc\nRNKFhgpONXyP32UMyFZOvzW27+8H2e7QWQGl/ujYdhYKWQIDAQABMA0GCSqGSIb3\nDQEBCwUAA4ICAQC0hyI4NqmkVW0Ck/kB+oRifxTcncZ65IOBrXeALhD3sHJ2hz6l\n3nNef/56d2KduSOMwpJo0Lj2uirbpfjSstj/xRS7Pof8JEZORCbde8gZJ0nt+J8+\nDjdw7sY+pPviXWjcfdRsPt76NZpqnr2aAz+RFPtyJ+i07xtYD6mrqtis5zZI5slp\n/gZ4C4zO4Xm/kDPq27agrKgI4Ake5ixhC1CssrtR8ppsTQ9pSgstYMj+LYVoVBDN\ndHAoQNS8SgTfaU2YzduLl/i74rNv9GNXTdk77TlNuiPh5ABJgfWJ+w/czP0laSSZ\n0BP1++rO/9PxewPkq63Om9CkFz6Ut3Zsl3hVYp4YraTKdgSrXUm+Hy2LVImjeADq\nZCL0ibued/K1YcBtr0Qlufhs4ELFSmogPqX6paOUMQz1A8hZHAfynT6wAtWwt2RO\n563IFYU8B32agVvqSIdt23CLVTJwyArg/hiqXGqUV9MDBkzN60z8eCsf8lxf0G4D\nWvA0hDgd9nVM5YUWe275aaPLkR7pgHd9CCN5ZbxOIasTrJTADQMZMHIxCF19Pudt\nQBSCsDZ6Z+GdWHqJGp0jJYDGZc0jxV3SzuTOuQxbuUnwbUNwkQ7hegVVmtDSw/mA\ng+Kl+owOOOYBx6Lf7ixjDUdetyE9HdFYGx7EZodaDq5n4Z9Vl4oSuj+MKA==\n-----END CERTIFICATE-----\n",
|
||||
"internal_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"
|
||||
},
|
||||
"mailroom": {
|
||||
"incoming_email_auth_token": null,
|
||||
"service_desk_email_auth_token": null
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
# WARNING: This value is valid only in the following conditions
|
||||
# 1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
|
||||
# 2. Password hasn't been changed manually, either via UI or via command line.
|
||||
#
|
||||
# If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.
|
||||
|
||||
Password: C/2zFETiHSuTBBY+sLDVQobhnCaeYkeZ9VtmkMfpr5A=
|
||||
|
||||
# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.
|
||||
@@ -0,0 +1,9 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
|
||||
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQS4aqPUdybr5Zoj2M0Lc2GJ4p3SCTWL
|
||||
o3XfCJtqawcwPX/ibVCPFXYB5KhTUIJQCfMPOlXmQbEvbVcvg733cuKqAAAAsOKBeMHigX
|
||||
jBAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLhqo9R3JuvlmiPY
|
||||
zQtzYYnindIJNYujdd8Im2prBzA9f+JtUI8VdgHkqFNQglAJ8w86VeZBsS9tVy+Dvfdy4q
|
||||
oAAAAhAOJ5pzfNRRionHlkdcvrxVq7640YhL+S82GgOsoMkqeUAAAAEXJvb3RAZ2l0bGFi
|
||||
LmxvY2FsAQIDBAUG
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLhqo9R3JuvlmiPYzQtzYYnindIJNYujdd8Im2prBzA9f+JtUI8VdgHkqFNQglAJ8w86VeZBsS9tVy+Dvfdy4qo= root@gitlab.local
|
||||
@@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBSfvOimaEg20PECSgdb4Wc4+Guu999e/xq4l8RyDa7yQAAAJjxM95Y8TPe
|
||||
WAAAAAtzc2gtZWQyNTUxOQAAACBSfvOimaEg20PECSgdb4Wc4+Guu999e/xq4l8RyDa7yQ
|
||||
AAAECK4oG226vS1gpsClnQGjOHkkeJpiyOqF3HpXUGm8OE6VJ+86KZoSDbQ8QJKB1vhZzj
|
||||
4a673317/GriXxHINrvJAAAAEXJvb3RAZ2l0bGFiLmxvY2FsAQIDBA==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFJ+86KZoSDbQ8QJKB1vhZzj4a673317/GriXxHINrvJ root@gitlab.local
|
||||
@@ -0,0 +1,38 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
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
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcvOaDvabIaoy2P8NCm/2F6yWj4/kZHZkKclFkJnnLrFOC4G+FmhaIZW4SSK68gGzCwkKCXpiYT1o6OYLzOcGMfmxLtwBdjz0gue+Sca4Qu53NTa2M7rFkJR8+vjtdD/ZFWfFOVQdZW6GLkrP70VyRfVXkaXmlrHYGUO/3d7auQMmo6TqY7CU+zQd6HK0Th6OeMT3T7mvuXbe1ZWk2PHGU7lfj/1JbrxIYEeQFQfNXLKKBCJV2K6DB/Ab8TUNdgqVqjvwE94PD2PKudbADOR6Yvq+9ccoZcLHH1Z8rpazf7GrE6q126M6C0+SXgr2NHS2XdAPzxtr+V63lgdNHM06vpsgMXjGEuCI6ouQhM8UX0jbNIDwTgTw175fAWeqGeBLgNqrzk4YYmyEwYxpvexe3rZJruLcxt18PhkxRy+T+EVKb7mxJg1swHjV9DP5ISvatx8QHs18HoVy2Gtu20eqH2zIq6a7E51fix2xNnEYHm+pRec7m0cZZ/T+zXsdAZOM= root@gitlab.local
|
||||
@@ -0,0 +1,52 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
gitlab:
|
||||
image: gitlab/gitlab-ce:16.9.1-ce.0
|
||||
container_name: gitlab-ce
|
||||
hostname: gitlab.local
|
||||
restart: always
|
||||
shm_size: '1g'
|
||||
environment:
|
||||
GITLAB_OMNIBUS_CONFIG: |
|
||||
external_url 'http://192.168.1.83:8890'
|
||||
gitlab_rails['gitlab_shell_ssh_port'] = 8929
|
||||
nginx['listen_port'] = 80
|
||||
# 邮件配置 (可选)
|
||||
# gitlab_rails['smtp_enable'] = true
|
||||
# gitlab_rails['smtp_address'] = "smtp.gmail.com"
|
||||
# gitlab_rails['smtp_port'] = 587
|
||||
# gitlab_rails['smtp_user_name'] = "your-email@gmail.com"
|
||||
# gitlab_rails['smtp_password'] = "your-password"
|
||||
# gitlab_rails['smtp_domain'] = "smtp.gmail.com"
|
||||
# gitlab_rails['smtp_authentication'] = "login"
|
||||
# gitlab_rails['smtp_enable_starttls_auto'] = true
|
||||
# gitlab_rails['gitlab_email_from'] = 'your-email@gmail.com'
|
||||
ports:
|
||||
- "8890:80" # HTTP Web UI
|
||||
- "8929:22" # SSH
|
||||
volumes:
|
||||
- ./config:/etc/gitlab
|
||||
- ~/ops/data/gitlab/logs:/var/log/gitlab
|
||||
- ~/ops/data/gitlab/data:/var/opt/gitlab
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:80/-/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 300s
|
||||
|
||||
# GitLab Runner for CI/CD
|
||||
gitlab-runner:
|
||||
image: gitlab/gitlab-runner:latest
|
||||
container_name: gitlab-runner
|
||||
restart: always
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./gitlab-runner-config:/etc/gitlab-runner
|
||||
depends_on:
|
||||
- gitlab
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: gitlab-network
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
# GitLab 快速备份脚本
|
||||
# 这是 gitlab-data-protection.sh 的简化版本,专注于快速备份操作
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 配置变量
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
GITLAB_DATA_PROTECTION="${SCRIPT_DIR}/gitlab-data-protection.sh"
|
||||
BACKUP_NAME="${1:-}"
|
||||
|
||||
# 调用主脚本的备份功能
|
||||
if [[ -x "$GITLAB_DATA_PROTECTION" ]]; then
|
||||
if [[ -n "$BACKUP_NAME" ]]; then
|
||||
"$GITLAB_DATA_PROTECTION" backup "$BACKUP_NAME"
|
||||
else
|
||||
"$GITLAB_DATA_PROTECTION" backup
|
||||
fi
|
||||
else
|
||||
echo "错误: 找不到 GitLab 数据保护脚本: $GITLAB_DATA_PROTECTION"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+591
@@ -0,0 +1,591 @@
|
||||
#!/bin/bash
|
||||
|
||||
# GitLab 数据保护和管理脚本
|
||||
# 支持完整的 GitLab 服务管理、备份和恢复
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 配置变量
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_NAME="${PROJECT_NAME:-gitlab}"
|
||||
GITLAB_DIR="${GITLAB_DIR:-${SCRIPT_DIR}}"
|
||||
GITLAB_DATA_DIR="${GITLAB_DATA_DIR:-~/ops/data/gitlab}"
|
||||
GITLAB_CONFIG_DIR="${GITLAB_CONFIG_DIR:-${GITLAB_DIR}/config}"
|
||||
LOG_FILE="${LOG_FILE:-~/ops/logs/gitlab-protection.log}"
|
||||
BACKUP_DIR="${BACKUP_DIR:-~/ops/backups/gitlab}"
|
||||
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-${GITLAB_DIR}/docker-compose.yml}"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log() {
|
||||
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
|
||||
}
|
||||
|
||||
info() {
|
||||
log "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
success() {
|
||||
log "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
warning() {
|
||||
log "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
log "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查必要的依赖
|
||||
check_dependencies() {
|
||||
local deps=("docker" "docker-compose")
|
||||
for dep in "${deps[@]}"; do
|
||||
if ! command -v "$dep" &> /dev/null; then
|
||||
error "$dep 未安装,请先安装 $dep"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查 Docker 是否运行
|
||||
if ! docker info &> /dev/null; then
|
||||
error "Docker 未运行,请启动 Docker Desktop"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建必要的目录
|
||||
ensure_directories() {
|
||||
mkdir -p "$(dirname "${LOG_FILE}")"
|
||||
mkdir -p "${BACKUP_DIR}"
|
||||
mkdir -p "$(dirname "${GITLAB_DATA_DIR}")"
|
||||
mkdir -p "${GITLAB_CONFIG_DIR}"
|
||||
}
|
||||
|
||||
# 检查 GitLab 配置
|
||||
check_gitlab_config() {
|
||||
if [[ ! -f "${DOCKER_COMPOSE_FILE}" ]]; then
|
||||
error "GitLab Docker Compose 配置文件不存在: ${DOCKER_COMPOSE_FILE}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 服务状态检查
|
||||
check_service_status() {
|
||||
info "检查 GitLab 服务状态..."
|
||||
|
||||
local running_containers
|
||||
running_containers=$(docker-compose -f "${DOCKER_COMPOSE_FILE}" ps -q 2>/dev/null || echo "")
|
||||
|
||||
if [[ -z "$running_containers" ]]; then
|
||||
warning "GitLab 服务未运行"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local healthy_containers
|
||||
healthy_containers=$(docker-compose -f "${DOCKER_COMPOSE_FILE}" ps --filter "status=running" --format "table {{.Service}}\t{{.Status}}" 2>/dev/null | grep -c "healthy\|Up" || echo "0")
|
||||
|
||||
info "运行中的容器数量: $(echo "$running_containers" | wc -l)"
|
||||
info "健康容器数量: $healthy_containers"
|
||||
|
||||
# 检查 GitLab 主服务
|
||||
if docker-compose -f "${DOCKER_COMPOSE_FILE}" ps --services --filter "status=running" | grep -q "gitlab"; then
|
||||
info "GitLab 主服务运行正常"
|
||||
else
|
||||
warning "GitLab 主服务未运行"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 启动 GitLab 服务
|
||||
start_services() {
|
||||
info "启动 GitLab 服务..."
|
||||
|
||||
# 检查配置
|
||||
if ! check_gitlab_config; then
|
||||
error "GitLab 配置检查失败,无法启动服务"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 确保数据目录存在
|
||||
mkdir -p "${GITLAB_DATA_DIR}"
|
||||
|
||||
# 启动服务
|
||||
cd "${GITLAB_DIR}"
|
||||
docker-compose -f "${DOCKER_COMPOSE_FILE}" up -d
|
||||
|
||||
# 等待服务启动
|
||||
info "等待 GitLab 服务启动完成..."
|
||||
info "这可能需要几分钟时间,请耐心等待..."
|
||||
|
||||
# 等待 GitLab 健康检查通过
|
||||
local max_wait=300 # 5 分钟
|
||||
local wait_time=0
|
||||
|
||||
while [[ $wait_time -lt $max_wait ]]; do
|
||||
if docker-compose -f "${DOCKER_COMPOSE_FILE}" ps --format "table {{.Service}}\t{{.Status}}" | grep -q "healthy"; then
|
||||
success "GitLab 服务启动成功"
|
||||
return 0
|
||||
fi
|
||||
|
||||
info "等待服务启动... ($((wait_time/60))分$((wait_time%60))秒)"
|
||||
sleep 10
|
||||
wait_time=$((wait_time + 10))
|
||||
done
|
||||
|
||||
warning "GitLab 服务可能还在启动中,请稍后检查状态"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 停止 GitLab 服务
|
||||
stop_services() {
|
||||
info "停止 GitLab 服务..."
|
||||
|
||||
if [[ ! -f "${DOCKER_COMPOSE_FILE}" ]]; then
|
||||
warning "Docker Compose 配置文件不存在,跳过停止操作"
|
||||
return 0
|
||||
fi
|
||||
|
||||
cd "${GITLAB_DIR}"
|
||||
docker-compose -f "${DOCKER_COMPOSE_FILE}" down || true
|
||||
|
||||
success "GitLab 服务已停止"
|
||||
}
|
||||
|
||||
# 重启 GitLab 服务
|
||||
restart_services() {
|
||||
info "重启 GitLab 服务..."
|
||||
stop_services
|
||||
sleep 5
|
||||
start_services
|
||||
}
|
||||
|
||||
# 健康检查
|
||||
health_check() {
|
||||
info "执行 GitLab 健康检查..."
|
||||
|
||||
local status=0
|
||||
|
||||
# 检查服务状态
|
||||
if ! check_service_status; then
|
||||
error "服务状态检查失败"
|
||||
status=1
|
||||
fi
|
||||
|
||||
# 检查端口
|
||||
local ports=("8890" "8929")
|
||||
for port in "${ports[@]}"; do
|
||||
if lsof -i ":$port" &> /dev/null; then
|
||||
info "端口 $port 正在使用"
|
||||
else
|
||||
warning "端口 $port 未被使用"
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查数据目录
|
||||
if [[ -d "${GITLAB_DATA_DIR}" ]]; then
|
||||
local data_size
|
||||
data_size=$(du -sh "${GITLAB_DATA_DIR}" 2>/dev/null | cut -f1)
|
||||
info "GitLab 数据目录大小: $data_size"
|
||||
else
|
||||
warning "GitLab 数据目录不存在"
|
||||
status=1
|
||||
fi
|
||||
|
||||
# 检查配置目录
|
||||
if [[ -d "${GITLAB_CONFIG_DIR}" ]]; then
|
||||
info "GitLab 配置目录存在"
|
||||
else
|
||||
warning "GitLab 配置目录不存在"
|
||||
status=1
|
||||
fi
|
||||
|
||||
if [[ $status -eq 0 ]]; then
|
||||
success "GitLab 健康检查通过"
|
||||
else
|
||||
error "GitLab 健康检查发现问题"
|
||||
fi
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
# 获取 GitLab 统计信息
|
||||
get_stats() {
|
||||
info "获取 GitLab 统计信息..."
|
||||
|
||||
# 服务状态
|
||||
check_service_status
|
||||
|
||||
# 数据目录统计
|
||||
if [[ -d "${GITLAB_DATA_DIR}" ]]; then
|
||||
echo ""
|
||||
info "=== 数据目录统计 ==="
|
||||
du -sh "${GITLAB_DATA_DIR}"/* 2>/dev/null | sort -hr || true
|
||||
|
||||
# 仓库数量统计
|
||||
local repos_dir="${GITLAB_DATA_DIR}/repositories"
|
||||
if [[ -d "$repos_dir" ]]; then
|
||||
local repo_count
|
||||
repo_count=$(find "$repos_dir" -maxdepth 2 -type d -name "*.git" 2>/dev/null | wc -l || echo "0")
|
||||
info "Git 仓库数量: $repo_count"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 备份文件统计
|
||||
if [[ -d "${BACKUP_DIR}" ]]; then
|
||||
echo ""
|
||||
info "=== 备份文件统计 ==="
|
||||
ls -lah "${BACKUP_DIR}"/*.tar.gz 2>/dev/null | tail -10 || true
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份 GitLab 数据
|
||||
backup_gitlab() {
|
||||
local backup_name="${1:-gitlab-$(date +%Y%m%d-%H%M%S)}"
|
||||
local backup_file="${BACKUP_DIR}/${backup_name}.tar.gz"
|
||||
|
||||
info "开始备份 GitLab 数据..."
|
||||
|
||||
# 检查服务状态
|
||||
local service_running=false
|
||||
if check_service_status &>/dev/null; then
|
||||
service_running=true
|
||||
info "检测到服务运行中,将创建在线备份"
|
||||
fi
|
||||
|
||||
# 创建备份
|
||||
local backup_items=()
|
||||
|
||||
# GitLab 配置
|
||||
if [[ -d "${GITLAB_CONFIG_DIR}" ]] && [[ -n "$(ls -A "${GITLAB_CONFIG_DIR}" 2>/dev/null)" ]]; then
|
||||
backup_items+=("${GITLAB_CONFIG_DIR}")
|
||||
fi
|
||||
|
||||
# GitLab 数据目录
|
||||
if [[ -d "${GITLAB_DATA_DIR}" ]]; then
|
||||
backup_items+=("${GITLAB_DATA_DIR}")
|
||||
fi
|
||||
|
||||
# Docker Compose 配置
|
||||
if [[ -f "${DOCKER_COMPOSE_FILE}" ]]; then
|
||||
backup_items+=("${DOCKER_COMPOSE_FILE}")
|
||||
fi
|
||||
|
||||
if [[ ${#backup_items[@]} -eq 0 ]]; then
|
||||
error "没有找到需要备份的文件或目录"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 执行备份
|
||||
info "创建备份文件: $backup_file"
|
||||
tar -czf "${backup_file}" "${backup_items[@]}" 2>/dev/null
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
# 创建备份元数据
|
||||
local meta_file="${backup_file}.meta"
|
||||
cat > "${meta_file}" << EOF
|
||||
backup_name="${backup_name}"
|
||||
backup_date="$(date -Iseconds)"
|
||||
backup_size="$(stat -f%z "${backup_file}" 2>/dev/null || stat -c%s "${backup_file}" 2>/dev/null || echo "unknown")"
|
||||
service_running="${service_running}"
|
||||
gitlab_version="16.9.1"
|
||||
items="$(printf '%s;' "${backup_items[@]}")"
|
||||
EOF
|
||||
|
||||
success "GitLab 备份完成: ${backup_file}"
|
||||
|
||||
# 显示备份信息
|
||||
local backup_size
|
||||
backup_size=$(ls -lh "${backup_file}" | awk '{print $5}')
|
||||
info "备份大小: ${backup_size}"
|
||||
|
||||
# 清理旧备份 (保留最近 10 个)
|
||||
cleanup_old_backups 10
|
||||
else
|
||||
error "GitLab 备份失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 恢复 GitLab 数据
|
||||
restore_gitlab() {
|
||||
local backup_file="${1:-}"
|
||||
|
||||
if [[ -z "$backup_file" ]]; then
|
||||
error "请指定备份文件"
|
||||
show_backups
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$backup_file" ]]; then
|
||||
error "备份文件不存在: $backup_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
info "开始从备份恢复 GitLab..."
|
||||
|
||||
# 创建安全备份
|
||||
local safety_backup="${BACKUP_DIR}/safety-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||||
if [[ -d "${GITLAB_DATA_DIR}" ]] || [[ -d "${GITLAB_CONFIG_DIR}" ]]; then
|
||||
info "创建当前状态的安全备份: $safety_backup"
|
||||
backup_gitlab "safety-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
fi
|
||||
|
||||
# 停止现有服务
|
||||
stop_services
|
||||
|
||||
# 恢复备份
|
||||
info "恢复备份文件: $backup_file"
|
||||
cd /
|
||||
tar -xzf "$backup_file" 2>/dev/null
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
success "GitLab 数据恢复完成"
|
||||
|
||||
# 启动服务
|
||||
sleep 5
|
||||
start_services
|
||||
|
||||
# 验证恢复结果
|
||||
if health_check; then
|
||||
success "GitLab 恢复验证通过"
|
||||
else
|
||||
error "GitLab 恢复验证失败,请检查日志"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
error "GitLab 数据恢复失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示可用备份
|
||||
show_backups() {
|
||||
info "可用的 GitLab 备份文件:"
|
||||
if [[ -d "${BACKUP_DIR}" ]]; then
|
||||
local backups=($(ls -t "${BACKUP_DIR}"/gitlab-*.tar.gz 2>/dev/null || true))
|
||||
if [[ ${#backups[@]} -gt 0 ]]; then
|
||||
for i in "${!backups[@]}"; do
|
||||
local backup_file="${backups[$i]}"
|
||||
local backup_size
|
||||
backup_size=$(ls -lh "$backup_file" | awk '{print $5}')
|
||||
local backup_date
|
||||
backup_date=$(stat -f%Sm -t%Y-%m-%d\ %H:%M:%S "$backup_file" 2>/dev/null || stat -c%y "$backup_file" 2>/dev/null | cut -d'.' -f1)
|
||||
printf "%2d. %-40s %10s %s\n" $((i+1)) "$(basename "$backup_file")" "$backup_size" "$backup_date"
|
||||
done
|
||||
else
|
||||
warning "没有找到 GitLab 备份文件"
|
||||
fi
|
||||
else
|
||||
warning "备份目录不存在: ${BACKUP_DIR}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理旧备份
|
||||
cleanup_old_backups() {
|
||||
local keep_count="${1:-5}"
|
||||
|
||||
info "清理旧备份文件,保留最近 $keep_count 个..."
|
||||
|
||||
if [[ -d "${BACKUP_DIR}" ]]; then
|
||||
local old_backups
|
||||
old_backups=($(ls -t "${BACKUP_DIR}"/gitlab-*.tar.gz 2>/dev/null | tail -n +$((keep_count+1)) || true))
|
||||
|
||||
if [[ ${#old_backups[@]} -gt 0 ]]; then
|
||||
for backup in "${old_backups[@]}"; do
|
||||
info "删除旧备份: $(basename "$backup")"
|
||||
rm -f "$backup" "${backup}.meta"
|
||||
done
|
||||
success "已清理 ${#old_backups[@]} 个旧备份文件"
|
||||
else
|
||||
info "没有需要清理的旧备份文件"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 设置定时任务
|
||||
setup_cron() {
|
||||
local cron_interval="${1:-"0 3 * * *"}" # 默认每天凌晨 3 点
|
||||
|
||||
info "设置 GitLab 备份定时任务..."
|
||||
|
||||
# 创建 cron 脚本
|
||||
local cron_script="${SCRIPT_DIR}/gitlab-cron-backup.sh"
|
||||
cat > "$cron_script" << EOF
|
||||
#!/bin/bash
|
||||
# GitLab 自动备份 cron 任务
|
||||
$(declare -f log info success warning error)
|
||||
$(declare -f check_dependencies ensure_directories backup_gitlab)
|
||||
|
||||
LOG_FILE="${LOG_FILE}"
|
||||
BACKUP_DIR="${BACKUP_DIR}"
|
||||
GITLAB_DATA_DIR="${GITLAB_DATA_DIR}"
|
||||
GITLAB_CONFIG_DIR="${GITLAB_CONFIG_DIR}"
|
||||
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE}"
|
||||
|
||||
# 执行备份
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
backup_gitlab
|
||||
EOF
|
||||
|
||||
chmod +x "$cron_script"
|
||||
|
||||
# 添加到 crontab
|
||||
local cron_entry="$cron_interval $cron_script >> ${LOG_FILE} 2>&1"
|
||||
(crontab -l 2>/dev/null | grep -v "gitlab-cron-backup" || true; echo "$cron_entry") | crontab -
|
||||
|
||||
# 设置 launchd 任务 (macOS 原生)
|
||||
local launchd_plist="$HOME/Library/LaunchAgents/com.ljwx.gitlab.backup.plist"
|
||||
cat > "$launchd_plist" << EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.ljwx.gitlab.backup</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>$cron_script</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Hour</key>
|
||||
<integer>3</integer>
|
||||
<key>Minute</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>StandardOutPath</key>
|
||||
<string>${LOG_FILE}.cron.stdout.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>${LOG_FILE}.cron.stderr.log</string>
|
||||
<key>RunAtLoad</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
# 加载 launchd 任务
|
||||
launchctl unload "$launchd_plist" 2>/dev/null || true
|
||||
launchctl load -w "$launchd_plist"
|
||||
|
||||
success "GitLab 备份定时任务已设置"
|
||||
info "Cron 任务: $cron_entry"
|
||||
info "Launchd 任务已加载"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
GitLab 数据保护和管理脚本
|
||||
|
||||
用法: $0 [命令] [参数]
|
||||
|
||||
命令:
|
||||
start 启动 GitLab 服务
|
||||
stop 停止 GitLab 服务
|
||||
restart 重启 GitLab 服务
|
||||
status 检查服务状态
|
||||
health 执行健康检查
|
||||
stats 显示统计信息
|
||||
backup [名称] 创建备份
|
||||
restore [文件] 从备份恢复
|
||||
list 显示可用备份
|
||||
cleanup [数量] 清理旧备份 (默认保留 5 个)
|
||||
setup 设置定时任务
|
||||
help 显示帮助信息
|
||||
|
||||
示例:
|
||||
$0 start # 启动服务
|
||||
$0 backup # 创建备份
|
||||
$0 backup my-backup # 创建命名备份
|
||||
$0 restore backup-2023.tar.gz # 从备份恢复
|
||||
$0 cleanup 10 # 保留最近 10 个备份
|
||||
|
||||
环境变量:
|
||||
GITLAB_DIR GitLab 配置目录 (默认: 脚本所在目录)
|
||||
GITLAB_DATA_DIR GitLab 数据目录 (默认: ~/ops/data/gitlab)
|
||||
GITLAB_CONFIG_DIR GitLab 配置目录 (默认: ~/ops/gitlab/config)
|
||||
BACKUP_DIR 备份目录 (默认: ~/ops/backups/gitlab)
|
||||
LOG_FILE 日志文件 (默认: ~/ops/logs/gitlab-protection.log)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local command="${1:-help}"
|
||||
local parameter="${2:-}"
|
||||
|
||||
# 设置环境变量
|
||||
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
|
||||
|
||||
case "$command" in
|
||||
"start")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
start_services
|
||||
;;
|
||||
"stop")
|
||||
stop_services
|
||||
;;
|
||||
"restart")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
restart_services
|
||||
;;
|
||||
"status")
|
||||
check_service_status
|
||||
;;
|
||||
"health")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
health_check
|
||||
;;
|
||||
"stats")
|
||||
get_stats
|
||||
;;
|
||||
"backup")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
backup_gitlab "$parameter"
|
||||
;;
|
||||
"restore")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
restore_gitlab "$parameter"
|
||||
;;
|
||||
"list"|"ls")
|
||||
show_backups
|
||||
;;
|
||||
"cleanup")
|
||||
cleanup_old_backups "$parameter"
|
||||
;;
|
||||
"setup")
|
||||
setup_cron "$parameter"
|
||||
;;
|
||||
"help"|"-h"|"--help")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
error "未知命令: $command"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 如果脚本被直接执行,调用主函数
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# GitLab 快速恢复脚本
|
||||
# 这是 gitlab-data-protection.sh 的简化版本,专注于快速恢复操作
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 配置变量
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
GITLAB_DATA_PROTECTION="${SCRIPT_DIR}/gitlab-data-protection.sh"
|
||||
BACKUP_FILE="${1:-}"
|
||||
|
||||
# 显示可用备份 (如果没有指定备份文件)
|
||||
if [[ -z "$BACKUP_FILE" ]]; then
|
||||
echo "可用的 GitLab 备份文件:"
|
||||
"$GITLAB_DATA_PROTECTION" list
|
||||
echo ""
|
||||
echo "请指定要恢复的备份文件,例如:"
|
||||
echo "$0 gitlab-20231220-120000.tar.gz"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 调用主脚本的恢复功能
|
||||
if [[ -x "$GITLAB_DATA_PROTECTION" ]]; then
|
||||
"$GITLAB_DATA_PROTECTION" restore "$BACKUP_FILE"
|
||||
else
|
||||
echo "错误: 找不到 GitLab 数据保护脚本: $GITLAB_DATA_PROTECTION"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
r_rIOicO9Zro6w
|
||||
@@ -0,0 +1,36 @@
|
||||
# GitLab Runner configuration file
|
||||
# This file will be auto-generated after runner registration
|
||||
# You can customize the configuration here
|
||||
|
||||
concurrent = 4
|
||||
check_interval = 0
|
||||
|
||||
[session_server]
|
||||
session_timeout = 1800
|
||||
|
||||
[[runners]]
|
||||
name = "docker-runner"
|
||||
url = "http://192.168.1.83:8890"
|
||||
token = "REPLACE_WITH_REGISTRATION_TOKEN"
|
||||
executor = "docker"
|
||||
[runners.docker]
|
||||
tls_verify = false
|
||||
image = "docker:latest"
|
||||
privileged = false
|
||||
disable_entrypoint_overwrite = false
|
||||
oom_kill_disable = false
|
||||
disable_cache = false
|
||||
volumes = ["/cache"]
|
||||
shm_size = 0
|
||||
[runners.cache]
|
||||
[runners.cache.s3]
|
||||
[runners.cache.gcs]
|
||||
|
||||
[[runners]]
|
||||
name = "shell-runner"
|
||||
url = "http://192.168.1.83:8890"
|
||||
token = "REPLACE_WITH_REGISTRATION_TOKEN"
|
||||
executor = "shell"
|
||||
[runners.cache]
|
||||
[runners.cache.s3]
|
||||
[runners.cache.gcs]
|
||||
@@ -0,0 +1,167 @@
|
||||
# GitLab CI/CD 手动设置指南
|
||||
|
||||
## 当前状态
|
||||
|
||||
✅ **已完成:**
|
||||
- GitLab CE 16.9.1 实例已启动
|
||||
- GitLab Runner 容器已运行
|
||||
- CI/CD 配置模板已创建
|
||||
- 环境变量配置脚本已准备
|
||||
|
||||
⏳ **需要手动完成:**
|
||||
- GitLab 初始密码设置
|
||||
- Runner 注册 token 获取
|
||||
- 手动注册 GitLab Runner
|
||||
|
||||
## 手动设置步骤
|
||||
|
||||
### 1. 访问 GitLab 并设置密码
|
||||
|
||||
1. 打开浏览器访问: http://192.168.1.83:8890
|
||||
2. 首次访问会显示设置密码页面
|
||||
3. 设置管理员密码 (建议: `admin123`)
|
||||
4. 使用用户名 `root` 和设置的密码登录
|
||||
|
||||
### 2. 获取 Runner 注册 Token
|
||||
|
||||
有两种方式获取 Runner 注册 token:
|
||||
|
||||
#### 方法 A: 实例级别 Runner (推荐)
|
||||
1. 登录后点击右上角头像
|
||||
2. 选择 "Admin Area"
|
||||
3. 左侧菜单找到 "Runners"
|
||||
4. 点击 "New instance runner"
|
||||
5. 复制显示的 "Registration token"
|
||||
|
||||
#### 方法 B: 群组级别 Runner
|
||||
1. 创建或选择一个群组
|
||||
2. 进入群组设置
|
||||
3. 左侧菜单找到 "CI/CD"
|
||||
4. 展开 "Runners" 部分
|
||||
5. 复制注册 token
|
||||
|
||||
### 3. 手动注册 GitLab Runner
|
||||
|
||||
打开终端,在 gitlab 目录中运行:
|
||||
|
||||
```bash
|
||||
# 注册 Docker Runner
|
||||
docker exec -it gitlab-runner gitlab-runner register
|
||||
|
||||
# 按提示输入以下信息:
|
||||
# Enter the GitLab instance URL: http://192.168.1.83:8890
|
||||
# Enter the registration token: [粘贴上面获取的 token]
|
||||
# Enter a description for the runner: docker-runner
|
||||
# Enter tags for the runner: docker,build,deploy
|
||||
# Enter optional maintenance note:
|
||||
# Enter an executor: docker
|
||||
# Enter the default Docker image: docker:latest
|
||||
|
||||
# 注册 Shell Runner (可选)
|
||||
docker exec -it gitlab-runner gitlab-runner register
|
||||
|
||||
# 按提示输入以下信息:
|
||||
# Enter the GitLab instance URL: http://192.168.1.83:8890
|
||||
# Enter the registration token: [使用相同的 token]
|
||||
# Enter a description for the runner: shell-runner
|
||||
# Enter tags for the runner: shell,local,scripts
|
||||
# Enter optional maintenance note:
|
||||
# Enter an executor: shell
|
||||
```
|
||||
|
||||
### 4. 验证 Runner 状态
|
||||
|
||||
在 GitLab 管理界面的 Runners 页面检查是否能看到已注册的 Runner。
|
||||
|
||||
### 5. 为 Stock 项目配置 CI/CD
|
||||
|
||||
#### 创建测试项目
|
||||
1. 在 GitLab 中创建新项目,例如 "stock-project"
|
||||
2. 克隆项目到本地
|
||||
3. 添加 CI/CD 配置文件
|
||||
|
||||
#### 使用提供的模板
|
||||
```bash
|
||||
# 复制简化配置模板
|
||||
cp gitlab/ci-templates/.gitlab-ci.yml.simple /path/to/stock-project/.gitlab-ci.yml
|
||||
|
||||
# 或者使用完整配置模板
|
||||
cp gitlab/ci-templates/.gitlab-ci.yml.stock /path/to/stock-project/.gitlab-ci.yml
|
||||
```
|
||||
|
||||
#### 配置环境变量
|
||||
运行环境变量配置脚本:
|
||||
```bash
|
||||
cd gitlab
|
||||
./setup-ci-env.sh stock-project dev
|
||||
```
|
||||
|
||||
或者在 GitLab UI 中手动配置:
|
||||
1. 进入项目设置
|
||||
2. CI/CD -> Variables
|
||||
3. 添加必要的环境变量
|
||||
|
||||
### 6. 测试 CI/CD 流水线
|
||||
|
||||
1. 创建一个简单的测试文件
|
||||
2. 提交并推送到 GitLab
|
||||
3. 观察流水线是否自动运行
|
||||
|
||||
## 快速测试命令
|
||||
|
||||
创建一个测试项目:
|
||||
```bash
|
||||
mkdir test-stock-project
|
||||
cd test-stock-project
|
||||
git init
|
||||
echo "# Test Stock Project" > README.md
|
||||
echo 'console.log("Hello from CI/CD!");' > test.js
|
||||
|
||||
# 添加 package.json
|
||||
cat > package.json << 'EOF'
|
||||
{
|
||||
"name": "test-stock-project",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "echo 'Running tests...' && node test.js"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# 复制 CI/CD 配置
|
||||
cp /Users/brunogao/work/codes/tools/macos/gitlab/ci-templates/.gitlab-ci.yml.simple .gitlab-ci.yml
|
||||
|
||||
# 提交并推送
|
||||
git add .
|
||||
git commit -m "Initial commit with CI/CD"
|
||||
git remote add origin http://192.168.1.83:8890/root/test-stock-project.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### GitLab 无法访问
|
||||
- 检查容器状态: `docker ps | grep gitlab`
|
||||
- 查看日志: `docker logs gitlab-ce`
|
||||
- 确认端口映射: `docker port gitlab-ce`
|
||||
|
||||
### Runner 无法注册
|
||||
- 确认 GitLab 完全启动 (通常需要 5-10 分钟)
|
||||
- 检查网络连接
|
||||
- 验证注册 token 是否正确
|
||||
|
||||
### 流水线不运行
|
||||
- 确认 Runner 已注册且状态为 "online"
|
||||
- 检查 `.gitlab-ci.yml` 文件语法
|
||||
- 确认 Runner 标签与流水线要求匹配
|
||||
|
||||
## 下一步
|
||||
|
||||
完成手动设置后,你将拥有一个完整的 GitLab CI/CD 环境,可以用于:
|
||||
- 自动化测试
|
||||
- 代码质量检查
|
||||
- 自动构建和部署
|
||||
- 安全扫描
|
||||
- 环境管理
|
||||
|
||||
所有配置文件和脚本都已保存在 `gitlab/` 目录中,可供参考和定制。
|
||||
Executable
+193
@@ -0,0 +1,193 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 简化的 GitLab Runner 注册脚本
|
||||
# 适用于已运行的 GitLab 实例
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# GitLab 配置
|
||||
GITLAB_URL="http://192.168.1.83:8890"
|
||||
GITLAB_ADMIN_USER="root"
|
||||
GITLAB_ADMIN_PASSWORD="admin123"
|
||||
|
||||
echo -e "${GREEN}GitLab Runner 简化注册脚本${NC}"
|
||||
echo "=================================="
|
||||
|
||||
# 检查 GitLab Runner 容器是否运行
|
||||
echo -e "${YELLOW}检查 GitLab Runner 容器状态...${NC}"
|
||||
if ! docker ps | grep gitlab-runner > /dev/null; then
|
||||
echo -e "${RED}错误: GitLab Runner 容器未运行${NC}"
|
||||
echo "请先启动 Runner: docker-compose up -d gitlab-runner"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ GitLab Runner 容器正在运行${NC}"
|
||||
|
||||
# 检查 GitLab 是否可访问
|
||||
echo -e "${YELLOW}检查 GitLab 服务可访问性...${NC}"
|
||||
if ! curl -s -I "$GITLAB_URL" | grep -q "302\|200"; then
|
||||
echo -e "${RED}错误: GitLab 服务不可访问${NC}"
|
||||
echo "请检查 GitLab 是否正常运行"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ GitLab 服务可访问${NC}"
|
||||
|
||||
# 获取管理员 token
|
||||
echo -e "${YELLOW}获取 GitLab API token...${NC}"
|
||||
PRIVATE_TOKEN=$(curl -s -X POST "$GITLAB_URL/api/v4/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"login\":\"$GITLAB_ADMIN_USER\",\"password\":\"$GITLAB_ADMIN_PASSWORD\"}" | \
|
||||
jq -r '.private_token' 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$PRIVATE_TOKEN" ] || [ "$PRIVATE_TOKEN" = "null" ]; then
|
||||
echo -e "${RED}错误: 无法获取 API token${NC}"
|
||||
echo "请检查 GitLab 管理员凭据"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ API token 获取成功${NC}"
|
||||
|
||||
# 创建群组级别的 Runner token
|
||||
echo -e "${YELLOW}获取 Runner 注册 token...${NC}"
|
||||
|
||||
# 首先尝试获取实例级别的 Runner token
|
||||
INSTANCE_TOKEN=$(curl -s "$GITLAB_URL/api/v4/runners" \
|
||||
-H "Private-Token: $PRIVATE_TOKEN" | \
|
||||
jq -r '.[0].token // ""' 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$INSTANCE_TOKEN" ]; then
|
||||
echo -e "${YELLOW}需要手动获取 Runner 注册 token${NC}"
|
||||
echo "请按以下步骤操作:"
|
||||
echo ""
|
||||
echo -e "${BLUE}1. 访问 GitLab 管理界面:${NC}"
|
||||
echo " $GITLAB_URL"
|
||||
echo ""
|
||||
echo -e "${BLUE}2. 使用管理员账号登录:${NC}"
|
||||
echo " 用户名: $GITLAB_ADMIN_USER"
|
||||
echo " 密码: $GITLAB_ADMIN_PASSWORD"
|
||||
echo ""
|
||||
echo -e "${BLUE}3. 获取 Runner 注册 token:${NC}"
|
||||
echo " 方法一 (实例级别 Runner):"
|
||||
echo " - 点击右上角管理员区域"
|
||||
echo " - 左侧菜单选择 'Runners'"
|
||||
echo " - 点击 'New instance runner'"
|
||||
echo " - 复制 'Registration token'"
|
||||
echo ""
|
||||
echo " 方法二 (群组级别 Runner):"
|
||||
echo " - 选择或创建一个群组"
|
||||
echo " - 进入群组设置 -> CI/CD -> Runners"
|
||||
echo " - 获取注册 token"
|
||||
echo ""
|
||||
echo -e "${BLUE}4. 将 token 粘贴到下面:${NC}"
|
||||
read -p "请输入 Runner 注册 token: " INPUT_TOKEN
|
||||
|
||||
if [ -z "$INPUT_TOKEN" ]; then
|
||||
echo -e "${RED}错误: 注册 token 不能为空${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REGISTRATION_TOKEN="$INPUT_TOKEN"
|
||||
else
|
||||
REGISTRATION_TOKEN="$INSTANCE_TOKEN"
|
||||
echo -e "${GREEN}✓ 获取到实例级 Runner token${NC}"
|
||||
fi
|
||||
|
||||
# 注册 Docker Runner
|
||||
echo -e "${YELLOW}注册 Docker Runner...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner register \
|
||||
--non-interactive \
|
||||
--url "$GITLAB_URL" \
|
||||
--registration-token "$REGISTRATION_TOKEN" \
|
||||
--executor "docker" \
|
||||
--docker-image docker:latest \
|
||||
--description "docker-runner" \
|
||||
--tag-list "docker,build,deploy" \
|
||||
--run-untagged="false" \
|
||||
--access-level="not_protected" \
|
||||
--docker-privileged="false" \
|
||||
--docker-volumes "/cache" \
|
||||
--docker-pull-policy "if-not-present"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ Docker Runner 注册成功${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ Docker Runner 注册失败${NC}"
|
||||
fi
|
||||
|
||||
# 注册 Shell Runner
|
||||
echo -e "${YELLOW}注册 Shell Runner...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner register \
|
||||
--non-interactive \
|
||||
--url "$GITLAB_URL" \
|
||||
--registration-token "$REGISTRATION_TOKEN" \
|
||||
--executor "shell" \
|
||||
--description "shell-runner" \
|
||||
--tag-list "shell,local,scripts" \
|
||||
--run-untagged="false" \
|
||||
--access-level="not_protected"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ Shell Runner 注册成功${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ Shell Runner 注册失败${NC}"
|
||||
fi
|
||||
|
||||
# 重启 Runner 服务
|
||||
echo -e "${YELLOW}重启 Runner 服务...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner restart
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ Runner 服务重启成功${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ Runner 服务重启失败${NC}"
|
||||
fi
|
||||
|
||||
# 验证 Runner 状态
|
||||
echo -e "${YELLOW}验证 Runner 状态...${NC}"
|
||||
echo "已注册的 Runners:"
|
||||
docker exec gitlab-runner gitlab-runner list 2>/dev/null || echo "无法列出 Runners"
|
||||
|
||||
# 验证 Runner 在 GitLab 中是否可见
|
||||
echo -e "${YELLOW}检查 GitLab 中的 Runner 状态...${NC}"
|
||||
RUNNERS_INFO=$(curl -s "$GITLAB_URL/api/v4/runners?per_page=10" \
|
||||
-H "Private-Token: $PRIVATE_TOKEN" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$RUNNERS_INFO" ]; then
|
||||
echo -e "${GREEN}✓ GitLab 中可见的 Runners:${NC}"
|
||||
echo "$RUNNERS_INFO" | jq -r '.[] | "ID: \(.id) | 名称: \(.description) | 状态: \(.status) | 标签: \(.tag_list | join(", "))"' 2>/dev/null || echo "无法解析 Runner 信息"
|
||||
else
|
||||
echo -e "${YELLOW}无法获取 GitLab 中的 Runner 信息${NC}"
|
||||
fi
|
||||
|
||||
# 显示配置完成信息
|
||||
echo ""
|
||||
echo -e "${GREEN}Runner 注册完成!${NC}"
|
||||
echo "=================================="
|
||||
echo -e "${BLUE}配置总结:${NC}"
|
||||
echo "• GitLab URL: $GITLAB_URL"
|
||||
echo "• Docker Runner: 已注册 (标签: docker,build,deploy)"
|
||||
echo "• Shell Runner: 已注册 (标签: shell,local,scripts)"
|
||||
echo ""
|
||||
echo -e "${BLUE}下一步操作:${NC}"
|
||||
echo "1. 在 GitLab 中查看和管理 Runners:"
|
||||
echo " $GITLAB_URL/admin/runners"
|
||||
echo ""
|
||||
echo "2. 为你的项目配置 CI/CD:"
|
||||
echo " - 将 .gitlab-ci.yml 文件添加到项目根目录"
|
||||
echo " - 推送代码到 GitLab"
|
||||
echo " - 流水线将自动运行"
|
||||
echo ""
|
||||
echo "3. 使用环境变量配置脚本:"
|
||||
echo " ./setup-ci-env.sh <项目名称> [环境类型]"
|
||||
echo ""
|
||||
echo -e "${BLUE}Runner 使用示例:${NC}"
|
||||
echo "• Docker Runner: 适用于容器化构建和测试"
|
||||
echo "• Shell Runner: 适用于本地脚本和系统任务"
|
||||
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
|
||||
# GitLab Runner 注册脚本
|
||||
# 用于将 Runner 注册到 GitLab 实例
|
||||
|
||||
set -e
|
||||
|
||||
# GitLab 实例配置
|
||||
GITLAB_URL="http://192.168.1.83:8890"
|
||||
GITLAB_ADMIN_USER="root"
|
||||
GITLAB_ADMIN_PASSWORD="admin123"
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${GREEN}GitLab Runner 注册脚本${NC}"
|
||||
echo "=================================="
|
||||
|
||||
# 检查 GitLab 是否运行
|
||||
echo -e "${YELLOW}检查 GitLab 服务状态...${NC}"
|
||||
if ! docker ps | grep gitlab-ce > /dev/null; then
|
||||
echo -e "${RED}错误: GitLab 容器未运行${NC}"
|
||||
echo "请先启动 GitLab: docker-compose up -d"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 等待 GitLab 完全启动
|
||||
echo -e "${YELLOW}等待 GitLab 完全启动...${NC}"
|
||||
until curl -f -s "$GITLAB_URL/-/health" > /dev/null; do
|
||||
echo "GitLab 正在启动中..."
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo -e "${GREEN}GitLab 已启动并可用${NC}"
|
||||
|
||||
# 获取 Runner 注册 token
|
||||
echo -e "${YELLOW}获取 Runner 注册 token...${NC}"
|
||||
REGISTRATION_TOKEN=$(curl -s -X POST "$GITLAB_URL/api/v4/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"login\":\"$GITLAB_ADMIN_USER\",\"password\":\"$GITLAB_ADMIN_PASSWORD\"}" | \
|
||||
jq -r '.private_token')
|
||||
|
||||
if [ "$REGISTRATION_TOKEN" = "null" ] || [ -z "$REGISTRATION_TOKEN" ]; then
|
||||
echo -e "${RED}错误: 无法获取认证 token${NC}"
|
||||
echo "请检查 GitLab 管理员凭据"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 获取 Runner 注册 token
|
||||
RUNNER_TOKEN=$(curl -s -X GET "$GITLAB_URL/api/v4/runners" \
|
||||
-H "Private-Token: $REGISTRATION_TOKEN" | \
|
||||
jq -r '.[0].token // ""')
|
||||
|
||||
if [ -z "$RUNNER_TOKEN" ]; then
|
||||
echo -e "${YELLOW}创建新的 Runner 注册 token...${NC}"
|
||||
# 这里需要从 GitLab UI 获取注册 token
|
||||
echo "请访问 $GITLAB_URL/admin/runners 获取注册 token"
|
||||
echo "或者在项目设置中获取项目特定的 runner token"
|
||||
read -p "请输入 Runner 注册 token: " INPUT_TOKEN
|
||||
RUNNER_TOKEN="$INPUT_TOKEN"
|
||||
fi
|
||||
|
||||
# 启动 GitLab Runner 容器
|
||||
echo -e "${YELLOW}启动 GitLab Runner 容器...${NC}"
|
||||
docker-compose up -d gitlab-runner
|
||||
|
||||
# 等待 Runner 容器启动
|
||||
sleep 10
|
||||
|
||||
# 注册 Docker Runner
|
||||
echo -e "${YELLOW}注册 Docker Runner...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner register \
|
||||
--non-interactive \
|
||||
--url "$GITLAB_URL" \
|
||||
--registration-token "$RUNNER_TOKEN" \
|
||||
--executor "docker" \
|
||||
--docker-image docker:latest \
|
||||
--description "docker-runner" \
|
||||
--tag-list "docker,build,deploy" \
|
||||
--run-untagged="false" \
|
||||
--access-level="not_protected"
|
||||
|
||||
# 注册 Shell Runner
|
||||
echo -e "${YELLOW}注册 Shell Runner...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner register \
|
||||
--non-interactive \
|
||||
--url "$GITLAB_URL" \
|
||||
--registration-token "$RUNNER_TOKEN" \
|
||||
--executor "shell" \
|
||||
--description "shell-runner" \
|
||||
--tag-list "shell,local,scripts" \
|
||||
--run-untagged="false" \
|
||||
--access-level="not_protected"
|
||||
|
||||
# 重启 Runner 服务
|
||||
echo -e "${YELLOW}重启 Runner 服务...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner restart
|
||||
|
||||
# 验证 Runner 状态
|
||||
echo -e "${YELLOW}验证 Runner 状态...${NC}"
|
||||
docker exec gitlab-runner gitlab-runner list
|
||||
|
||||
echo -e "${GREEN}Runner 注册完成!${NC}"
|
||||
echo "=================================="
|
||||
echo "您现在可以在 GitLab 项目中启用 CI/CD 功能了"
|
||||
echo "访问 $GITLAB_URL 查看和管理您的 runners"
|
||||
Executable
+252
@@ -0,0 +1,252 @@
|
||||
#!/bin/bash
|
||||
|
||||
# GitLab CI/CD 环境变量配置脚本
|
||||
# 用于快速设置项目所需的环境变量
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# GitLab 配置
|
||||
GITLAB_URL="http://192.168.1.83:8890"
|
||||
GITLAB_ADMIN_USER="root"
|
||||
GITLAB_ADMIN_PASSWORD="admin123"
|
||||
|
||||
echo -e "${GREEN}GitLab CI/CD 环境变量配置脚本${NC}"
|
||||
echo "=================================="
|
||||
|
||||
# 使用说明
|
||||
usage() {
|
||||
echo -e "${BLUE}用法:${NC}"
|
||||
echo " $0 [项目名称] [环境类型]"
|
||||
echo ""
|
||||
echo -e "${BLUE}参数:${NC}"
|
||||
echo " 项目名称 GitLab 项目名称"
|
||||
echo " 环境类型 dev/prod (可选,默认为 dev)"
|
||||
echo ""
|
||||
echo -e "${BLUE}示例:${NC}"
|
||||
echo " $0 stock-project dev"
|
||||
echo " $0 stock-app prod"
|
||||
}
|
||||
|
||||
# 检查参数
|
||||
if [ $# -lt 1 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROJECT_NAME="$1"
|
||||
ENV_TYPE="${2:-dev}"
|
||||
|
||||
echo -e "${YELLOW}项目名称: $PROJECT_NAME${NC}"
|
||||
echo -e "${YELLOW}环境类型: $ENV_TYPE${NC}"
|
||||
echo ""
|
||||
|
||||
# 检查 GitLab 是否运行
|
||||
echo -e "${YELLOW}检查 GitLab 服务状态...${NC}"
|
||||
if ! docker ps | grep gitlab-ce > /dev/null; then
|
||||
echo -e "${RED}错误: GitLab 容器未运行${NC}"
|
||||
echo "请先启动 GitLab: cd gitlab && docker-compose up -d"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 等待 GitLab 完全启动
|
||||
echo -e "${YELLOW}等待 GitLab 完全启动...${NC}"
|
||||
until curl -f -s "$GITLAB_URL/-/health" > /dev/null; do
|
||||
echo "GitLab 正在启动中..."
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo -e "${GREEN}GitLab 已启动并可用${NC}"
|
||||
|
||||
# 获取 GitLab API token
|
||||
echo -e "${YELLOW}获取 GitLab API token...${NC}"
|
||||
PRIVATE_TOKEN=$(curl -s -X POST "$GITLAB_URL/api/v4/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"login\":\"$GITLAB_ADMIN_USER\",\"password\":\"$GITLAB_ADMIN_PASSWORD\"}" | \
|
||||
jq -r '.private_token')
|
||||
|
||||
if [ "$PRIVATE_TOKEN" = "null" ] || [ -z "$PRIVATE_TOKEN" ]; then
|
||||
echo -e "${RED}错误: 无法获取 API token${NC}"
|
||||
echo "请检查 GitLab 管理员凭据"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 查找项目
|
||||
echo -e "${YELLOW}查找项目: $PROJECT_NAME${NC}"
|
||||
PROJECT_INFO=$(curl -s "$GITLAB_URL/api/v4/projects?search=$PROJECT_NAME" \
|
||||
-H "Private-Token: $PRIVATE_TOKEN" | \
|
||||
jq ".[] | select(.path_with_namespace | contains(\"$PROJECT_NAME\"))")
|
||||
|
||||
if [ -z "$PROJECT_INFO" ]; then
|
||||
echo -e "${RED}错误: 未找到项目 '$PROJECT_NAME'${NC}"
|
||||
echo "请确保项目已存在于 GitLab 中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROJECT_ID=$(echo "$PROJECT_INFO" | jq -r '.id')
|
||||
PROJECT_PATH=$(echo "$PROJECT_INFO" | jq -r '.path_with_namespace')
|
||||
|
||||
echo -e "${GREEN}找到项目: $PROJECT_PATH (ID: $PROJECT_ID)${NC}"
|
||||
|
||||
# 环境变量配置
|
||||
echo -e "${YELLOW}配置 CI/CD 环境变量...${NC}"
|
||||
|
||||
# 基础环境变量
|
||||
VARS=(
|
||||
"NODE_VERSION|18|Node.js 版本"
|
||||
"PYTHON_VERSION|3.11|Python 版本"
|
||||
"CI_DEBUG_TRACE|false|启用调试日志"
|
||||
)
|
||||
|
||||
# 部署相关环境变量
|
||||
if [ "$ENV_TYPE" = "prod" ]; then
|
||||
VARS+=(
|
||||
"DEPLOY_ENV|production|部署环境"
|
||||
"ENVIRONMENT_NAME|production|环境名称"
|
||||
)
|
||||
else
|
||||
VARS+=(
|
||||
"DEPLOY_ENV|development|部署环境"
|
||||
"ENVIRONMENT_NAME|development|环境名称"
|
||||
)
|
||||
fi
|
||||
|
||||
# 数据库配置 (示例)
|
||||
VARS+=(
|
||||
"POSTGRES_DB|${PROJECT_NAME}_db|数据库名称"
|
||||
"POSTGRES_USER|${PROJECT_NAME}_user|数据库用户"
|
||||
"REDIS_URL|redis://redis:6379|Redis 连接"
|
||||
)
|
||||
|
||||
# 为每个变量创建或更新
|
||||
for var in "${VARS[@]}"; do
|
||||
IFS='|' read -r key value description <<< "$var"
|
||||
|
||||
echo -e "${BLUE}设置变量: $key${NC}"
|
||||
echo -e "${BLUE}描述: $description${NC}"
|
||||
echo -e "${BLUE}值: $value${NC}"
|
||||
|
||||
# 检查变量是否已存在
|
||||
existing_var=$(curl -s "$GITLAB_URL/api/v4/projects/$PROJECT_ID/variables/$key" \
|
||||
-H "Private-Token: $PRIVATE_TOKEN" || echo "")
|
||||
|
||||
if [ -n "$existing_var" ]; then
|
||||
# 更新现有变量
|
||||
result=$(curl -s -X PUT "$GITLAB_URL/api/v4/projects/$PROJECT_ID/variables/$key" \
|
||||
-H "Private-Token: $PRIVATE_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"value\":\"$value\",\"description\":\"$description\"}")
|
||||
else
|
||||
# 创建新变量
|
||||
result=$(curl -s -X POST "$GITLAB_URL/api/v4/projects/$PROJECT_ID/variables" \
|
||||
-H "Private-Token: $PRIVATE_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"key\":\"$key\",\"value\":\"$value\",\"description\":\"$description\"}")
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ 变量设置成功${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ 变量设置失败${NC}"
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
# 提示用户配置敏感变量
|
||||
echo -e "${YELLOW}需要手动配置的敏感变量:${NC}"
|
||||
echo "=================================="
|
||||
echo "1. SSH_PRIVATE_KEY - 部署服务器 SSH 私钥"
|
||||
echo "2. DEPLOY_SERVER - 部署服务器地址"
|
||||
echo "3. DEPLOY_USER - 部署服务器用户名"
|
||||
echo "4. DATABASE_PASSWORD - 数据库密码"
|
||||
echo ""
|
||||
echo -e "${BLUE}配置方法:${NC}"
|
||||
echo "1. 访问 $GITLAB_URL"
|
||||
echo "2. 进入项目: $PROJECT_PATH"
|
||||
echo "3. Settings -> CI/CD -> Variables"
|
||||
echo "4. 添加上述敏感变量,选择 'Protected' 和 'Masked'"
|
||||
echo ""
|
||||
|
||||
# 创建示例 .gitlab-ci.yml 文件
|
||||
echo -e "${YELLOW}创建示例 CI/CD 配置文件...${NC}"
|
||||
cat > /tmp/.gitlab-ci.yml << 'EOF'
|
||||
# 使用 stock 项目模板
|
||||
include:
|
||||
- local: 'gitlab/ci-templates/.gitlab-ci.yml.simple'
|
||||
|
||||
# 或者直接使用简化配置
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
NODE_VERSION: "18"
|
||||
IMAGE_TAG: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
|
||||
|
||||
test:
|
||||
stage: test
|
||||
image: node:$NODE_VERSION-alpine
|
||||
script:
|
||||
- echo "运行测试..."
|
||||
- npm install
|
||||
- npm test
|
||||
coverage: '/Total coverage: \d+\.\d+%/'
|
||||
artifacts:
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage/cobertura-coverage.xml
|
||||
|
||||
build:
|
||||
stage: build
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- docker build -t $IMAGE_TAG .
|
||||
- docker push $IMAGE_TAG
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
script:
|
||||
- echo "部署到 $DEPLOY_ENV 环境"
|
||||
- echo "镜像: $IMAGE_TAG"
|
||||
environment:
|
||||
name: $ENVIRONMENT_NAME
|
||||
when: manual
|
||||
only:
|
||||
- main
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}示例配置文件已创建: /tmp/.gitlab-ci.yml${NC}"
|
||||
echo ""
|
||||
|
||||
# 显示下一步操作
|
||||
echo -e "${GREEN}环境变量配置完成!${NC}"
|
||||
echo "=================================="
|
||||
echo -e "${BLUE}下一步操作:${NC}"
|
||||
echo "1. 复制示例配置文件到项目根目录:"
|
||||
echo " cp /tmp/.gitlab-ci.yml /path/to/your/project/"
|
||||
echo ""
|
||||
echo "2. 推送代码到 GitLab:"
|
||||
echo " git add .gitlab-ci.yml"
|
||||
echo " git commit -m 'Add CI/CD configuration'"
|
||||
echo " git push origin main"
|
||||
echo ""
|
||||
echo "3. 在 GitLab UI 中配置敏感变量"
|
||||
echo "4. 等待流水线自动运行"
|
||||
echo ""
|
||||
echo -e "${BLUE}查看流水线:${NC}"
|
||||
echo "$GITLAB_URL/$PROJECT_PATH/-/pipelines"
|
||||
@@ -0,0 +1,40 @@
|
||||
# Harbor 环境变量配置
|
||||
# 复制此文件为 .env 并根据需要修改配置
|
||||
|
||||
# Harbor 基本配置
|
||||
HARBOR_DOMAIN=192.168.1.83
|
||||
HARBOR_HTTP_PORT=8080
|
||||
HARBOR_HTTPS_PORT=8443
|
||||
|
||||
# Harbor 管理员密码
|
||||
HARBOR_ADMIN_PASSWORD=admin
|
||||
|
||||
# 数据目录配置
|
||||
HARBOR_DATA_DIR=~/ops/data/harbor
|
||||
HARBOR_CERT_DIR=~/ops/harbor/certs
|
||||
|
||||
# 备份配置
|
||||
HARBOR_BACKUP_DIR=~/ops/backups/harbor
|
||||
HARBOR_BACKUP_RETENTION_DAYS=30
|
||||
HARBOR_BACKUP_INTERVAL_HOURS=12
|
||||
|
||||
# 日志配置
|
||||
HARBOR_LOG_DIR=~/ops/logs
|
||||
|
||||
# 数据库配置
|
||||
HARBOR_DB_PASSWORD=root123
|
||||
HARBOR_DB_MAX_IDLE_CONNS=100
|
||||
HARBOR_DB_MAX_OPEN_CONNS=900
|
||||
|
||||
# Redis 配置
|
||||
HARBOR_REDIS_HOST=redis
|
||||
HARBOR_REDIS_PORT=6379
|
||||
|
||||
# 证书配置
|
||||
HARBOR_SSL_CERT=/Users/brunogao/certs/harbor.lan.pem
|
||||
HARBOR_SSL_KEY=/Users/brunogao/certs/harbor.lan-key.pem
|
||||
|
||||
# 代理配置 (如果需要)
|
||||
# HTTP_PROXY=
|
||||
# HTTPS_PROXY=
|
||||
# NO_PROXY=localhost,127.0.0.1
|
||||
@@ -0,0 +1,374 @@
|
||||
# Harbor 维护模块
|
||||
|
||||
## 概述
|
||||
|
||||
这是 macOS 工具集中的 Harbor 维护模块,提供完整的 Harbor 容器镜像仓库管理解决方案,包括服务部署、自动备份、健康监控和一键恢复功能。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ **一键部署**: Docker Compose 快速部署 Harbor 服务
|
||||
- ✅ **自动备份**: 双重定时任务保障 (cron + launchd)
|
||||
- ✅ **安全恢复**: 支持一键恢复和安全回滚
|
||||
- ✅ **健康监控**: 实时监控服务状态和数据完整性
|
||||
- ✅ **数据迁移**: 支持从现有 Harbor 无损迁移
|
||||
- ✅ **macOS 集成**: 原生支持 macOS 系统特性
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
harbor/
|
||||
├── harbor.yml # Harbor 配置文件
|
||||
├── docker-compose.yml # Docker 服务配置
|
||||
├── harbor-data-protection.sh # 主管理脚本
|
||||
├── harbor-backup.sh # 快速备份脚本
|
||||
├── harbor-restore.sh # 快速恢复脚本
|
||||
├── common/ # Harbor 通用配置
|
||||
└── README.md # 本文档
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 环境准备
|
||||
|
||||
确保系统已安装:
|
||||
- Docker Desktop for Mac
|
||||
- Git (用于版本控制)
|
||||
|
||||
### 2. 初始化设置
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
cd /path/to/macos/harbor
|
||||
|
||||
# 复制环境配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 根据需要修改配置(可选)
|
||||
nano .env
|
||||
|
||||
# 初始化设置(自动配置定时任务等)
|
||||
./harbor-data-protection.sh setup
|
||||
```
|
||||
|
||||
### 3. 启动服务
|
||||
|
||||
```bash
|
||||
# 启动 Harbor 服务
|
||||
./harbor-data-protection.sh start
|
||||
|
||||
# 检查服务状态
|
||||
./harbor-data-protection.sh health
|
||||
```
|
||||
|
||||
### 4. 访问 Harbor
|
||||
|
||||
- **Web 界面**: http://192.168.1.83:8080
|
||||
- **Registry API**: http://192.168.1.83:8080/api/v2.0/
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 服务管理
|
||||
|
||||
```bash
|
||||
# 启动服务
|
||||
./harbor-data-protection.sh start
|
||||
|
||||
# 停止服务
|
||||
./harbor-data-protection.sh stop
|
||||
|
||||
# 重启服务
|
||||
./harbor-data-protection.sh restart
|
||||
|
||||
# 健康检查
|
||||
./harbor-data-protection.sh health
|
||||
|
||||
# 查看统计信息
|
||||
./harbor-data-protection.sh stats
|
||||
```
|
||||
|
||||
### 备份操作
|
||||
|
||||
```bash
|
||||
# 手动备份(自动命名)
|
||||
./harbor-backup.sh
|
||||
|
||||
# 手动备份(指定名称)
|
||||
./harbor-backup.sh my-backup-20231019
|
||||
|
||||
# 查看备份文件
|
||||
ls -la ~/ops/backups/harbor/
|
||||
```
|
||||
|
||||
### 恢复操作
|
||||
|
||||
```bash
|
||||
# 查看可用备份
|
||||
./harbor-restore.sh
|
||||
|
||||
# 从指定备份恢复
|
||||
./harbor-restore.sh harbor-20231019-120000.tar.gz
|
||||
```
|
||||
|
||||
### 高级操作
|
||||
|
||||
```bash
|
||||
# 完整功能菜单
|
||||
./harbor-data-protection.sh help
|
||||
|
||||
# 重新初始化设置
|
||||
./harbor-data-protection.sh setup
|
||||
|
||||
# 查看统计信息
|
||||
./harbor-data-protection.sh stats
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
### 环境变量 (.env)
|
||||
|
||||
| 变量名 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `HARBOR_DOMAIN` | 192.168.1.83 | Harbor 服务器域名 |
|
||||
| `HARBOR_HTTP_PORT` | 8080 | HTTP 端口 |
|
||||
| `HARBOR_HTTPS_PORT` | 8443 | HTTPS 端口 |
|
||||
| `HARBOR_ADMIN_PASSWORD` | admin | 管理员密码 |
|
||||
| `HARBOR_DATA_DIR` | ~/ops/data/harbor | Harbor 数据目录 |
|
||||
| `HARBOR_BACKUP_DIR` | ~/ops/backups/harbor | 备份存储目录 |
|
||||
| `HARBOR_BACKUP_RETENTION_DAYS` | 30 | 备份保留天数 |
|
||||
| `HARBOR_BACKUP_INTERVAL_HOURS` | 12 | 自动备份间隔(小时) |
|
||||
|
||||
### Harbor 配置 (harbor.yml)
|
||||
|
||||
主要配置项:
|
||||
- `hostname`: Harbor 服务器地址
|
||||
- `http.port`: HTTP 服务端口
|
||||
- `https.port`: HTTPS 服务端口
|
||||
- `harbor_admin_password`: 管理员密码
|
||||
- `data_volume`: 数据存储路径
|
||||
|
||||
## 迁移说明
|
||||
|
||||
### 从现有 Harbor 迁移
|
||||
|
||||
如果已经有运行的 Harbor 实例,可以按照以下步骤无损迁移:
|
||||
|
||||
1. **备份现有数据**
|
||||
```bash
|
||||
# 停止现有服务
|
||||
cd ~/harbor/harbor && docker-compose down
|
||||
|
||||
# 备份数据目录
|
||||
tar -czf harbor-backup-$(date +%Y%m%d-%H%M%S).tar.gz ~/harbor-data
|
||||
```
|
||||
|
||||
2. **使用新模块**
|
||||
```bash
|
||||
# 部署新模块
|
||||
./init-ops.sh
|
||||
|
||||
# 恢复数据
|
||||
./harbor-restore.sh harbor-backup-*.tar.gz
|
||||
```
|
||||
|
||||
3. **验证迁移结果**
|
||||
```bash
|
||||
# 检查服务状态
|
||||
./harbor-data-protection.sh health
|
||||
|
||||
# 验证镜像数量
|
||||
./harbor-data-protection.sh stats
|
||||
```
|
||||
|
||||
## 备份机制
|
||||
|
||||
### 自动备份
|
||||
|
||||
系统提供双重保障的自动备份:
|
||||
|
||||
1. **Cron 任务**: 传统 Unix 定时任务
|
||||
2. **Launchd 任务**: macOS 原生定时任务
|
||||
|
||||
默认每 12 小时自动备份一次,保留 30 天的备份文件。
|
||||
|
||||
### 备份内容
|
||||
|
||||
- Harbor 配置文件 (harbor.yml)
|
||||
- Docker Compose 配置
|
||||
- Harbor 数据目录 (包括镜像数据、数据库等)
|
||||
- 通用配置目录
|
||||
|
||||
### 备份位置
|
||||
|
||||
```
|
||||
~/ops/backups/harbor/
|
||||
├── harbor-20231019-120000.tar.gz # 备份文件
|
||||
├── harbor-20231019-120000.tar.gz.meta # 备份元数据
|
||||
└── safety-backup-*.tar.gz # 恢复时的安全备份
|
||||
```
|
||||
|
||||
## 恢复机制
|
||||
|
||||
### 安全恢复流程
|
||||
|
||||
1. **停止服务**: 安全停止所有 Harbor 服务
|
||||
2. **安全备份**: 自动创建当前状态的安全备份
|
||||
3. **数据恢复**: 从指定备份恢复数据
|
||||
4. **服务启动**: 重启服务并验证状态
|
||||
5. **完整性检查**: 验证数据完整性
|
||||
|
||||
### 恢回滚
|
||||
|
||||
如果恢复出现问题,可以使用安全备份回滚:
|
||||
|
||||
```bash
|
||||
./harbor-restore.sh safety-backup-20231019-130000.tar.gz
|
||||
```
|
||||
|
||||
## 监控和日志
|
||||
|
||||
### 健康检查内容
|
||||
|
||||
- Docker 环境状态
|
||||
- Harbor 各服务运行状态
|
||||
- 数据卷完整性
|
||||
- 镜像仓库数量统计
|
||||
- 备份状态检查
|
||||
- 定时任务状态
|
||||
|
||||
### 日志文件位置
|
||||
|
||||
```
|
||||
~/ops/logs/
|
||||
├── harbor-protection.log # 主脚本日志
|
||||
├── harbor-backup_stdout.log # 备份输出日志
|
||||
└── harbor-backup_stderr.log # 备份错误日志
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# 查看主日志
|
||||
tail -f ~/ops/logs/harbor-protection.log
|
||||
|
||||
# 查看定时任务日志
|
||||
tail -f ~/ops/logs/harbor-backup_*.log
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **Docker 服务未启动**
|
||||
```bash
|
||||
# 启动 Docker Desktop
|
||||
open /Applications/Docker.app
|
||||
```
|
||||
|
||||
2. **端口冲突**
|
||||
```bash
|
||||
# 检查端口占用
|
||||
lsof -i :8080
|
||||
lsof -i :8443
|
||||
```
|
||||
|
||||
3. **权限问题**
|
||||
```bash
|
||||
# 设置脚本权限
|
||||
chmod +x harbor-*.sh
|
||||
```
|
||||
|
||||
4. **定时任务未执行**
|
||||
```bash
|
||||
# 检查 launchd 任务
|
||||
launchctl list | grep harbor
|
||||
|
||||
# 检查 cron 任务
|
||||
crontab -l | grep harbor
|
||||
```
|
||||
|
||||
### 手动恢复定时任务
|
||||
|
||||
```bash
|
||||
# 重新加载 launchd 任务
|
||||
launchctl unload ~/Library/LaunchAgents/com.ljwx.harbor.backup.plist 2>/dev/null || true
|
||||
launchctl load -w ~/Library/LaunchAgents/com.ljwx.harbor.backup.plist
|
||||
|
||||
# 重新设置 cron 任务
|
||||
./harbor-data-protection.sh setup
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 备份优化
|
||||
|
||||
- 调整备份频率:修改 `HARBOR_BACKUP_INTERVAL_HOURS`
|
||||
- 调整保留策略:修改 `HARBOR_BACKUP_RETENTION_DAYS`
|
||||
- 使用外部存储:修改 `HARBOR_BACKUP_DIR` 到外部磁盘
|
||||
|
||||
### 服务优化
|
||||
|
||||
- 调整 Docker 资源限制
|
||||
- 使用外部数据库(PostgreSQL)
|
||||
- 配置 CDN 或反向代理
|
||||
- 优化存储性能
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **定期备份**: 确保自动备份正常运行
|
||||
2. **异地备份**: 将重要备份同步到云存储
|
||||
3. **访问控制**: 配置防火墙规则限制访问
|
||||
4. **定期更新**: 定期更新 Harbor 版本
|
||||
5. **监控告警**: 配置服务状态监控
|
||||
6. **SSL 证书**: 使用有效的 SSL 证书
|
||||
|
||||
## 升级指南
|
||||
|
||||
### Harbor 版本升级
|
||||
|
||||
```bash
|
||||
# 1. 备份当前数据
|
||||
./harbor-backup.sh pre-upgrade-$(date +%Y%m%d)
|
||||
|
||||
# 2. 停止服务
|
||||
./harbor-data-protection.sh stop
|
||||
|
||||
# 3. 更新镜像版本
|
||||
# 编辑 harbor.yml 或 docker-compose.yml,修改镜像标签
|
||||
|
||||
# 4. 启动服务
|
||||
./harbor-data-protection.sh start
|
||||
|
||||
# 5. 验证升级
|
||||
./harbor-data-protection.sh health
|
||||
```
|
||||
|
||||
## 集成说明
|
||||
|
||||
### 与 CI/CD 集成
|
||||
|
||||
```bash
|
||||
# CI 脚本示例
|
||||
./harbor-backup.sh ci-pre-build-$(BUILD_NUMBER)
|
||||
# 执行构建任务
|
||||
./harbor-restore.sh ci-pre-build-$(BUILD_NUMBER).tar.gz
|
||||
```
|
||||
|
||||
### 与监控系统集成
|
||||
|
||||
```bash
|
||||
# 健康检查 API 调用
|
||||
./harbor-data-protection.sh health
|
||||
echo $?
|
||||
```
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License - 可自由使用和修改
|
||||
|
||||
## 支持
|
||||
|
||||
如有问题或建议,请通过以下方式联系:
|
||||
|
||||
1. 查看日志文件排查问题
|
||||
2. 检查 GitHub Issues
|
||||
3. 提交新的 Issue 或 Pull Request
|
||||
@@ -0,0 +1,6 @@
|
||||
appname = Harbor
|
||||
runmode = prod
|
||||
enablegzip = true
|
||||
|
||||
[prod]
|
||||
httpport = 8080
|
||||
@@ -0,0 +1,51 @@
|
||||
CONFIG_PATH=/etc/core/app.conf
|
||||
UAA_CA_ROOT=/etc/core/certificates/uaa_ca.pem
|
||||
_REDIS_URL_CORE=redis://redis:6379?idle_timeout_seconds=30
|
||||
SYNC_QUOTA=true
|
||||
_REDIS_URL_REG=redis://redis:6379/1?idle_timeout_seconds=30
|
||||
|
||||
LOG_LEVEL=info
|
||||
EXT_ENDPOINT=https://192.168.1.83:8443
|
||||
DATABASE_TYPE=postgresql
|
||||
POSTGRESQL_HOST=postgresql
|
||||
POSTGRESQL_PORT=5432
|
||||
POSTGRESQL_USERNAME=postgres
|
||||
POSTGRESQL_PASSWORD=root123
|
||||
POSTGRESQL_DATABASE=registry
|
||||
POSTGRESQL_SSLMODE=disable
|
||||
POSTGRESQL_MAX_IDLE_CONNS=100
|
||||
POSTGRESQL_MAX_OPEN_CONNS=900
|
||||
POSTGRESQL_CONN_MAX_LIFETIME=5m
|
||||
POSTGRESQL_CONN_MAX_IDLE_TIME=0
|
||||
REGISTRY_URL=http://registry:5000
|
||||
PORTAL_URL=http://portal:8080
|
||||
TOKEN_SERVICE_URL=http://core:8080/service/token
|
||||
HARBOR_ADMIN_PASSWORD=admin
|
||||
MAX_JOB_WORKERS=10
|
||||
CORE_SECRET=evrhBggzCUD4nZrP
|
||||
JOBSERVICE_SECRET=Fz2ZivOojMGv0pN9
|
||||
WITH_TRIVY=False
|
||||
CORE_URL=http://core:8080
|
||||
CORE_LOCAL_URL=http://127.0.0.1:8080
|
||||
JOBSERVICE_URL=http://jobservice:8080
|
||||
TRIVY_ADAPTER_URL=http://trivy-adapter:8080
|
||||
REGISTRY_STORAGE_PROVIDER_NAME=filesystem
|
||||
READ_ONLY=false
|
||||
RELOAD_KEY=
|
||||
REGISTRY_CONTROLLER_URL=http://registryctl:8080
|
||||
REGISTRY_CREDENTIAL_USERNAME=harbor_registry_user
|
||||
REGISTRY_CREDENTIAL_PASSWORD=0k8vBxdZcBoL7eYFjJiD96WzKGpIf7XN
|
||||
CSRF_KEY=r7triBX5KUTSc8AQRzt8Zp3AdntdIs8j
|
||||
ROBOT_SCANNER_NAME_PREFIX=8tzoAVCZ
|
||||
PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE=docker-hub,harbor,azure-acr,aws-ecr,google-gcr,quay,docker-registry,github-ghcr,jfrog-artifactory
|
||||
|
||||
HTTP_PROXY=
|
||||
HTTPS_PROXY=
|
||||
NO_PROXY=.local,.internal,127.0.0.1,localhost,core,trivy-adapter,portal,registry,registryctl,nginx,jobservice,log,redis,postgresql,db,exporter
|
||||
|
||||
PORT=8080
|
||||
|
||||
|
||||
|
||||
|
||||
QUOTA_UPDATE_PROVIDER=db
|
||||
@@ -0,0 +1 @@
|
||||
POSTGRES_PASSWORD=root123
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
#Protocol used to serve
|
||||
protocol: "http"
|
||||
|
||||
#Server listening port
|
||||
port: 8080
|
||||
|
||||
#Worker pool
|
||||
worker_pool:
|
||||
#Worker concurrency
|
||||
workers: 10
|
||||
backend: "redis"
|
||||
#Additional config if use 'redis' backend
|
||||
redis_pool:
|
||||
#redis://[arbitrary_username:password@]ipaddress:port/database_index
|
||||
redis_url: redis://redis:6379/2?idle_timeout_seconds=30
|
||||
namespace: "harbor_job_service_namespace"
|
||||
idle_timeout_second: 3600
|
||||
#Loggers for the running job
|
||||
job_loggers:
|
||||
# The jobLoggers backend name, only support "STD_OUTPUT", "FILE" and/or "DB"
|
||||
- name: "STD_OUTPUT"
|
||||
level: "INFO" # INFO/DEBUG/WARNING/ERROR/FATAL
|
||||
- name: "FILE"
|
||||
level: "INFO"
|
||||
settings: # Customized settings of logger
|
||||
base_dir: "/var/log/jobs"
|
||||
sweeper:
|
||||
duration: 1 #days
|
||||
settings: # Customized settings of sweeper
|
||||
work_dir: "/var/log/jobs"
|
||||
|
||||
#Loggers for the job service
|
||||
loggers:
|
||||
- name: "STD_OUTPUT" # Same with above
|
||||
level: "INFO"
|
||||
|
||||
|
||||
reaper:
|
||||
# the max time to wait for a task to finish, if unfinished after max_update_hours, the task will be mark as error, but the task will continue to run, default value is 24,
|
||||
max_update_hours: 24
|
||||
# the max time for execution in running state without new task created
|
||||
max_dangling_hours: 168
|
||||
|
||||
# the max size of job log returned by API, default is 10M
|
||||
max_retrieve_size_mb: 10
|
||||
@@ -0,0 +1,17 @@
|
||||
CORE_SECRET=evrhBggzCUD4nZrP
|
||||
REGISTRY_URL=http://registry:5000
|
||||
JOBSERVICE_SECRET=Fz2ZivOojMGv0pN9
|
||||
CORE_URL=http://core:8080
|
||||
REGISTRY_CONTROLLER_URL=http://registryctl:8080
|
||||
JOBSERVICE_WEBHOOK_JOB_MAX_RETRY=3
|
||||
JOBSERVICE_WEBHOOK_JOB_HTTP_CLIENT_TIMEOUT=3
|
||||
|
||||
|
||||
HTTP_PROXY=
|
||||
HTTPS_PROXY=
|
||||
NO_PROXY=.local,.internal,127.0.0.1,localhost,core,trivy-adapter,portal,registry,registryctl,nginx,jobservice,log,redis,postgresql,db,exporter
|
||||
REGISTRY_CREDENTIAL_USERNAME=harbor_registry_user
|
||||
REGISTRY_CREDENTIAL_PASSWORD=0k8vBxdZcBoL7eYFjJiD96WzKGpIf7XN
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/var/log/docker/*.log {
|
||||
rotate 50
|
||||
size 200M
|
||||
copytruncate
|
||||
compress
|
||||
missingok
|
||||
nodateext
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# Rsyslog configuration file for docker.
|
||||
|
||||
template(name="DynaFile" type="string" string="/var/log/docker/%programname%.log")
|
||||
|
||||
if $programname != "rsyslogd" then {
|
||||
action(type="omfile" dynaFile="DynaFile")
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
worker_processes auto;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 3096;
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
client_body_temp_path /tmp/client_body_temp;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
tcp_nodelay on;
|
||||
include /etc/nginx/conf.d/*.upstream.conf;
|
||||
|
||||
# this is necessary for us to be able to disable request buffering in all cases
|
||||
proxy_http_version 1.1;
|
||||
|
||||
upstream core {
|
||||
server core:8080;
|
||||
}
|
||||
|
||||
upstream portal {
|
||||
server portal:8080;
|
||||
}
|
||||
|
||||
log_format timed_combined '$remote_addr - '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" '
|
||||
'$request_time $upstream_response_time $pipe';
|
||||
|
||||
access_log /dev/stdout timed_combined;
|
||||
|
||||
map $http_x_forwarded_proto $x_forwarded_proto {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/*.server.conf;
|
||||
|
||||
server {
|
||||
listen 8443 ssl;
|
||||
# server_name harbordomain.com;
|
||||
server_tokens off;
|
||||
# SSL
|
||||
ssl_certificate /etc/cert/server.crt;
|
||||
ssl_certificate_key /etc/cert/server.key;
|
||||
|
||||
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
|
||||
# disable any limits to avoid HTTP 413 for large image uploads
|
||||
client_max_body_size 0;
|
||||
|
||||
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
|
||||
chunked_transfer_encoding on;
|
||||
|
||||
# Add extra headers
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header Content-Security-Policy "frame-ancestors 'none'";
|
||||
|
||||
# customized location config file can place to /etc/nginx dir with prefix harbor.https. and suffix .conf
|
||||
include /etc/nginx/conf.d/harbor.https.*.conf;
|
||||
|
||||
location / {
|
||||
proxy_pass http://portal/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
|
||||
|
||||
proxy_cookie_path / "/; HttpOnly; Secure";
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /c/ {
|
||||
proxy_pass http://core/c/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
|
||||
|
||||
proxy_cookie_path / "/; Secure";
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://core/api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
|
||||
|
||||
proxy_cookie_path / "/; Secure";
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /v1/ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location /v2/ {
|
||||
proxy_pass http://core/v2/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
proxy_send_timeout 900;
|
||||
proxy_read_timeout 900;
|
||||
}
|
||||
|
||||
location /service/ {
|
||||
proxy_pass http://core/service/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
|
||||
|
||||
proxy_cookie_path / "/; Secure";
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /service/notifications {
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
server {
|
||||
listen 8080;
|
||||
#server_name harbordomain.com;
|
||||
return 308 https://$host:8443$request_uri;
|
||||
}
|
||||
|
||||
# Additional HTTP server on port 8081 for users who accidentally use HTTP on port 8443
|
||||
server {
|
||||
listen 8081;
|
||||
#server_name harbordomain.com;
|
||||
return 308 https://$host:8443$request_uri;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
worker_processes auto;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
|
||||
client_body_temp_path /tmp/client_body_temp;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1000;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
location /devcenter-api-2.0 {
|
||||
try_files $uri $uri/ /swagger-ui-index.html;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
version: 0.1
|
||||
log:
|
||||
level: info
|
||||
fields:
|
||||
service: registry
|
||||
storage:
|
||||
cache:
|
||||
layerinfo: redis
|
||||
filesystem:
|
||||
rootdirectory: /storage
|
||||
maintenance:
|
||||
uploadpurging:
|
||||
enabled: true
|
||||
age: 168h
|
||||
interval: 24h
|
||||
dryrun: false
|
||||
delete:
|
||||
enabled: true
|
||||
redis:
|
||||
addr: redis:6379
|
||||
readtimeout: 10s
|
||||
writetimeout: 10s
|
||||
dialtimeout: 10s
|
||||
password:
|
||||
db: 1
|
||||
pool:
|
||||
maxidle: 100
|
||||
maxactive: 500
|
||||
idletimeout: 60s
|
||||
http:
|
||||
addr: :5000
|
||||
secret: placeholder
|
||||
debug:
|
||||
addr: localhost:5001
|
||||
auth:
|
||||
htpasswd:
|
||||
realm: harbor-registry-basic-realm
|
||||
path: /etc/registry/passwd
|
||||
validation:
|
||||
disabled: true
|
||||
compatibility:
|
||||
schema1:
|
||||
enabled: true
|
||||
@@ -0,0 +1 @@
|
||||
harbor_registry_user:$2y$05$qpjbQSEnJNUHPgMZxjzE2.dbLI.bsnkpjSpJdu2J.1S24ZVF585zS
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
protocol: "http"
|
||||
port: 8080
|
||||
log_level: info
|
||||
registry_config: "/etc/registry/config.yml"
|
||||
@@ -0,0 +1,2 @@
|
||||
CORE_SECRET=evrhBggzCUD4nZrP
|
||||
JOBSERVICE_SECRET=Fz2ZivOojMGv0pN9
|
||||
@@ -0,0 +1,258 @@
|
||||
version: '2.3'
|
||||
services:
|
||||
log:
|
||||
image: goharbor/harbor-log:v2.11.1
|
||||
container_name: harbor-log
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /var/log/harbor/:/var/log/docker/:z
|
||||
- type: bind
|
||||
source: ./common/config/log/logrotate.conf
|
||||
target: /etc/logrotate.d/logrotate.conf
|
||||
- type: bind
|
||||
source: ./common/config/log/rsyslog_docker.conf
|
||||
target: /etc/rsyslog.d/rsyslog_docker.conf
|
||||
ports:
|
||||
- 127.0.0.1:1514:10514
|
||||
networks:
|
||||
- harbor
|
||||
registry:
|
||||
image: goharbor/registry-photon:v2.11.1
|
||||
container_name: registry
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /Users/brunogao/ops/data/harbor/registry:/storage:z
|
||||
- ./common/config/registry/:/etc/registry/:z
|
||||
- type: bind
|
||||
source: /Users/brunogao/ops/data/harbor/secret/registry/root.crt
|
||||
target: /etc/registry/root.crt
|
||||
- type: bind
|
||||
source: ./common/config/shared/trust-certificates
|
||||
target: /harbor_cust_cert
|
||||
networks:
|
||||
- harbor
|
||||
depends_on:
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "registry"
|
||||
registryctl:
|
||||
image: goharbor/harbor-registryctl:v2.11.1
|
||||
container_name: registryctl
|
||||
env_file:
|
||||
- ./common/config/registryctl/env
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /Users/brunogao/ops/data/harbor/registry:/storage:z
|
||||
- ./common/config/registry/:/etc/registry/:z
|
||||
- type: bind
|
||||
source: ./common/config/registryctl/config.yml
|
||||
target: /etc/registryctl/config.yml
|
||||
- type: bind
|
||||
source: ./common/config/shared/trust-certificates
|
||||
target: /harbor_cust_cert
|
||||
networks:
|
||||
- harbor
|
||||
depends_on:
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "registryctl"
|
||||
postgresql:
|
||||
image: goharbor/harbor-db:v2.11.1
|
||||
container_name: harbor-db
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /Users/brunogao/ops/data/harbor/database:/var/lib/postgresql/data:z
|
||||
networks:
|
||||
harbor:
|
||||
env_file:
|
||||
- ./common/config/db/env
|
||||
depends_on:
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "postgresql"
|
||||
shm_size: '1gb'
|
||||
core:
|
||||
image: goharbor/harbor-core:v2.11.1
|
||||
container_name: harbor-core
|
||||
env_file:
|
||||
- ./common/config/core/env
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /Users/brunogao/ops/data/harbor/ca_download/:/etc/core/ca/:z
|
||||
- /Users/brunogao/ops/data/harbor/:/data/:z
|
||||
- ./common/config/core/certificates/:/etc/core/certificates/:z
|
||||
- type: bind
|
||||
source: ./common/config/core/app.conf
|
||||
target: /etc/core/app.conf
|
||||
- type: bind
|
||||
source: /Users/brunogao/ops/data/harbor/secret/core/private_key.pem
|
||||
target: /etc/core/private_key.pem
|
||||
- type: bind
|
||||
source: /Users/brunogao/ops/data/harbor/secret/keys/secretkey
|
||||
target: /etc/core/key
|
||||
- type: bind
|
||||
source: ./common/config/shared/trust-certificates
|
||||
target: /harbor_cust_cert
|
||||
networks:
|
||||
harbor:
|
||||
depends_on:
|
||||
- log
|
||||
- registry
|
||||
- redis
|
||||
- postgresql
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "core"
|
||||
portal:
|
||||
image: goharbor/harbor-portal:v2.11.1
|
||||
container_name: harbor-portal
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
- SETUID
|
||||
- NET_BIND_SERVICE
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./common/config/portal/nginx.conf
|
||||
target: /etc/nginx/nginx.conf
|
||||
networks:
|
||||
- harbor
|
||||
depends_on:
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "portal"
|
||||
|
||||
jobservice:
|
||||
image: goharbor/harbor-jobservice:v2.11.1
|
||||
container_name: harbor-jobservice
|
||||
env_file:
|
||||
- ./common/config/jobservice/env
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /Users/brunogao/ops/data/harbor/job_logs:/var/log/jobs:z
|
||||
- type: bind
|
||||
source: ./common/config/jobservice/config.yml
|
||||
target: /etc/jobservice/config.yml
|
||||
- type: bind
|
||||
source: ./common/config/shared/trust-certificates
|
||||
target: /harbor_cust_cert
|
||||
networks:
|
||||
- harbor
|
||||
depends_on:
|
||||
- core
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "jobservice"
|
||||
redis:
|
||||
image: goharbor/redis-photon:v2.11.1
|
||||
container_name: redis
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
- SETUID
|
||||
volumes:
|
||||
- /Users/brunogao/ops/data/harbor/redis:/var/lib/redis
|
||||
networks:
|
||||
harbor:
|
||||
depends_on:
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "redis"
|
||||
proxy:
|
||||
image: goharbor/nginx-photon:v2.11.1
|
||||
container_name: nginx
|
||||
restart: always
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
- SETUID
|
||||
- NET_BIND_SERVICE
|
||||
volumes:
|
||||
- ./common/config/nginx:/etc/nginx:z
|
||||
- /Users/brunogao/ops/data/harbor/secret/cert:/etc/cert:z
|
||||
- type: bind
|
||||
source: ./common/config/shared/trust-certificates
|
||||
target: /harbor_cust_cert
|
||||
networks:
|
||||
- harbor
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 8081:8081
|
||||
- 8443:8443
|
||||
depends_on:
|
||||
- registry
|
||||
- core
|
||||
- portal
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://localhost:1514"
|
||||
tag: "proxy"
|
||||
networks:
|
||||
harbor:
|
||||
external: false
|
||||
@@ -0,0 +1,91 @@
|
||||
# GitLab CI/CD 环境变量配置
|
||||
# 企业级 CI/CD 蓝皮书 - Harbor 集成配置
|
||||
|
||||
# Harbor 容器仓库配置
|
||||
HARBOR_URL="192.168.1.83:8443"
|
||||
HARBOR_INSECURE="true"
|
||||
|
||||
# Harbor Robot Account (CI/CD)
|
||||
HARBOR_DEV_USER="robot$ci"
|
||||
HARBOR_DEV_PASSWORD="EhlqdiZvxAGreXaCK7faAte4kNbPymtG"
|
||||
|
||||
# Harbor 项目配置
|
||||
HARBOR_DEV_PROJECT="ljwx-dev"
|
||||
HARBOR_STAGE_PROJECT="ljwx-stage"
|
||||
HARBOR_PROD_PROJECT="ljwx-prod"
|
||||
|
||||
# Docker 镜像仓库配置
|
||||
DOCKER_REGISTRY="$HARBOR_URL"
|
||||
DOCKER_REGISTRY_USER="$HARBOR_DEV_USER"
|
||||
DOCKER_REGISTRY_PASSWORD="$HARBOR_DEV_PASSWORD"
|
||||
|
||||
# GitLab Runner 配置
|
||||
RUNNER_EXECUTOR="docker"
|
||||
RUNNER_DOCKER_IMAGE="docker:24.0.7"
|
||||
RUNNER_DOCKER_PRIVILEGED="true"
|
||||
RUNNER_DOCKER_VOLUMES="/var/run/docker.sock:/var/run/docker.sock,/cache"
|
||||
|
||||
# K8s 集群配置 (预留)
|
||||
K8S_DEV_CLUSTER="dev-cluster.ljwx.com"
|
||||
K8S_STAGE_CLUSTER="stage-cluster.ljwx.com"
|
||||
K8S_PROD_CLUSTER="prod-cluster.ljwx.com"
|
||||
|
||||
# 应用配置
|
||||
APP_NAME="ljwx-enterprise"
|
||||
APP_VERSION="1.0.0"
|
||||
BUILD_TARGET="linux/arm64"
|
||||
|
||||
# 安全配置
|
||||
SECURITY_SCAN_ENABLED="true"
|
||||
VULNERABILITY_THRESHOLD="high"
|
||||
CONTAINER_SCAN_ENABLED="true"
|
||||
|
||||
# 通知配置
|
||||
SLACK_WEBHOOK_URL=""
|
||||
EMAIL_NOTIFY_ENABLED="false"
|
||||
TEAMS_WEBHOOK_URL=""
|
||||
|
||||
# 备份配置
|
||||
BACKUP_ENABLED="true"
|
||||
BACKUP_RETENTION_DAYS="30"
|
||||
BACKUP_STORAGE_LOCATION="s3://enterprise-backups"
|
||||
|
||||
# 监控配置
|
||||
PROMETHEUS_ENABLED="true"
|
||||
GRAFANA_ENABLED="true"
|
||||
JAEGER_ENABLED="false"
|
||||
|
||||
# Git 配置
|
||||
GIT_USER_EMAIL="ci@ljwx.com"
|
||||
GIT_USER_NAME="LJWX CI/CD"
|
||||
|
||||
# 构建配置
|
||||
MAVEN_OPTS="-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
|
||||
NODE_OPTIONS="--max-old-space-size=4096"
|
||||
PYTHON_CACHE_DIR="$CI_PROJECT_DIR/.cache/pip"
|
||||
|
||||
# 测试配置
|
||||
TEST_TIMEOUT="30m"
|
||||
COVERAGE_THRESHOLD="80"
|
||||
TEST_PARALLELISM="4"
|
||||
|
||||
# 部署配置
|
||||
DEV_DEPLOY_STRATEGY="rolling"
|
||||
STAGE_DEPLOY_STRATEGY="blue-green"
|
||||
PROD_DEPLOY_STRATEGY="canary"
|
||||
|
||||
# 回滚配置
|
||||
AUTO_ROLLBACK_ENABLED="true"
|
||||
ROLLBACK_TIMEOUT="10m"
|
||||
HEALTH_CHECK_INTERVAL="30s"
|
||||
|
||||
# 资源限制
|
||||
DEFAULT_CPU_LIMIT="1000m"
|
||||
DEFAULT_MEMORY_LIMIT="2Gi"
|
||||
BUILD_CPU_LIMIT="2000m"
|
||||
BUILD_MEMORY_LIMIT="4Gi"
|
||||
|
||||
# 网络配置
|
||||
SERVICE_MESH_ENABLED="true"
|
||||
INGRESS_CLASS="nginx"
|
||||
TLS_ENABLED="true"
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"gitlab_workhorse": {
|
||||
"secret_token": "84tABJKOYmTcKsskhWtvlIyqU/aH0+LxLNPAr27V8r4="
|
||||
},
|
||||
"gitlab_shell": {
|
||||
"secret_token": "bbe09e3b9555f2f06d08eb4ed9c1aad18b6f836e651b427e7e4cba884184242001883b3b93044ec34210985b999779f0a161c160761f24d2fbff814e69bd1e3c"
|
||||
},
|
||||
"gitlab_rails": {
|
||||
"secret_key_base": "6545781a75c56e2ee25d0a28eaa7e4b10a6e6ebf3d8efa278d50700f3c688969251eb141d9b29094bf2acc2b6636b3db9a20915ed7eae997374b537d072ff9b1",
|
||||
"db_key_base": "336dd3ed6a763d9fc11c4609324434aa19c9585729e23930fac5238b225a4b0e9df847588d0826179e7b5deacbdf37e5adf68adcda846c307da4a227cc81d192",
|
||||
"otp_key_base": "08fe9208076f8088dfdca25ff5e8933fe4a4844e344a601e042e8ae40321b97f727453e93b852f978fb20cae36ca978620bbd198bcd7a556bfc6e406ff22069c",
|
||||
"encrypted_settings_key_base": "22921af55f891345dcb16e35649fd7b0cb74064c84622606badd0808325e0749ea955d679a4db995cbfb301ac3c8fdcfcdc625a10a1201841d7e0906c42d5994",
|
||||
"openid_connect_signing_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n",
|
||||
"ci_jwt_signing_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"
|
||||
},
|
||||
"gitlab_pages": {
|
||||
"gitlab_secret": "vSGX1XT5uloQ7wX-TxFOGnJLQwCSiW2MAyyb_nKEaKw",
|
||||
"gitlab_id": "MAbuRe-RicEDF-TAt0il07Ib1oa7YUq6t_X7nGk3kGI",
|
||||
"auth_secret": null,
|
||||
"api_secret_key": "SqhJ7Lq0fudU/dzLhxp4CVbq7sMoZR7Fcb/NsgCcH6g=",
|
||||
"register_as_oauth_app": null
|
||||
},
|
||||
"gitlab_kas": {
|
||||
"api_secret_key": "YzMxYzE1YjNmOTcwMjZiZTg0NTU2YTRlYTc5NjNmNzU=",
|
||||
"private_api_secret_key": "Y2Q5OTA1ZTczOTRlYzk1ODJjNTZlMzU4MTBlZWIzMTA="
|
||||
},
|
||||
"suggested_reviewers": {
|
||||
"api_secret_key": null
|
||||
},
|
||||
"registry": {
|
||||
"http_secret": "ffd29c6711ed3b569366cc7b50763f031844480f360ab847cfd5f77a2bcec0b97e5fec00a64a45f15c0908ce5f8040018c666c058df9fc106708234aad4120d0",
|
||||
"internal_certificate": "-----BEGIN CERTIFICATE-----\nMIIFBTCCAu2gAwIBAgIBADANBgkqhkiG9w0BAQsFADBGMQwwCgYDVQQGEwNVU0Ex\nDzANBgNVBAoMBkdpdExhYjESMBAGA1UECwwJQ29udGFpbmVyMREwDwYDVQQDDAhS\nZWdpc3RyeTAeFw0yNTEwMTkxMjEyMjBaFw0zNTEwMTcxMjEyMjBaMEYxDDAKBgNV\nBAYTA1VTQTEPMA0GA1UECgwGR2l0TGFiMRIwEAYDVQQLDAlDb250YWluZXIxETAP\nBgNVBAMMCFJlZ2lzdHJ5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nw45EFNG5skX7lr1+xxZNNVBQSeiNTXGYudpMBuH8vLztEvOabR1IA4OruWD5/skc\nlGZ5EIZHxmeOdINaibL87+MKdIq2JrLv8VbsuqtMxzAG7OoOexvpqrSKE8ZG02hE\n6Cw0rc43gc9oWo//qpVt5zDR7PS+X75UuKkiUyYyIP7QqdD9dc4EpVAPl1ZSEON2\nlZ46xwlVvXQKfZoe2/+BJqzxhUYXw5Qm1WRzZFe6LXUYOw5ym6DNcEKyjdSkqN0r\n8oFefJ2iAPGnjMiaUhitCwb68pPJ6qpZzkhBT5bxXu6NkISBvGXC0poX8aPTSSVe\nAFyCdhmK+RNXf/5HHNPcaxKE4C4CfDgFDvju62jwjVU9zvoQQBu7PwFZDgupCCmd\nZDpTPwHctMLfSfoROmrosTqS8LACI7VnjUTHHwncaQNcKdDrE6jQSPGk/6U39reZ\nDs785qDk1+d4j2+mnncWSyKiQm9oeZTpfqcH0IR5PXRon35EbfR+WG9jdHTYOKEq\neGys5A/ke6m8ZWf0zhpph1z8SViuKK+amTAaKkphIQ0Cv6PhTSwkZuNSSMF5FDIO\nDsz4D3kU5o6kFgGZidcb/obSrDrPNRjZtZbVtUAmfgC9xDneR1QLBcIZD9yKrFCQ\nPyLAzduyCbP0hVtK05YROTNtAE5NF90aHvn3xbRHrdMCAwEAATANBgkqhkiG9w0B\nAQsFAAOCAgEAgUbtH/tBk6NWhd6O0OxE8WiJFdgP8temB7muaha3nYDc67jPLnma\nudWXynavCp1WqqImkoO3r4bgiTJs0e90UPxKlf+nLkjziOCCwah08GfQ8lrEsY7P\nKRKjgKBTE3M3yj7ixhoPFMfOVuXGXvcDf9CEuByy3TIuAHfeOreUXOBc49eK1/i1\nYldjI7Q2jIlqJAJAI8Z9BmP47/JU0J6YJnYfsv1FxMw4icpDbvkEFuusiZcI+zkJ\nrhRqBcSQ1V+LRDYr/YMRsApOWCADsfe7wrUxvYi7ZkoDcfanxIrH2d7TaSvRayGD\n0f/AjPGDtpg9vsMI7sImyOQbccIpqwL9n3uB7QFmutHEHdf7GjKvGVdSaYMwxZyj\nTojyrEZhqn8XUjRRtsWu4yI+t2CSa3uO2IOyHaWtbhp67N3HiJUZU12SldB1mFWE\n5U3kzmT6ouNRkMd5xBdKPvrn7ahoqwgfm02NGvV4b8tFrsT5Ts3z1qEBRByJ3JnL\nB7+8e/7QXlVUrBCMKzPUU2RzR/ybVqsMtiCxteAZAamXg6BeSd1pLwgyG/guj0bo\nUx3TNTsT6a806RCBdu1GpgSA2Yehl7OFsfP9djYpOwTIX9mgrvEplb6wG1a0OoDk\n7+xhi4eVHWmAVuqCb4tHYUAZ4kLcVEhPZf0kLP6RLqlOI8trud6WU68=\n-----END CERTIFICATE-----\n",
|
||||
"internal_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIJKQIBAAKCAgEAw45EFNG5skX7lr1+xxZNNVBQSeiNTXGYudpMBuH8vLztEvOa\nbR1IA4OruWD5/skclGZ5EIZHxmeOdINaibL87+MKdIq2JrLv8VbsuqtMxzAG7OoO\nexvpqrSKE8ZG02hE6Cw0rc43gc9oWo//qpVt5zDR7PS+X75UuKkiUyYyIP7QqdD9\ndc4EpVAPl1ZSEON2lZ46xwlVvXQKfZoe2/+BJqzxhUYXw5Qm1WRzZFe6LXUYOw5y\nm6DNcEKyjdSkqN0r8oFefJ2iAPGnjMiaUhitCwb68pPJ6qpZzkhBT5bxXu6NkISB\nvGXC0poX8aPTSSVeAFyCdhmK+RNXf/5HHNPcaxKE4C4CfDgFDvju62jwjVU9zvoQ\nQBu7PwFZDgupCCmdZDpTPwHctMLfSfoROmrosTqS8LACI7VnjUTHHwncaQNcKdDr\nE6jQSPGk/6U39reZDs785qDk1+d4j2+mnncWSyKiQm9oeZTpfqcH0IR5PXRon35E\nbfR+WG9jdHTYOKEqeGys5A/ke6m8ZWf0zhpph1z8SViuKK+amTAaKkphIQ0Cv6Ph\nTSwkZuNSSMF5FDIODsz4D3kU5o6kFgGZidcb/obSrDrPNRjZtZbVtUAmfgC9xDne\nR1QLBcIZD9yKrFCQPyLAzduyCbP0hVtK05YROTNtAE5NF90aHvn3xbRHrdMCAwEA\nAQKCAgB/zOP1bzKarV3En8bQuWRv6TLvekmOSST0oRN6lAomFpog/o73rGE52r1J\ng3Ud67T/zxBjmj4iDd9ticKLpyviYlCc5WIxXFOvN42yWOzuaBa+kiAwmIdXBnIO\nhlAXLVeLHAi5ZcGk1jVuqhj+FHYk1yT6ZOBdlfesTuydxqKQKbeYo3phmOg0WWQ3\nFTTA0MbY9PWYyiL8k2+fsi9ku1BeRDv7S1mQeav/XYyEEUkdGB9jyQdhae+Y5B3o\nzwVlTlXAQIfNjP8o+sTzHs6rxHCiekdabPdSo03ZoCL+rrjDv8dIoTBgPWjbVdU8\nGEKm1QLf3ZVtNTg7m0Zd4YH79wFe28FiLrp0ViYlkTByJqPQ2Qfej5hijM+ZLXh5\nkJFbz9mQ5yNxBPz7CDdMKe9kzPKvTGTccXdSjdTo/pWGMZ9PBoZnrxA35gcjWGQ3\n03c+wKEvtC4WcKAcG6Si85lhS1n/2C+sULONa07UIfFLnAHLP6uNUjfspkxVkhH4\n2r6zGGKDoT/Q+7QOe76/Jw8hJmVG8qoOVIr0gYmojO8cBVvRGKyoSeKmE1/mwjyW\nYnc0RUi/phiLSnARbt0BIW57JtwSpF5FJq6oK5jD8VrrXyU2IWJPzz1sk8xTS/QS\nQ0xTJwbyITjaeQfPZ2/FhqjJDJwt0+N/scad6PLuTOZI6FDa4QKCAQEA5nHQbBup\n2sd1AH+AM8/sFDp8dUkiBEnAakQtaEFcnDXJy7GkZqotskM4DTBaRZW2oLVlx366\nxYm+aXzT1P3fAcEGi/qabAPpk8JGwXUrrqOG/ALui4SrrSY2k6MvXgii7Hs4+a/z\nw0Pjui0FiyfsDD5HQHYJzZYUnQqjetbA9l0wHqETBghRv5QMPv4/5OS9goiZb8Kr\naSfKDFotgEMtNE9TZzL3Vzq/JsqbuZ9eZ6jI6bBIXtlSDJo6kkBLG3Kd1hcswtEj\nuUtDbaSqKGVq2yN3cz1gusOlZfdKXGAp+QvcF9+mVYjAqqLqUeAJ2y0tHAMugGiZ\nms5d9skH51qyqQKCAQEA2T36RmYLWLH0KD16WNjP2LU9XOSPWc/4CfCgRTxkvX0F\nT49ljP7ouU5OMPLQgfLaeTq4jC4g1YXCmDY96yN2nhQT2fxBNN3RSA9Pa1n3EC4J\nR8VFZjT6S+PTnbfIP4nLcIclYfkieV0Fu1HZCUe2E6Tn0z0bLpaFy3Cr4+eu4Jkp\ncMCru3IqFU4YKn3XIfuhJkWJsEXkmsvtbZrykNtvua5cQ09b7Z9Mj4a0Mmj0DqwP\nd5JQ6sEcFl0zwBDh763dD0LVsF6qOwfYDuAJfZOwWn9iP5YJFFSRPTXIFicA/Sqa\niHcAqVpUuF6eNssnIdJH1p0Lw0NsdjI5ZIKvanvmGwKCAQEAlCzCs4DmKsLtvLA/\nIxGi3y7sMA4iTVeO3cWQ3OSKQ/diFhPXfhwW3fTS6cgZg3zMvXFmTGx0c+gqA3I8\nU0waROp05zTwblvlqRjWnjZVLCoB9bF86UEZknBrz2qyXmh3Ok/RRtuYhgn1OBUS\n53N4GDdDYXOEwiiqgIACtk24LbGl60vvC4X16pWreiXJt8hNAs4Kuw4VYbwv8tlZ\nQIvxWR1Yp5bh67jeiHbmwuhyr3ycE4dCQZrDY08YMkodAT0luC+WnH4V1mNKrAmh\nT/BGUTnw6KyisfRzOalUqyk6U+UIVGF+dqlEGXQ/7v172O6nfsec8vxPKHdhe/mv\nl1d+YQKCAQAt7gycFbcQaY9VcqoLXsuS5b6zhR9Jvc6TS2yXNs2Vwnj8+TRfOwW5\nJ/UgJDYxQ0ctmlyqRpZqjn018UHmFPlfMp9/1vVyV/OHaLVB3SN/KDyOEAc8NLc2\nlFSJY/HSfS+l+uzMaf//6Mrtb8CTVbYJMTRSVPkKQIjJGmk9Jh6zHa7FR/cHCnwb\nRQeW9EQnyyunC8ywmBZdJABuy/O87KgSeerH0F9/Pc7SCYjPn6D5+SbMAQNanrlx\ngQMP+IHMStYSA+9p+pnDIUVs37Eh+7etaoE7MF17DuYmKtjC1jw/SmKht4dMRuzi\njh6lNw5u+CZ4GXwDLJ4h3zyDI54yxT9BAoIBAQCzYrMs6NaE1HG/QSkcZ5aHEvnR\nJox/1UDXcS5WjAtvqLgrdxN2IqhKsetVM4HytzpSmW7VGLm8FGvu67IKa+DwCsYq\nYoFgdJYOqRpvYk2UdNPMvTWMuJEsnzgG91FQ2ftu7yOfUjlOZnGfKfZuWWY4SMes\n5LGIA/s+GQY39sGaJahSt7eqIpaCXTA6g+7oQz8kuUF+tGn9Ms5/mqQgS+vBMKDW\nDZi614DowG7gxX0/9Fg4mqfstO0LgbLODzLwLKq9J/lWqaN7QASr7a23idnSiWoa\nkJCcNpAF8ubmO8Dcz+mHWYoYt3bURn69cGwMoMJfji22mZT3Wre/SH2Bn7bq\n-----END RSA PRIVATE KEY-----\n"
|
||||
},
|
||||
"letsencrypt": {
|
||||
"auto_enabled": null
|
||||
},
|
||||
"mattermost": {
|
||||
"email_invite_salt": "aa89bd78b0cf5e7a252c006706189879",
|
||||
"file_public_link_salt": "7814e1b33d5118bee79d29f26cf9dfba",
|
||||
"sql_at_rest_encrypt_key": "38d36278fff3ee68f48edb732afe000a",
|
||||
"register_as_oauth_app": null
|
||||
},
|
||||
"postgresql": {
|
||||
"internal_certificate": "-----BEGIN CERTIFICATE-----\nMIIFBzCCAu+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBHMQwwCgYDVQQGEwNVU0Ex\nDzANBgNVBAoMBkdpdExhYjERMA8GA1UECwwIRGF0YWJhc2UxEzARBgNVBAMMClBv\nc3RncmVTUUwwHhcNMjUxMDE5MTIxMjIyWhcNMzUxMDE3MTIxMjIyWjBHMQwwCgYD\nVQQGEwNVU0ExDzANBgNVBAoMBkdpdExhYjERMA8GA1UECwwIRGF0YWJhc2UxEzAR\nBgNVBAMMClBvc3RncmVTUUwwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\nAQCmODHJRKX7sOYmAD8zN6Bmoi13VRhYEta9mWBRpkg1H0P41nCF9PxwVoqKqymt\nGgyZCs0wFEsPRWc0/5r3AoPBlup+eggMMvEnvr5Y9Z/vaG354rUr/tXEqma3ekwr\nVHGberXsF3+ohmctQrzxa3+3eElnL/sz9iUunPu3IZoE19OjAsCeu1kgo6af0UWe\niObQd2gvCSkRZ1t+ctvdiVS3Wblzs95disOXjhTU06Aji3868Yc1xrhI5J7WP/iS\n/z/SP2pmqGvgnMswgkrABkauuaI6WZCWj6uPEajgn+GMoXLTMKPBznDxtD6B2M9z\nS5hSHATLYnRYADeVZoXolq4s9WVDMJfOB7vnDHWbnZAA+lz66RfPMgpLH0b3C10U\n06MRyx145uXkImoYeQqEd3AWLNDXQIpZxXqN11kA9lCMqMyWPPGRgQK3oeZEzah+\n8rynoL/RS593Ne0yrCT1/hQKsmLeY8SsgmbgEAvgGIQZllwuwgUmXqwtdE8g8Md0\nlfgdqFNdJWqEjcRRQVbPVWClN3Ln4qh7IisCa9ZXVhmyhMEFgruI6C/0R6ynxPLu\nXdc8UnAPlhxt/BoC84jhv9ixkM1/ue5QZlwkbUcjqZDcMRS/91YGwPMWfuw2oALi\nSOcPMOSNJy3PRVYlAmOgS/Bq5ufdy98qNnYSCBZRVua2/QIDAQABMA0GCSqGSIb3\nDQEBCwUAA4ICAQAQ+f/zhgQvKYe8OCcr6Ri/4CYN7WtLJwSsrFSPZNofZgVpJY9e\nH3Evz/7y/1kawHDHKNDea04+5OYSpyS2DzBderDtdEJ63XQ0mHlDjsCeVXltblx+\nP80jl+a3xAp4SQ0pQJTln+9LF/tjXmuXz21XdS5fJbtrpwubYyDG7qgBANd2wtQG\njTnUJCsAUYSscYT5QrMgvHo6csxM3usios4H3u+AilzHSyigFBJgWbUEHxHBZLiq\nX3ucSKQH++5Wi/nd3KMKfbUcQdTXie1NymmiPUO4SjZKyMcVrLxb7+Ayy2F0FerT\ne7UWKgsFhiGGXXsGnSAcW8h6TmxOU4RmrTcs7McVg9dGkN+t4oeJkLTFWdzyfr/Q\nrzpZZax7tBwdnpK3OmEUZqnqccqiO/ludnDT92e1/sCK8Os+I1Ho0djyd5u88ACo\nSKGE+zFGeaCUWDutc6qtk7m4j9GI/rMHE6mrB1PPKaD3l35p2KEYORtOYNhXCgwb\nAob5UTRA+to/Q2JMTPqeYIqx86sEScoUje56deJInMB2Izle2ii2w2UtbdmRhM4J\nwrY+4zDlPbAk+oqdAVtDhyiOnxF/mrvP0i+036wJAC8eufjaJaV6+YPQvNF6mREU\nhxdWq4jgpWeV6GuUZemDYc/GUx+av+6wCyjN6mY7QLix8R4Ur4woKskwOQ==\n-----END CERTIFICATE-----\n",
|
||||
"internal_key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"
|
||||
},
|
||||
"mailroom": {
|
||||
"incoming_email_auth_token": null,
|
||||
"service_desk_email_auth_token": null
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
QCRhYSVZyyArPTlUAca83uMkg
|
||||
@@ -0,0 +1,9 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
|
||||
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQRZEGo+QqcWCpmc+5oEBY6/MVtNgO4b
|
||||
/cFHVHI1jWR3DUxjy42DrQrUwTdhQP+/akzggJkeZdrMx2wYFmrSQShIAAAAsGYu4RhmLu
|
||||
EYAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFkQaj5CpxYKmZz7
|
||||
mgQFjr8xW02A7hv9wUdUcjWNZHcNTGPLjYOtCtTBN2FA/79qTOCAmR5l2szHbBgWatJBKE
|
||||
gAAAAgVpMHrvAvegJxD7D7Pt3I6kROyh1pFuDmPRekWnepbMUAAAARcm9vdEBnaXRsYWIu
|
||||
bG9jYWwBAgMEBQYH
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFkQaj5CpxYKmZz7mgQFjr8xW02A7hv9wUdUcjWNZHcNTGPLjYOtCtTBN2FA/79qTOCAmR5l2szHbBgWatJBKEg= root@gitlab.local
|
||||
@@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACAhjNhWIv6q9j6rtIRaYuIkh5Ui8Epi9CFW0gruYJwGrAAAAJhDpEc4Q6RH
|
||||
OAAAAAtzc2gtZWQyNTUxOQAAACAhjNhWIv6q9j6rtIRaYuIkh5Ui8Epi9CFW0gruYJwGrA
|
||||
AAAEBKZwRgwiVtu5FHHME8sh31Ah0aO/09Ec5emFSEsGn2pyGM2FYi/qr2Pqu0hFpi4iSH
|
||||
lSLwSmL0IVbSCu5gnAasAAAAEXJvb3RAZ2l0bGFiLmxvY2FsAQIDBA==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICGM2FYi/qr2Pqu0hFpi4iSHlSLwSmL0IVbSCu5gnAas root@gitlab.local
|
||||
@@ -0,0 +1,38 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
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
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCp0oTA3ydj0mPbLsbouE+G++M2w674cXYReJ1cpA2NCFSTzjaLo4Vh/KqpcG4IS5XaqB2kM6AtdgHc/kzZ1dBLL1wNceDWTDxJNjapKYYN0r33ujzN+7pIXJXY6ek8jbxtZfs/0UNPhU3rgbkHowNwFwiQPxY/NdpJrLntrU3Urd0sBoyVe58QzOEuaSysgfCDqw3fxEVpBGosVl70gym1r4kHtxhAm4gV9c56Tj5Pz+Z8Y4IvHRsVUA7AgmqtFzwg/Of6ComEEriJXqgbDr+g5koE/yGvAPRuwvvEa+7Na2vVuZ/e000en4rP7VJVNlL+6DW52JwZyl1Xf10Pmx6Xbkp8PHXutyFgsbMr5fjlX4qM5zhNYxpgsgwten9rDiA/F36nzdiminlIT38yHnQGqkSr40n1ePlhcywWRux3NV0VFRQVYgVWnpolGHb/3XPWiqKJrGBYJXoejC2nwQDe0r423f2G4AJgcIyRIWAmdcBnw0K26Ke5pwo153gaEsk= root@gitlab.local
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Harbor 快速备份脚本
|
||||
# 这是 harbor-data-protection.sh 的简化版本,专注于快速备份操作
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 配置变量
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
HARBOR_DATA_PROTECTION="${SCRIPT_DIR}/harbor-data-protection.sh"
|
||||
BACKUP_NAME="${1:-}"
|
||||
|
||||
# 调用主脚本的备份功能
|
||||
if [[ -x "$HARBOR_DATA_PROTECTION" ]]; then
|
||||
if [[ -n "$BACKUP_NAME" ]]; then
|
||||
"$HARBOR_DATA_PROTECTION" backup "$BACKUP_NAME"
|
||||
else
|
||||
"$HARBOR_DATA_PROTECTION" backup
|
||||
fi
|
||||
else
|
||||
echo "错误: 找不到 Harbor 数据保护脚本: $HARBOR_DATA_PROTECTION"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+596
@@ -0,0 +1,596 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Harbor 数据保护和管理脚本
|
||||
# 支持 Docker Compose 模式的 Harbor 服务管理
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 配置变量
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_NAME="${PROJECT_NAME:-harbor}"
|
||||
HARBOR_DIR="${HARBOR_DIR:-${SCRIPT_DIR}}"
|
||||
HARBOR_DATA_DIR="${HARBOR_DATA_DIR:-~/ops/data/harbor}"
|
||||
HARBOR_CERT_DIR="${HARBOR_CERT_DIR:-${SCRIPT_DIR}/certs}"
|
||||
LOG_FILE="${LOG_FILE:-~/ops/logs/harbor-protection.log}"
|
||||
BACKUP_DIR="${BACKUP_DIR:-~/ops/backups/harbor}"
|
||||
HARBOR_YML="${HARBOR_YML:-${HARBOR_DIR}/harbor.yml}"
|
||||
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-${HARBOR_DIR}/docker-compose.yml}"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log() {
|
||||
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
|
||||
}
|
||||
|
||||
info() {
|
||||
log "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
success() {
|
||||
log "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
warning() {
|
||||
log "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
log "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查必要的依赖
|
||||
check_dependencies() {
|
||||
local deps=("docker" "docker-compose")
|
||||
for dep in "${deps[@]}"; do
|
||||
if ! command -v "$dep" &> /dev/null; then
|
||||
error "$dep 未安装,请先安装 $dep"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查 Docker 是否运行
|
||||
if ! docker info &> /dev/null; then
|
||||
error "Docker 未运行,请启动 Docker Desktop"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建必要的目录
|
||||
ensure_directories() {
|
||||
mkdir -p "$(dirname "${LOG_FILE}")"
|
||||
mkdir -p "${BACKUP_DIR}"
|
||||
mkdir -p "$(dirname "${HARBOR_DATA_DIR}")"
|
||||
mkdir -p "${HARBOR_CERT_DIR}"
|
||||
}
|
||||
|
||||
# 检查 Harbor 配置
|
||||
check_harbor_config() {
|
||||
if [[ ! -f "${HARBOR_YML}" ]]; then
|
||||
error "Harbor 配置文件不存在: ${HARBOR_YML}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "${DOCKER_COMPOSE_FILE}" ]]; then
|
||||
error "Docker Compose 配置文件不存在: ${DOCKER_COMPOSE_FILE}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 服务状态检查
|
||||
check_service_status() {
|
||||
info "检查 Harbor 服务状态..."
|
||||
|
||||
local running_containers
|
||||
running_containers=$(docker-compose -f "${DOCKER_COMPOSE_FILE}" ps -q 2>/dev/null || echo "")
|
||||
|
||||
if [[ -z "$running_containers" ]]; then
|
||||
warning "Harbor 服务未运行"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local healthy_containers
|
||||
healthy_containers=$(docker-compose -f "${DOCKER_COMPOSE_FILE}" ps --filter "status=running" --format "table {{.Service}}\t{{.Status}}" 2>/dev/null | grep -c "healthy\|Up" || echo "0")
|
||||
|
||||
info "运行中的容器数量: $(echo "$running_containers" | wc -l)"
|
||||
info "健康容器数量: $healthy_containers"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 启动 Harbor 服务
|
||||
start_services() {
|
||||
info "启动 Harbor 服务..."
|
||||
|
||||
# 检查配置
|
||||
if ! check_harbor_config; then
|
||||
error "Harbor 配置检查失败,无法启动服务"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 确保数据目录存在
|
||||
mkdir -p "${HARBOR_DATA_DIR}"
|
||||
|
||||
# 启动服务
|
||||
cd "${HARBOR_DIR}"
|
||||
docker-compose -f "${DOCKER_COMPOSE_FILE}" up -d
|
||||
|
||||
# 等待服务启动
|
||||
info "等待服务启动完成..."
|
||||
sleep 10
|
||||
|
||||
# 检查服务状态
|
||||
if check_service_status; then
|
||||
success "Harbor 服务启动成功"
|
||||
return 0
|
||||
else
|
||||
error "Harbor 服务启动失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 停止 Harbor 服务
|
||||
stop_services() {
|
||||
info "停止 Harbor 服务..."
|
||||
|
||||
if [[ ! -f "${DOCKER_COMPOSE_FILE}" ]]; then
|
||||
warning "Docker Compose 配置文件不存在,跳过停止操作"
|
||||
return 0
|
||||
fi
|
||||
|
||||
cd "${HARBOR_DIR}"
|
||||
docker-compose -f "${DOCKER_COMPOSE_FILE}" down || true
|
||||
|
||||
success "Harbor 服务已停止"
|
||||
}
|
||||
|
||||
# 重启 Harbor 服务
|
||||
restart_services() {
|
||||
info "重启 Harbor 服务..."
|
||||
stop_services
|
||||
sleep 5
|
||||
start_services
|
||||
}
|
||||
|
||||
# 健康检查
|
||||
health_check() {
|
||||
info "执行 Harbor 健康检查..."
|
||||
|
||||
local status=0
|
||||
|
||||
# 检查服务状态
|
||||
if ! check_service_status; then
|
||||
error "服务状态检查失败"
|
||||
status=1
|
||||
fi
|
||||
|
||||
# 检查端口
|
||||
local ports=("8080" "8081" "8443" "8444")
|
||||
for port in "${ports[@]}"; do
|
||||
if lsof -i ":$port" &> /dev/null; then
|
||||
info "端口 $port 正在使用"
|
||||
else
|
||||
warning "端口 $port 未被使用"
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查数据目录
|
||||
if [[ -d "${HARBOR_DATA_DIR}" ]]; then
|
||||
local data_size
|
||||
data_size=$(du -sh "${HARBOR_DATA_DIR}" 2>/dev/null | cut -f1)
|
||||
info "Harbor 数据目录大小: $data_size"
|
||||
else
|
||||
warning "Harbor 数据目录不存在"
|
||||
status=1
|
||||
fi
|
||||
|
||||
# 检查证书
|
||||
if [[ -f "${HARBOR_CERT_DIR}/harbor.crt" ]]; then
|
||||
info "SSL 证书文件存在"
|
||||
|
||||
# 检查证书有效期
|
||||
if command -v openssl &> /dev/null; then
|
||||
local cert_exp
|
||||
cert_exp=$(openssl x509 -in "${HARBOR_CERT_DIR}/harbor.crt" -noout -enddate 2>/dev/null | cut -d= -f2 || echo "unknown")
|
||||
info "SSL 证书有效期: $cert_exp"
|
||||
fi
|
||||
else
|
||||
warning "SSL 证书文件不存在"
|
||||
fi
|
||||
|
||||
if [[ $status -eq 0 ]]; then
|
||||
success "Harbor 健康检查通过"
|
||||
else
|
||||
error "Harbor 健康检查发现问题"
|
||||
fi
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
# 获取 Harbor 统计信息
|
||||
get_stats() {
|
||||
info "获取 Harbor 统计信息..."
|
||||
|
||||
# 服务状态
|
||||
check_service_status
|
||||
|
||||
# 数据目录统计
|
||||
if [[ -d "${HARBOR_DATA_DIR}" ]]; then
|
||||
echo ""
|
||||
info "=== 数据目录统计 ==="
|
||||
du -sh "${HARBOR_DATA_DIR}"/* 2>/dev/null | sort -hr || true
|
||||
|
||||
# 镜像数量估算 (基于 registry 目录)
|
||||
local registry_dir="${HARBOR_DATA_DIR}/registry"
|
||||
if [[ -d "$registry_dir" ]]; then
|
||||
local repo_count
|
||||
repo_count=$(find "$registry_dir" -type d -name "*.git" 2>/dev/null | wc -l || echo "0")
|
||||
info "估算的镜像仓库数量: $repo_count"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 备份文件统计
|
||||
if [[ -d "${BACKUP_DIR}" ]]; then
|
||||
echo ""
|
||||
info "=== 备份文件统计 ==="
|
||||
ls -lah "${BACKUP_DIR}"/*.tar.gz 2>/dev/null | tail -10 || true
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份 Harbor 数据
|
||||
backup_harbor() {
|
||||
local backup_name="${1:-harbor-$(date +%Y%m%d-%H%M%S)}"
|
||||
local backup_file="${BACKUP_DIR}/${backup_name}.tar.gz"
|
||||
|
||||
info "开始备份 Harbor 数据..."
|
||||
|
||||
# 检查服务状态
|
||||
local service_running=false
|
||||
if check_service_status &>/dev/null; then
|
||||
service_running=true
|
||||
warning "服务正在运行,建议在备份前停止服务以获得一致性备份"
|
||||
read -p "是否继续备份? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
info "备份已取消"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# 创建备份
|
||||
local backup_items=()
|
||||
|
||||
# Harbor 配置
|
||||
if [[ -f "${HARBOR_YML}" ]]; then
|
||||
backup_items+=("${HARBOR_YML}")
|
||||
fi
|
||||
|
||||
if [[ -f "${DOCKER_COMPOSE_FILE}" ]]; then
|
||||
backup_items+=("${DOCKER_COMPOSE_FILE}")
|
||||
fi
|
||||
|
||||
# Harbor 数据目录
|
||||
if [[ -d "${HARBOR_DATA_DIR}" ]]; then
|
||||
backup_items+=("${HARBOR_DATA_DIR}")
|
||||
fi
|
||||
|
||||
# 证书目录
|
||||
if [[ -d "${HARBOR_CERT_DIR}" ]] && [[ -n "$(ls -A "${HARBOR_CERT_DIR}" 2>/dev/null)" ]]; then
|
||||
backup_items+=("${HARBOR_CERT_DIR}")
|
||||
fi
|
||||
|
||||
if [[ ${#backup_items[@]} -eq 0 ]]; then
|
||||
error "没有找到需要备份的文件或目录"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 执行备份
|
||||
info "创建备份文件: $backup_file"
|
||||
tar -czf "${backup_file}" "${backup_items[@]}" 2>/dev/null
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
# 创建备份元数据
|
||||
local meta_file="${backup_file}.meta"
|
||||
cat > "${meta_file}" << EOF
|
||||
backup_name="${backup_name}"
|
||||
backup_date="$(date -Iseconds)"
|
||||
backup_size="$(stat -f%z "${backup_file}" 2>/dev/null || stat -c%s "${backup_file}" 2>/dev/null || echo "unknown")"
|
||||
service_running="${service_running}"
|
||||
harbor_version="$(grep "_version" "${HARBOR_YML}" 2>/dev/null | cut -d' ' -f2 || echo "unknown")"
|
||||
items="$(printf '%s;' "${backup_items[@]}")"
|
||||
EOF
|
||||
|
||||
success "Harbor 备份完成: ${backup_file}"
|
||||
|
||||
# 显示备份信息
|
||||
local backup_size
|
||||
backup_size=$(ls -lh "${backup_file}" | awk '{print $5}')
|
||||
info "备份大小: ${backup_size}"
|
||||
|
||||
# 清理旧备份 (保留最近 10 个)
|
||||
cleanup_old_backups 10
|
||||
else
|
||||
error "Harbor 备份失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 恢复 Harbor 数据
|
||||
restore_harbor() {
|
||||
local backup_file="${1:-}"
|
||||
|
||||
if [[ -z "$backup_file" ]]; then
|
||||
error "请指定备份文件"
|
||||
show_backups
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$backup_file" ]]; then
|
||||
error "备份文件不存在: $backup_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
info "开始从备份恢复 Harbor..."
|
||||
|
||||
# 创建安全备份
|
||||
local safety_backup="${BACKUP_DIR}/safety-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||||
if [[ -d "${HARBOR_DATA_DIR}" ]] || [[ -f "${HARBOR_YML}" ]]; then
|
||||
info "创建当前状态的安全备份: $safety_backup"
|
||||
backup_harbor "safety-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
fi
|
||||
|
||||
# 停止现有服务
|
||||
stop_services
|
||||
|
||||
# 恢复备份
|
||||
info "恢复备份文件: $backup_file"
|
||||
cd /
|
||||
tar -xzf "$backup_file" 2>/dev/null
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
success "Harbor 数据恢复完成"
|
||||
|
||||
# 启动服务
|
||||
sleep 5
|
||||
start_services
|
||||
|
||||
# 验证恢复结果
|
||||
if health_check; then
|
||||
success "Harbor 恢复验证通过"
|
||||
else
|
||||
error "Harbor 恢复验证失败,请检查日志"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
error "Harbor 数据恢复失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示可用备份
|
||||
show_backups() {
|
||||
info "可用的 Harbor 备份文件:"
|
||||
if [[ -d "${BACKUP_DIR}" ]]; then
|
||||
local backups=($(ls -t "${BACKUP_DIR}"/harbor-*.tar.gz 2>/dev/null || true))
|
||||
if [[ ${#backups[@]} -gt 0 ]]; then
|
||||
for i in "${!backups[@]}"; do
|
||||
local backup_file="${backups[$i]}"
|
||||
local backup_size
|
||||
backup_size=$(ls -lh "$backup_file" | awk '{print $5}')
|
||||
local backup_date
|
||||
backup_date=$(stat -f%Sm -t%Y-%m-%d\ %H:%M:%S "$backup_file" 2>/dev/null || stat -c%y "$backup_file" 2>/dev/null | cut -d'.' -f1)
|
||||
printf "%2d. %-40s %10s %s\n" $((i+1)) "$(basename "$backup_file")" "$backup_size" "$backup_date"
|
||||
done
|
||||
else
|
||||
warning "没有找到 Harbor 备份文件"
|
||||
fi
|
||||
else
|
||||
warning "备份目录不存在: ${BACKUP_DIR}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理旧备份
|
||||
cleanup_old_backups() {
|
||||
local keep_count="${1:-5}"
|
||||
|
||||
info "清理旧备份文件,保留最近 $keep_count 个..."
|
||||
|
||||
if [[ -d "${BACKUP_DIR}" ]]; then
|
||||
local old_backups
|
||||
old_backups=($(ls -t "${BACKUP_DIR}"/harbor-*.tar.gz 2>/dev/null | tail -n +$((keep_count+1)) || true))
|
||||
|
||||
if [[ ${#old_backups[@]} -gt 0 ]]; then
|
||||
for backup in "${old_backups[@]}"; do
|
||||
info "删除旧备份: $(basename "$backup")"
|
||||
rm -f "$backup" "${backup}.meta"
|
||||
done
|
||||
success "已清理 ${#old_backups[@]} 个旧备份文件"
|
||||
else
|
||||
info "没有需要清理的旧备份文件"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 设置定时任务
|
||||
setup_cron() {
|
||||
local cron_interval="${1:-"0 2 * * *"}" # 默认每天凌晨 2 点
|
||||
|
||||
info "设置 Harbor 备份定时任务..."
|
||||
|
||||
# 创建 cron 脚本
|
||||
local cron_script="${SCRIPT_DIR}/harbor-cron-backup.sh"
|
||||
cat > "$cron_script" << EOF
|
||||
#!/bin/bash
|
||||
# Harbor 自动备份 cron 任务
|
||||
$(declare -f log info success warning error)
|
||||
$(declare -f check_dependencies ensure_directories backup_harbor)
|
||||
|
||||
LOG_FILE="${LOG_FILE}"
|
||||
BACKUP_DIR="${BACKUP_DIR}"
|
||||
HARBOR_DATA_DIR="${HARBOR_DATA_DIR}"
|
||||
HARBOR_CERT_DIR="${HARBOR_CERT_DIR}"
|
||||
HARBOR_YML="${HARBOR_YML}"
|
||||
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE}"
|
||||
|
||||
# 执行备份
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
backup_harbor
|
||||
EOF
|
||||
|
||||
chmod +x "$cron_script"
|
||||
|
||||
# 添加到 crontab
|
||||
local cron_entry="$cron_interval $cron_script >> ${LOG_FILE} 2>&1"
|
||||
(crontab -l 2>/dev/null | grep -v "harbor-cron-backup" || true; echo "$cron_entry") | crontab -
|
||||
|
||||
# 设置 launchd 任务 (macOS 原生)
|
||||
local launchd_plist="$HOME/Library/LaunchAgents/com.ljwx.harbor.backup.plist"
|
||||
cat > "$launchd_plist" << EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.ljwx.harbor.backup</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>$cron_script</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Hour</key>
|
||||
<integer>2</integer>
|
||||
<key>Minute</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>StandardOutPath</key>
|
||||
<string>${LOG_FILE}.cron.stdout.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>${LOG_FILE}.cron.stderr.log</string>
|
||||
<key>RunAtLoad</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
# 加载 launchd 任务
|
||||
launchctl unload "$launchd_plist" 2>/dev/null || true
|
||||
launchctl load -w "$launchd_plist"
|
||||
|
||||
success "Harbor 备份定时任务已设置"
|
||||
info "Cron 任务: $cron_entry"
|
||||
info "Launchd 任务已加载"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Harbor 数据保护和管理脚本
|
||||
|
||||
用法: $0 [命令] [参数]
|
||||
|
||||
命令:
|
||||
start 启动 Harbor 服务
|
||||
stop 停止 Harbor 服务
|
||||
restart 重启 Harbor 服务
|
||||
status 检查服务状态
|
||||
health 执行健康检查
|
||||
stats 显示统计信息
|
||||
backup [名称] 创建备份
|
||||
restore [文件] 从备份恢复
|
||||
list 显示可用备份
|
||||
cleanup [数量] 清理旧备份 (默认保留 5 个)
|
||||
setup 设置定时任务
|
||||
help 显示帮助信息
|
||||
|
||||
示例:
|
||||
$0 start # 启动服务
|
||||
$0 backup # 创建备份
|
||||
$0 backup my-backup # 创建命名备份
|
||||
$0 restore backup-2023.tar.gz # 从备份恢复
|
||||
$0 cleanup 10 # 保留最近 10 个备份
|
||||
|
||||
环境变量:
|
||||
HARBOR_DIR Harbor 配置目录 (默认: 脚本所在目录)
|
||||
HARBOR_DATA_DIR Harbor 数据目录 (默认: ~/ops/data/harbor)
|
||||
BACKUP_DIR 备份目录 (默认: ~/ops/backups/harbor)
|
||||
LOG_FILE 日志文件 (默认: ~/ops/logs/harbor-protection.log)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local command="${1:-help}"
|
||||
local parameter="${2:-}"
|
||||
|
||||
# 设置环境变量
|
||||
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
|
||||
|
||||
case "$command" in
|
||||
"start")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
start_services
|
||||
;;
|
||||
"stop")
|
||||
stop_services
|
||||
;;
|
||||
"restart")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
restart_services
|
||||
;;
|
||||
"status")
|
||||
check_service_status
|
||||
;;
|
||||
"health")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
health_check
|
||||
;;
|
||||
"stats")
|
||||
get_stats
|
||||
;;
|
||||
"backup")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
backup_harbor "$parameter"
|
||||
;;
|
||||
"restore")
|
||||
check_dependencies
|
||||
ensure_directories
|
||||
restore_harbor "$parameter"
|
||||
;;
|
||||
"list"|"ls")
|
||||
show_backups
|
||||
;;
|
||||
"cleanup")
|
||||
cleanup_old_backups "$parameter"
|
||||
;;
|
||||
"setup")
|
||||
setup_cron "$parameter"
|
||||
;;
|
||||
"help"|"-h"|"--help")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
error "未知命令: $command"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 如果脚本被直接执行,调用主函数
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Harbor 快速恢复脚本
|
||||
# 这是 harbor-data-protection.sh 的简化版本,专注于快速恢复操作
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 配置变量
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
HARBOR_DATA_PROTECTION="${SCRIPT_DIR}/harbor-data-protection.sh"
|
||||
BACKUP_FILE="${1:-}"
|
||||
|
||||
# 显示可用备份 (如果没有指定备份文件)
|
||||
if [[ -z "$BACKUP_FILE" ]]; then
|
||||
echo "可用的 Harbor 备份文件:"
|
||||
"$HARBOR_DATA_PROTECTION" list
|
||||
echo ""
|
||||
echo "请指定要恢复的备份文件,例如:"
|
||||
echo "$0 harbor-20231220-120000.tar.gz"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 调用主脚本的恢复功能
|
||||
if [[ -x "$HARBOR_DATA_PROTECTION" ]]; then
|
||||
"$HARBOR_DATA_PROTECTION" restore "$BACKUP_FILE"
|
||||
else
|
||||
echo "错误: 找不到 Harbor 数据保护脚本: $HARBOR_DATA_PROTECTION"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,316 @@
|
||||
# Configuration file of Harbor
|
||||
|
||||
# The IP address or hostname to access admin UI and registry service.
|
||||
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
|
||||
hostname: 192.168.1.83
|
||||
|
||||
# http related config
|
||||
http:
|
||||
# port for http, default is 80. If https enabled, this port will redirect to https port
|
||||
port: 8080
|
||||
|
||||
# https related config
|
||||
https:
|
||||
# https port for harbor, default is 443
|
||||
port: 8443
|
||||
# The path of cert and key files for nginx
|
||||
certificate: /Users/brunogao/certs/harbor.lan.pem
|
||||
private_key: /Users/brunogao/certs/harbor.lan-key.pem
|
||||
# enable strong ssl ciphers (default: false)
|
||||
# strong_ssl_ciphers: false
|
||||
|
||||
# # Harbor will set ipv4 enabled only by default if this block is not configured
|
||||
# # Otherwise, please uncomment this block to configure your own ip_family stacks
|
||||
# ip_family:
|
||||
# # ipv6Enabled set to true if ipv6 is enabled in docker network, currently it affected the nginx related component
|
||||
# ipv6:
|
||||
# enabled: false
|
||||
# # ipv4Enabled set to true by default, currently it affected the nginx related component
|
||||
# ipv4:
|
||||
# enabled: true
|
||||
|
||||
# # Uncomment following will enable tls communication between all harbor components
|
||||
# internal_tls:
|
||||
# # set enabled to true means internal tls is enabled
|
||||
# enabled: true
|
||||
# # put your cert and key files on dir
|
||||
# dir: /etc/harbor/tls/internal
|
||||
|
||||
|
||||
# Uncomment external_url if you want to enable external proxy
|
||||
# And when it enabled the hostname will no longer used
|
||||
# external_url: https://reg.mydomain.com:8433
|
||||
|
||||
# The initial password of Harbor admin
|
||||
# It only works in first time to install harbor
|
||||
# Remember Change the admin password from UI after launching Harbor.
|
||||
harbor_admin_password: admin
|
||||
|
||||
# Harbor DB configuration
|
||||
database:
|
||||
# The password for the root user of Harbor DB. Change this before any production use.
|
||||
password: root123
|
||||
# The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
|
||||
max_idle_conns: 100
|
||||
# The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.
|
||||
# Note: the default number of connections is 1024 for postgres of harbor.
|
||||
max_open_conns: 900
|
||||
# The maximum amount of time a connection may be reused. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's age.
|
||||
# The value is a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||
conn_max_lifetime: 5m
|
||||
# The maximum amount of time a connection may be idle. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's idle time.
|
||||
# The value is a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||
conn_max_idle_time: 0
|
||||
|
||||
# The default data volume
|
||||
data_volume: /Users/brunogao/ops/data/harbor
|
||||
|
||||
# Harbor Storage settings by default is using /data dir on local filesystem
|
||||
# Uncomment storage_service setting If you want to using external storage
|
||||
# storage_service:
|
||||
# # ca_bundle is the path to the custom root ca certificate, which will be injected into the truststore
|
||||
# # of registry's containers. This is usually needed when the user hosts a internal storage with self signed certificate.
|
||||
# ca_bundle:
|
||||
|
||||
# # storage backend, default is filesystem, options include filesystem, azure, gcs, s3, swift and oss
|
||||
# # for more info about this configuration please refer https://distribution.github.io/distribution/about/configuration/
|
||||
# # and https://distribution.github.io/distribution/storage-drivers/
|
||||
# filesystem:
|
||||
# maxthreads: 100
|
||||
# # set disable to true when you want to disable registry redirect
|
||||
# redirect:
|
||||
# disable: false
|
||||
|
||||
# Trivy configuration
|
||||
#
|
||||
# Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases.
|
||||
# It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached
|
||||
# in the local file system. In addition, the database contains the update timestamp so Trivy can detect whether it
|
||||
# should download a newer version from the Internet or use the cached one. Currently, the database is updated every
|
||||
# 12 hours and published as a new release to GitHub.
|
||||
trivy:
|
||||
# ignoreUnfixed The flag to display only fixed vulnerabilities
|
||||
ignore_unfixed: false
|
||||
# skipUpdate The flag to enable or disable Trivy DB downloads from GitHub
|
||||
#
|
||||
# You might want to enable this flag in test or CI/CD environments to avoid GitHub rate limiting issues.
|
||||
# If the flag is enabled you have to download the `trivy-offline.tar.gz` archive manually, extract `trivy.db` and
|
||||
# `metadata.json` files and mount them in the `/home/scanner/.cache/trivy/db` path.
|
||||
skip_update: false
|
||||
#
|
||||
# skipJavaDBUpdate If the flag is enabled you have to manually download the `trivy-java.db` file and mount it in the
|
||||
# `/home/scanner/.cache/trivy/java-db/trivy-java.db` path
|
||||
skip_java_db_update: false
|
||||
#
|
||||
# The offline_scan option prevents Trivy from sending API requests to identify dependencies.
|
||||
# Scanning JAR files and pom.xml may require Internet access for better detection, but this option tries to avoid it.
|
||||
# For example, the offline mode will not try to resolve transitive dependencies in pom.xml when the dependency doesn't
|
||||
# exist in the local repositories. It means a number of detected vulnerabilities might be fewer in offline mode.
|
||||
# It would work if all the dependencies are in local.
|
||||
# This option doesn't affect DB download. You need to specify "skip-update" as well as "offline-scan" in an air-gapped environment.
|
||||
offline_scan: false
|
||||
#
|
||||
# Comma-separated list of what security issues to detect. Possible values are `vuln`, `config` and `secret`. Defaults to `vuln`.
|
||||
security_check: vuln
|
||||
#
|
||||
# insecure The flag to skip verifying registry certificate
|
||||
insecure: false
|
||||
#
|
||||
# timeout The duration to wait for scan completion.
|
||||
# There is upper bound of 30 minutes defined in scan job. So if this `timeout` is larger than 30m0s, it will also timeout at 30m0s.
|
||||
timeout: 5m0s
|
||||
#
|
||||
# github_token The GitHub access token to download Trivy DB
|
||||
#
|
||||
# Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough
|
||||
# for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000
|
||||
# requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult
|
||||
# https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting
|
||||
#
|
||||
# You can create a GitHub token by following the instructions in
|
||||
# https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
|
||||
#
|
||||
# github_token: xxx
|
||||
|
||||
jobservice:
|
||||
# Maximum number of job workers in job service
|
||||
max_job_workers: 10
|
||||
# The jobLoggers backend name, only support "STD_OUTPUT", "FILE" and/or "DB"
|
||||
job_loggers:
|
||||
- STD_OUTPUT
|
||||
- FILE
|
||||
# - DB
|
||||
# The jobLogger sweeper duration (ignored if `jobLogger` is `stdout`)
|
||||
logger_sweeper_duration: 1 #days
|
||||
|
||||
notification:
|
||||
# Maximum retry count for webhook job
|
||||
webhook_job_max_retry: 3
|
||||
# HTTP client timeout for webhook job
|
||||
webhook_job_http_client_timeout: 3 #seconds
|
||||
|
||||
# Log configurations
|
||||
log:
|
||||
# options are debug, info, warning, error, fatal
|
||||
level: info
|
||||
# configs for logs in local storage
|
||||
local:
|
||||
# Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated.
|
||||
rotate_count: 50
|
||||
# Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes.
|
||||
# If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G
|
||||
# are all valid.
|
||||
rotate_size: 200M
|
||||
# The directory on your host that store log
|
||||
location: /var/log/harbor
|
||||
|
||||
# Uncomment following lines to enable external syslog endpoint.
|
||||
# external_endpoint:
|
||||
# # protocol used to transmit log to external endpoint, options is tcp or udp
|
||||
# protocol: tcp
|
||||
# # The host of external endpoint
|
||||
# host: localhost
|
||||
# # Port of external endpoint
|
||||
# port: 5140
|
||||
|
||||
#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
|
||||
_version: 2.11.0
|
||||
|
||||
# Uncomment external_database if using external database.
|
||||
# external_database:
|
||||
# harbor:
|
||||
# host: harbor_db_host
|
||||
# port: harbor_db_port
|
||||
# db_name: harbor_db_name
|
||||
# username: harbor_db_username
|
||||
# password: harbor_db_password
|
||||
# ssl_mode: disable
|
||||
# max_idle_conns: 2
|
||||
# max_open_conns: 0
|
||||
|
||||
# Uncomment redis if need to customize redis db
|
||||
# redis:
|
||||
# # db_index 0 is for core, it's unchangeable
|
||||
# # registry_db_index: 1
|
||||
# # jobservice_db_index: 2
|
||||
# # trivy_db_index: 5
|
||||
# # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it.
|
||||
# # harbor_db_index: 6
|
||||
# # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it.
|
||||
# # cache_layer_db_index: 7
|
||||
|
||||
# Uncomment external_redis if using external Redis server
|
||||
# external_redis:
|
||||
# # support redis, redis+sentinel
|
||||
# # host for redis: <host_redis>:<port_redis>
|
||||
# # host for redis+sentinel:
|
||||
# # <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
|
||||
# host: redis:6379
|
||||
# password:
|
||||
# # Redis AUTH command was extended in Redis 6, it is possible to use it in the two-arguments AUTH <username> <password> form.
|
||||
# # there's a known issue when using external redis username ref:https://github.com/goharbor/harbor/issues/18892
|
||||
# # if you care about the image pull/push performance, please refer to this https://github.com/goharbor/harbor/wiki/Harbor-FAQs#external-redis-username-password-usage
|
||||
# # username:
|
||||
# # sentinel_master_set must be set to support redis+sentinel
|
||||
# #sentinel_master_set:
|
||||
# # db_index 0 is for core, it's unchangeable
|
||||
# registry_db_index: 1
|
||||
# jobservice_db_index: 2
|
||||
# trivy_db_index: 5
|
||||
# idle_timeout_seconds: 30
|
||||
# # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it.
|
||||
# # harbor_db_index: 6
|
||||
# # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it.
|
||||
# # cache_layer_db_index: 7
|
||||
|
||||
# Uncomment uaa for trusting the certificate of uaa instance that is hosted via self-signed cert.
|
||||
# uaa:
|
||||
# ca_file: /path/to/ca
|
||||
|
||||
# Global proxy
|
||||
# Config http proxy for components, e.g. http://my.proxy.com:3128
|
||||
# Components doesn't need to connect to each others via http proxy.
|
||||
# Remove component from `components` array if want disable proxy
|
||||
# for it. If you want use proxy for replication, MUST enable proxy
|
||||
# for core and jobservice, and set `http_proxy` and `https_proxy`.
|
||||
# Add domain to the `no_proxy` field, when you want disable proxy
|
||||
# for some special registry.
|
||||
proxy:
|
||||
http_proxy:
|
||||
https_proxy:
|
||||
no_proxy:
|
||||
components:
|
||||
- core
|
||||
- jobservice
|
||||
- trivy
|
||||
|
||||
# metric:
|
||||
# enabled: false
|
||||
# port: 9090
|
||||
# path: /metrics
|
||||
|
||||
# Trace related config
|
||||
# only can enable one trace provider(jaeger or otel) at the same time,
|
||||
# and when using jaeger as provider, can only enable it with agent mode or collector mode.
|
||||
# if using jaeger collector mode, uncomment endpoint and uncomment username, password if needed
|
||||
# if using jaeger agetn mode uncomment agent_host and agent_port
|
||||
# trace:
|
||||
# enabled: true
|
||||
# # set sample_rate to 1 if you wanna sampling 100% of trace data; set 0.5 if you wanna sampling 50% of trace data, and so forth
|
||||
# sample_rate: 1
|
||||
# # # namespace used to differentiate different harbor services
|
||||
# # namespace:
|
||||
# # # attributes is a key value dict contains user defined attributes used to initialize trace provider
|
||||
# # attributes:
|
||||
# # application: harbor
|
||||
# # # jaeger should be 1.26 or newer.
|
||||
# # jaeger:
|
||||
# # endpoint: http://hostname:14268/api/traces
|
||||
# # username:
|
||||
# # password:
|
||||
# # agent_host: hostname
|
||||
# # # export trace data by jaeger.thrift in compact mode
|
||||
# # agent_port: 6831
|
||||
# # otel:
|
||||
# # endpoint: hostname:4318
|
||||
# # url_path: /v1/traces
|
||||
# # compression: false
|
||||
# # insecure: true
|
||||
# # # timeout is in seconds
|
||||
# # timeout: 10
|
||||
|
||||
# Enable purge _upload directories
|
||||
upload_purging:
|
||||
enabled: true
|
||||
# remove files in _upload directories which exist for a period of time, default is one week.
|
||||
age: 168h
|
||||
# the interval of the purge operations
|
||||
interval: 24h
|
||||
dryrun: false
|
||||
|
||||
# Cache layer configurations
|
||||
# If this feature enabled, harbor will cache the resource
|
||||
# `project/project_metadata/repository/artifact/manifest` in the redis
|
||||
# which can especially help to improve the performance of high concurrent
|
||||
# manifest pulling.
|
||||
# NOTICE
|
||||
# If you are deploying Harbor in HA mode, make sure that all the harbor
|
||||
# instances have the same behaviour, all with caching enabled or disabled,
|
||||
# otherwise it can lead to potential data inconsistency.
|
||||
cache:
|
||||
# not enabled by default
|
||||
enabled: false
|
||||
# keep cache for one day by default
|
||||
expire_hours: 24
|
||||
|
||||
# Harbor core configurations
|
||||
# Uncomment to enable the following harbor core related configuration items.
|
||||
# core:
|
||||
# # The provider for updating project quota(usage), there are 2 options, redis or db,
|
||||
# # by default is implemented by db but you can switch the updation via redis which
|
||||
# # can improve the performance of high concurrent pushing to the same project,
|
||||
# # and reduce the database connections spike and occupies.
|
||||
# # By redis will bring up some delay for quota usage updation for display, so only
|
||||
# # suggest switch provider to redis if you were ran into the db connections spike around
|
||||
# # the scenario of high concurrent pushing to same project, no improvement for other scenes.
|
||||
# quota_update_provider: redis # Or db
|
||||
+108
@@ -75,7 +75,11 @@ create_base_structure() {
|
||||
"${OPS_DIR}/data"
|
||||
"${OPS_DIR}/backups/brew"
|
||||
"${OPS_DIR}/backups/gitea"
|
||||
"${OPS_DIR}/backups/harbor"
|
||||
"${OPS_DIR}/backups/gitlab"
|
||||
"${OPS_DIR}/data/gitea"
|
||||
"${OPS_DIR}/data/harbor"
|
||||
"${OPS_DIR}/data/gitlab"
|
||||
)
|
||||
|
||||
for dir in "${dirs[@]}"; do
|
||||
@@ -184,6 +188,110 @@ deploy_gitea_module() {
|
||||
fi
|
||||
}
|
||||
|
||||
# 部署 harbor 模块
|
||||
deploy_harbor_module() {
|
||||
if [[ "$DOCKER_AVAILABLE" != true ]]; then
|
||||
warn "跳过 harbor 模块部署(Docker 未安装)"
|
||||
return
|
||||
fi
|
||||
|
||||
log "🐙 部署 Harbor 维护模块..."
|
||||
|
||||
local harbor_target_dir="${OPS_DIR}/harbor"
|
||||
|
||||
# 创建目录
|
||||
mkdir -p "$harbor_target_dir"
|
||||
|
||||
# 复制文件
|
||||
local files=(
|
||||
"harbor/harbor.yml"
|
||||
"harbor/docker-compose.yml"
|
||||
"harbor/harbor-data-protection.sh"
|
||||
"harbor/harbor-backup.sh"
|
||||
"harbor/harbor-restore.sh"
|
||||
"harbor/.env.example"
|
||||
"harbor/common"
|
||||
"harbor/README.md"
|
||||
)
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
local src="${PROJECT_ROOT}/$file"
|
||||
local dst="${harbor_target_dir}/$(basename "$file")"
|
||||
|
||||
if [[ -f "$src" ]] || [[ -d "$src" ]]; then
|
||||
if [[ -d "$src" ]]; then
|
||||
cp -r "$src" "$dst"
|
||||
else
|
||||
cp "$src" "$dst"
|
||||
fi
|
||||
chmod +x "$dst" 2>/dev/null || true # 只对脚本设置可执行权限
|
||||
log "✅ 复制: $(basename "$file")"
|
||||
else
|
||||
warn "文件不存在: $src"
|
||||
fi
|
||||
done
|
||||
|
||||
# 创建 .env 文件(如果不存在)
|
||||
local env_file="${harbor_target_dir}/.env"
|
||||
if [[ ! -f "$env_file" ]] && [[ -f "${PROJECT_ROOT}/harbor/.env.example" ]]; then
|
||||
cp "${PROJECT_ROOT}/harbor/.env.example" "$env_file"
|
||||
log "✅ 创建环境配置文件: .env"
|
||||
info "💡 请根据需要编辑 ${env_file}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 部署 gitlab 模块
|
||||
deploy_gitlab_module() {
|
||||
if [[ "$DOCKER_AVAILABLE" != true ]]; then
|
||||
warn "跳过 gitlab 模块部署(Docker 未安装)"
|
||||
return
|
||||
fi
|
||||
|
||||
log "🦊 部署 GitLab 维护模块..."
|
||||
|
||||
local gitlab_target_dir="${OPS_DIR}/gitlab"
|
||||
|
||||
# 创建目录
|
||||
mkdir -p "$gitlab_target_dir"
|
||||
|
||||
# 复制文件
|
||||
local files=(
|
||||
"gitlab/docker-compose.yml"
|
||||
"gitlab/gitlab-data-protection.sh"
|
||||
"gitlab/gitlab-backup.sh"
|
||||
"gitlab/gitlab-restore.sh"
|
||||
"gitlab/.env.example"
|
||||
"gitlab/README.md"
|
||||
)
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
local src="${PROJECT_ROOT}/$file"
|
||||
local dst="${gitlab_target_dir}/$(basename "$file")"
|
||||
|
||||
if [[ -f "$src" ]]; then
|
||||
cp "$src" "$dst"
|
||||
chmod +x "$dst" 2>/dev/null || true # 只对脚本设置可执行权限
|
||||
log "✅ 复制: $(basename "$file")"
|
||||
else
|
||||
warn "文件不存在: $src"
|
||||
fi
|
||||
done
|
||||
|
||||
# 复制配置目录
|
||||
if [[ -d "${PROJECT_ROOT}/gitlab/config" ]]; then
|
||||
cp -r "${PROJECT_ROOT}/gitlab/config" "${gitlab_target_dir}/"
|
||||
log "✅ 复制: config/"
|
||||
fi
|
||||
|
||||
# 创建 .env 文件(如果不存在)
|
||||
local env_file="${gitlab_target_dir}/.env"
|
||||
if [[ ! -f "$env_file" ]] && [[ -f "${PROJECT_ROOT}/gitlab/.env.example" ]]; then
|
||||
cp "${PROJECT_ROOT}/gitlab/.env.example" "$env_file"
|
||||
log "✅ 创建环境配置文件: .env"
|
||||
info "💡 请根据需要编辑 ${env_file}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建项目总 README
|
||||
create_main_readme() {
|
||||
local readme_file="${OPS_DIR}/README.md"
|
||||
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Claude Bluebook Context Generator (v1.2)
|
||||
自动生成Claude开发上下文
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
def generate_context():
|
||||
"""生成Claude上下文"""
|
||||
project_root = Path.cwd()
|
||||
|
||||
context = f"""# Claude AI Development Context v1.2
|
||||
|
||||
## Project Information
|
||||
**Name**: {project_root.name}
|
||||
**Root**: {project_root}
|
||||
**Copyright**: © 2025 灵境万象智能科技有限公司
|
||||
|
||||
## Current Development Phase
|
||||
**Phase**: AI-Powered Development
|
||||
**Focus**: High-quality enterprise-grade development
|
||||
|
||||
## Quality Standards
|
||||
**Code Quality**:
|
||||
- Type coverage: ≥90%
|
||||
- Test coverage: ≥80%
|
||||
- Code quality: ≥B级
|
||||
|
||||
**Performance**:
|
||||
- API response P95: ≤3s
|
||||
- Concurrent users: ≥1000
|
||||
- CPU usage: ≤70%
|
||||
|
||||
**Security**:
|
||||
- Zero high-severity vulnerabilities
|
||||
- OWASP Top 10 compliance
|
||||
- Authentication and authorization complete
|
||||
|
||||
## Development Guidelines
|
||||
1. **Enterprise-Grade Code**: Industry best practices with comprehensive documentation
|
||||
2. **Quality-First**: All quality gates must be passed
|
||||
3. **Security-First**: Security by design and default
|
||||
4. **Performance-Optimized**: Efficient, scalable code
|
||||
5. **Well-Tested**: High test coverage and automated quality checks
|
||||
|
||||
## My Role & Approach
|
||||
**Role**: Senior Full-Stack Developer specializing in AI-powered systems
|
||||
**Approach**:
|
||||
- Structured responses with clear progress tracking
|
||||
- Ask clarifying questions when requirements are ambiguous
|
||||
- Suggest improvements and alternative approaches
|
||||
- Focus on practical, maintainable, enterprise-grade solutions
|
||||
|
||||
## Quality Assurance
|
||||
All deliverables validated against:
|
||||
- Functional requirements ✓
|
||||
- Performance benchmarks ✓
|
||||
- Security standards ✓
|
||||
- Code quality metrics ✓
|
||||
- Documentation completeness ✓
|
||||
|
||||
Let's build high-quality, enterprise-grade software together!
|
||||
"""
|
||||
|
||||
return context.strip()
|
||||
|
||||
def main():
|
||||
context = generate_context()
|
||||
cache_file = Path.cwd() / ".claude-bluebook-cache.json"
|
||||
|
||||
cache_data = {
|
||||
"version": "2.0.0",
|
||||
"copyright": "© 2025 灵境万象智能科技有限公司",
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"claude_context": context
|
||||
}
|
||||
|
||||
with open(cache_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(cache_data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"✅ Context saved to: {cache_file}")
|
||||
print("🚀 Ready for Claude AI collaboration!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user