This commit is contained in:
vipg
2025-10-09 16:38:20 +08:00
parent 81632fa5d3
commit 7e9930ae6b
2 changed files with 158 additions and 254 deletions

159
README.md
View File

@@ -1 +1,158 @@
# REAMDME
# 用户服务部署使用手册
## 一、概述
本文档介绍用户服务系统的创建、构建和部署流程,涉及`create_api.py``build.py``deploy/deploy.sh`三个核心脚本的使用方法帮助使用者快速搭建和部署用户服务相关的API模块。
## 二、环境准备
1. 确保系统安装以下工具:
- Python 3.x
- Docker
- Docker Compose
2. 克隆代码库后,进入项目根目录:
```bash
cd user_service
```
## 三、核心脚本功能说明
### 1. 创建新API服务create_api.py
用于基于模板快速创建新的API服务模块自动生成目录结构和配置文件。
#### 使用方法:
1. 编辑`create_api.py`文件,设置`a`(功能名)和`b`(次功能名)参数:
```python
a = "aaaa" # 主功能名
b = "bbbb" # 次功能名(可选,如果不需要,留空)
```
2. 执行脚本:
```bash
sudo python3 create_api.py
```
#### 功能说明:
- 自动在`deploy/api`目录下创建新服务目录(格式:`api_{a}_{b}` 或 `api_{a}`
- 复制`api_template`模板文件并替换其中的占位符
- 生成对应的`docker-compose.{a}.{b}.yaml`或`docker-compose.{a}.yaml`文件
- 自动修改`release.sh`、`init.py`和`README.md`中的服务标识
### 2. 构建API服务镜像build.py
用于批量构建所有API服务的Docker镜像并将构建结果整理到指定目录。
#### 使用方法:
```bash
python3 build.py
```
#### 功能说明:
1. 遍历所有以`api_`开头的目录(排除`api_template`
2. 执行每个目录下的`release.sh`脚本:
- 为脚本添加执行权限
- 运行脚本删除旧镜像并构建新镜像
3. 收集构建生成的`.tar`镜像文件:
- 复制到`deploy/images`目录
- 自动处理文件权限问题
- 清理原始目录中的`.tar`文件
#### 注意事项:
- 若遇到权限问题,可尝试使用`sudo`运行:
```bash
sudo python3 build.py
```
- 脚本会自动跳过不存在`release.sh`的目录
### 3. 部署服务deploy/deploy.sh
用于停止现有服务、构建API并启动新的Docker Compose编排。
#### 使用方法:
```bash
cd deploy
./deploy.sh
```
#### 功能说明:
1. **步骤1停止现有服务**
- 停止`docker-compose.yaml`定义的`user_service`项目
2. **步骤2构建所有API服务**
- 遍历`./api`目录下的所有服务
- 执行每个服务的`release.sh`脚本
- 若构建失败则终止部署流程
3. **步骤3启动新服务**
- 使用`docker-compose.yaml`启动服务
- 项目名称为`user_service`
#### 配置说明:
脚本开头可修改以下配置参数:
```bash
COMPOSE_PROJECT_NAME="user_service" # Docker Compose项目名称
DOCKER_COMPOSE_FILE="./docker-compose.yaml" # 配置文件路径
API_DIR="./api" # API服务所在目录
```
## 四、完整工作流程
1. **创建新API服务**
```bash
# 编辑create_api.py设置功能名
python3 create_api.py
```
2. **开发API功能**
- 在生成的`deploy/api/api_{a}_{b}`目录中编写代码(如`main.go`
- 根据需要修改`init.py`中的初始化逻辑
3. **构建服务镜像**
```bash
python3 build.py
```
4. **部署服务**
```bash
cd deploy
./deploy.sh
```
## 五、常见问题处理
1. **权限错误**
- 执行脚本时若出现`Permission denied`,尝试添加执行权限:
```bash
chmod +x deploy/deploy.sh
```
- 或使用`sudo`运行相关命令
2. **镜像构建失败**
- 检查`release.sh`中的镜像名称和构建命令是否正确
- 确保Docker服务正常运行`systemctl status docker`
3. **服务启动失败**
- 检查`docker-compose.yaml`配置是否正确
- 查看容器日志排查问题:`docker logs <容器名>`
4. **端口冲突**
- 若启动时提示端口被占用,修改`init.py`中的端口映射配置
## 六、服务目录结构说明
成功创建并部署后,项目主要目录结构如下:
```
user_service_副本/
├── deploy/
│ ├── api/ # 所有API服务目录
│ │ ├── api_login/ # 登录服务
│ │ ├── api_register/ # 注册服务
│ │ └── ... # 其他API服务
│ ├── images/ # 构建好的镜像文件
│ ├── docker-compose.yaml # 服务编排配置
│ └── deploy.sh # 部署脚本
├── create_api.py # 创建新API的脚本
└── build.py # 构建镜像的脚本
```

253
build.py
View File

@@ -1,253 +0,0 @@
import os
import shutil
import yaml
import subprocess
from typing import Dict, Any
def run_shell_command(command: str, cwd: str = None) -> bool:
"""执行shell命令并返回执行结果"""
try:
print(f"执行命令: {command} (工作目录: {cwd or os.getcwd()})")
result = subprocess.run(
command,
cwd=cwd,
shell=True,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
print(f"命令输出: {result.stdout}")
return True
except subprocess.CalledProcessError as e:
print(f"命令执行失败: {e.stderr}")
return False
def cleanup_dangling_images() -> bool:
"""清除docker虚悬镜像dangling images"""
print("开始清除虚悬镜像...")
return run_shell_command('sudo docker images -f "dangling=true" -q | xargs -r sudo docker rmi')
def execute_release_scripts(root_dir: str) -> bool:
"""遍历所有api_目录并执行release.sh脚本排除api_template"""
print("开始执行所有api_目录下的release.sh脚本...")
# 定义目标镜像目录
images_dir = os.path.join(root_dir, 'deploy', 'images')
# 确保目标目录存在并设置权限
os.makedirs(images_dir, exist_ok=True)
# 尝试设置目录可写权限(解决目标目录权限问题)
try:
os.chmod(images_dir, 0o755)
except PermissionError:
print(f"警告:无法修改目录权限 {images_dir},可能导致文件复制失败")
for dir_name in os.listdir(root_dir):
# 排除api_template文件夹
if dir_name == "api_template":
print(f"跳过模板目录: {dir_name}")
continue
dir_path = os.path.join(root_dir, dir_name)
if os.path.isdir(dir_path) and dir_name.startswith('api_'):
release_script = os.path.join(dir_path, 'release.sh')
if os.path.exists(release_script):
print(f"处理目录: {dir_path}")
# 添加执行权限
if not run_shell_command(f"chmod +x {release_script}", dir_path):
print(f"{release_script} 添加权限失败,跳过执行")
continue
# 执行release.sh
if not run_shell_command(f"./release.sh", dir_path):
print(f"{release_script} 执行失败,跳过后续步骤")
return False
# 复制目录下的.tar文件到根目录的deploy/images下替换方式
for file in os.listdir(dir_path):
if file.endswith('.tar'):
src_path = os.path.join(dir_path, file)
dest_path = os.path.join(images_dir, file)
# 检查源文件是否存在且可读
if not os.path.exists(src_path):
print(f"警告:源文件不存在 {src_path},跳过")
continue
if not os.access(src_path, os.R_OK):
print(f"警告:无权限读取 {src_path},尝试修复权限...")
try:
# 尝试赋予源文件读权限
os.chmod(src_path, 0o644)
# 再次检查权限
if not os.access(src_path, os.R_OK):
print(f"错误:仍无法读取 {src_path},请手动检查权限")
continue
except PermissionError:
print(f"错误:无法修复 {src_path} 权限,跳过该文件")
continue
# 处理目标文件
if os.path.exists(dest_path):
try:
os.remove(dest_path)
print(f"已删除旧文件: {dest_path}")
except PermissionError:
print(f"警告:无权限删除旧文件 {dest_path}尝试用sudo运行脚本")
continue
# 复制文件(带权限处理)
try:
shutil.copy2(src_path, dest_path)
# 复制后确保目标文件可读写
os.chmod(dest_path, 0o644)
print(f"已将 {src_path} 替换复制到 {dest_path}")
# 复制成功后删除原文件
try:
os.remove(src_path)
print(f"已删除原文件: {src_path}")
except PermissionError:
print(f"警告:无权限删除原文件 {src_path},请手动清理")
except Exception as e:
print(f"删除原文件 {src_path} 时发生错误: {str(e)}")
except PermissionError:
print(f"错误:复制 {src_path} 失败(权限不足)")
print("建议:使用 sudo 权限重新运行脚本sudo python3 build.py")
return False
except Exception as e:
print(f"复制文件时发生错误: {str(e)},跳过该文件")
continue
else:
print(f"{dir_path} 中未找到release.sh跳过")
print("所有release.sh脚本执行完成")
return True
def merge_yaml_files(root_dir: str) -> Dict[str, Any]:
"""合并所有 docker-compose 相关 YAML 文件内容排除api_template"""
merged = {
'services': {},
'networks': {},
'volumes': {}
}
yaml_files = []
# 根目录下的 docker-compose.*.yaml
for file in os.listdir(root_dir):
if file.startswith('docker-compose.') and file.endswith('.yaml') and file != 'docker-compose.yaml':
yaml_files.append(os.path.join(root_dir, file))
# api_ 目录下的 docker-compose.*.yaml排除api_template
for dir_name in os.listdir(root_dir):
if dir_name == "api_template":
print(f"跳过模板目录的yaml文件: {dir_name}")
continue
dir_path = os.path.join(root_dir, dir_name)
if os.path.isdir(dir_path) and dir_name.startswith('api_'):
for file in os.listdir(dir_path):
if file.startswith('docker-compose.') and file.endswith('.yaml'):
yaml_files.append(os.path.join(dir_path, file))
# 合并所有 YAML 文件内容
for file_path in yaml_files:
print(f"合并文件: {file_path}")
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
if not data:
continue
if 'services' in data:
merged['services'].update(data['services'])
if 'networks' in data:
merged['networks'].update(data['networks'])
if 'volumes' in data:
merged['volumes'].update(data['volumes'])
except yaml.YAMLError as e:
print(f"解析 {file_path} 失败: {e}")
continue
except PermissionError:
print(f"错误:无权限读取 {file_path},跳过该文件")
continue
return merged
def main():
# 先执行清除虚悬镜像操作
print("部署流程开始,先执行清除虚悬镜像操作...")
if not cleanup_dangling_images():
print("清除虚悬镜像失败(非致命错误,继续部署流程)")
else:
print("虚悬镜像清除完成")
# 获取项目根目录deploy.py 所在目录)
root_dir = os.path.dirname(os.path.abspath(__file__))
print(f"项目根目录: {root_dir}")
# 1. 执行所有api_目录下的release.sh脚本
if not execute_release_scripts(root_dir):
print("执行release脚本失败终止部署流程")
return
# 2. 合并所有YAML文件
merged_data = merge_yaml_files(root_dir)
# 输出到根目录的docker-compose.yaml
output_path = os.path.join(root_dir, 'docker-compose.yaml')
try:
with open(output_path, 'w', encoding='utf-8') as f:
yaml.dump(
merged_data,
f,
sort_keys=False,
allow_unicode=True,
default_flow_style=False
)
print(f"已生成合并后的 docker-compose.yaml: {output_path}")
# 将新的docker-compose.yaml以替换方式复制到根目录的deploy/下
deploy_dir = os.path.join(root_dir, 'deploy')
os.makedirs(deploy_dir, exist_ok=True)
# 确保deploy目录可写
try:
os.chmod(deploy_dir, 0o755)
except PermissionError:
print(f"警告:无法修改目录权限 {deploy_dir}")
dest_compose_path = os.path.join(deploy_dir, 'docker-compose.yaml')
# 替换方式复制
if os.path.exists(dest_compose_path):
try:
os.remove(dest_compose_path)
except PermissionError:
print(f"警告:无权限删除旧文件 {dest_compose_path}")
return False
shutil.copy2(output_path, dest_compose_path)
# 设置目标文件权限
os.chmod(dest_compose_path, 0o644)
print(f"已将 {output_path} 替换复制到 {dest_compose_path}")
except PermissionError as e:
print(f"错误:无权限操作文件 {output_path}{dest_compose_path}")
print(f"详细错误: {str(e)}")
print("建议:使用 sudo 权限重新运行脚本sudo python3 build.py")
return False
except Exception as e:
print(f"生成或复制docker-compose.yaml时出错: {str(e)}")
return False
print("\n===== 清理虚悬镜像 =====")
if not cleanup_dangling_images():
print("清除虚悬镜像失败(非致命错误,继续部署流程)")
else:
print("虚悬镜像清除完成")
if __name__ == "__main__":
# 需要安装 pyyaml 库: pip install pyyaml
main()