add
This commit is contained in:
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@@ -33,6 +33,9 @@ fi
|
|||||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||||
|
# 添加最高级别的可读写权限
|
||||||
|
sudo chmod 777 "${TAR_FILE}"
|
||||||
|
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||||
else
|
else
|
||||||
echo "错误:镜像打包失败" >&2
|
echo "错误:镜像打包失败" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
166
build.py
166
build.py
@@ -1,5 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
import shutil # 新增导入shutil用于文件复制
|
import shutil
|
||||||
import yaml
|
import yaml
|
||||||
import subprocess
|
import subprocess
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
@@ -26,7 +26,6 @@ def run_shell_command(command: str, cwd: str = None) -> bool:
|
|||||||
def cleanup_dangling_images() -> bool:
|
def cleanup_dangling_images() -> bool:
|
||||||
"""清除docker虚悬镜像(dangling images)"""
|
"""清除docker虚悬镜像(dangling images)"""
|
||||||
print("开始清除虚悬镜像...")
|
print("开始清除虚悬镜像...")
|
||||||
# 清除所有<none>:<none>的虚悬镜像,xargs -r确保无镜像时不执行删除命令
|
|
||||||
return run_shell_command('sudo docker images -f "dangling=true" -q | xargs -r sudo docker rmi')
|
return run_shell_command('sudo docker images -f "dangling=true" -q | xargs -r sudo docker rmi')
|
||||||
|
|
||||||
def execute_release_scripts(root_dir: str) -> bool:
|
def execute_release_scripts(root_dir: str) -> bool:
|
||||||
@@ -35,8 +34,13 @@ def execute_release_scripts(root_dir: str) -> bool:
|
|||||||
|
|
||||||
# 定义目标镜像目录
|
# 定义目标镜像目录
|
||||||
images_dir = os.path.join(root_dir, 'deploy', 'images')
|
images_dir = os.path.join(root_dir, 'deploy', 'images')
|
||||||
# 确保目标目录存在
|
# 确保目标目录存在并设置权限
|
||||||
os.makedirs(images_dir, exist_ok=True)
|
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):
|
for dir_name in os.listdir(root_dir):
|
||||||
# 排除api_template文件夹
|
# 排除api_template文件夹
|
||||||
@@ -65,12 +69,47 @@ def execute_release_scripts(root_dir: str) -> bool:
|
|||||||
if file.endswith('.tar'):
|
if file.endswith('.tar'):
|
||||||
src_path = os.path.join(dir_path, file)
|
src_path = os.path.join(dir_path, file)
|
||||||
dest_path = os.path.join(images_dir, 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):
|
if os.path.exists(dest_path):
|
||||||
os.remove(dest_path)
|
try:
|
||||||
# 复制文件
|
os.remove(dest_path)
|
||||||
shutil.copy2(src_path, dest_path)
|
print(f"已删除旧文件: {dest_path}")
|
||||||
print(f"已将 {src_path} 替换复制到 {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}")
|
||||||
|
except PermissionError:
|
||||||
|
print(f"错误:复制 {src_path} 失败(权限不足)")
|
||||||
|
print("建议:使用 sudo 权限重新运行脚本(sudo python3 build.py)")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"复制文件时发生错误: {str(e)},跳过该文件")
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
print(f"{dir_path} 中未找到release.sh,跳过")
|
print(f"{dir_path} 中未找到release.sh,跳过")
|
||||||
|
|
||||||
@@ -80,24 +119,20 @@ def execute_release_scripts(root_dir: str) -> bool:
|
|||||||
def merge_yaml_files(root_dir: str) -> Dict[str, Any]:
|
def merge_yaml_files(root_dir: str) -> Dict[str, Any]:
|
||||||
"""合并所有 docker-compose 相关 YAML 文件内容(排除api_template)"""
|
"""合并所有 docker-compose 相关 YAML 文件内容(排除api_template)"""
|
||||||
merged = {
|
merged = {
|
||||||
'version': '3.8', # 默认使用 3.8 版本
|
'version': '3.8',
|
||||||
'services': {},
|
'services': {},
|
||||||
'networks': {},
|
'networks': {},
|
||||||
'volumes': {}
|
'volumes': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 查找所有 docker-compose 相关 YAML 文件
|
|
||||||
yaml_files = []
|
yaml_files = []
|
||||||
# 1. 根目录下的 docker-compose.*.yaml
|
# 根目录下的 docker-compose.*.yaml
|
||||||
for file in os.listdir(root_dir):
|
for file in os.listdir(root_dir):
|
||||||
if file.startswith('docker-compose.') and file.endswith('.yaml'):
|
if file.startswith('docker-compose.') and file.endswith('.yaml') and file != 'docker-compose.yaml':
|
||||||
if file == 'docker-compose.yaml': # 跳过目标文件本身
|
|
||||||
continue
|
|
||||||
yaml_files.append(os.path.join(root_dir, file))
|
yaml_files.append(os.path.join(root_dir, file))
|
||||||
|
|
||||||
# 2. api_ 目录下的 docker-compose.*.yaml(排除api_template)
|
# api_ 目录下的 docker-compose.*.yaml(排除api_template)
|
||||||
for dir_name in os.listdir(root_dir):
|
for dir_name in os.listdir(root_dir):
|
||||||
# 排除api_template文件夹
|
|
||||||
if dir_name == "api_template":
|
if dir_name == "api_template":
|
||||||
print(f"跳过模板目录的yaml文件: {dir_name}")
|
print(f"跳过模板目录的yaml文件: {dir_name}")
|
||||||
continue
|
continue
|
||||||
@@ -111,34 +146,50 @@ def merge_yaml_files(root_dir: str) -> Dict[str, Any]:
|
|||||||
# 合并所有 YAML 文件内容
|
# 合并所有 YAML 文件内容
|
||||||
for file_path in yaml_files:
|
for file_path in yaml_files:
|
||||||
print(f"合并文件: {file_path}")
|
print(f"合并文件: {file_path}")
|
||||||
with open(file_path, 'r', encoding='utf-8') as f:
|
try:
|
||||||
try:
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
data = yaml.safe_load(f)
|
data = yaml.safe_load(f)
|
||||||
if not data:
|
if not data:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 合并 services
|
|
||||||
if 'services' in data:
|
if 'services' in data:
|
||||||
merged['services'].update(data['services'])
|
merged['services'].update(data['services'])
|
||||||
|
|
||||||
# 合并 networks
|
|
||||||
if 'networks' in data:
|
if 'networks' in data:
|
||||||
merged['networks'].update(data['networks'])
|
merged['networks'].update(data['networks'])
|
||||||
|
|
||||||
# 合并 volumes
|
|
||||||
if 'volumes' in data:
|
if 'volumes' in data:
|
||||||
merged['volumes'].update(data['volumes'])
|
merged['volumes'].update(data['volumes'])
|
||||||
|
|
||||||
# 保留最高版本号
|
|
||||||
if 'version' in data and data['version'] > merged['version']:
|
if 'version' in data and data['version'] > merged['version']:
|
||||||
merged['version'] = data['version']
|
merged['version'] = data['version']
|
||||||
|
|
||||||
except yaml.YAMLError as e:
|
except yaml.YAMLError as e:
|
||||||
print(f"解析 {file_path} 失败: {e}")
|
print(f"解析 {file_path} 失败: {e}")
|
||||||
continue
|
continue
|
||||||
|
except PermissionError:
|
||||||
|
print(f"错误:无权限读取 {file_path},跳过该文件")
|
||||||
|
continue
|
||||||
|
|
||||||
return merged
|
return merged
|
||||||
|
|
||||||
|
def stop_docker_compose(root_dir: str) -> bool:
|
||||||
|
"""停止docker-compose"""
|
||||||
|
print("开始停止docker-compose...")
|
||||||
|
compose_file = os.path.join(root_dir, 'docker-compose.yaml')
|
||||||
|
if not os.path.exists(compose_file):
|
||||||
|
print(f"未找到docker-compose文件: {compose_file}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return run_shell_command(f"sudo docker-compose -f {compose_file} down", root_dir)
|
||||||
|
|
||||||
|
def start_docker_compose(root_dir: str) -> bool:
|
||||||
|
"""启动docker-compose"""
|
||||||
|
print("开始启动docker-compose...")
|
||||||
|
compose_file = os.path.join(root_dir, 'docker-compose.yaml')
|
||||||
|
if not os.path.exists(compose_file):
|
||||||
|
print(f"未找到docker-compose文件: {compose_file}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return run_shell_command(f"sudo docker-compose -f {compose_file} up -d", root_dir)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# 先执行清除虚悬镜像操作
|
# 先执行清除虚悬镜像操作
|
||||||
print("部署流程开始,先执行清除虚悬镜像操作...")
|
print("部署流程开始,先执行清除虚悬镜像操作...")
|
||||||
@@ -161,25 +212,48 @@ def main():
|
|||||||
|
|
||||||
# 输出到根目录的docker-compose.yaml
|
# 输出到根目录的docker-compose.yaml
|
||||||
output_path = os.path.join(root_dir, 'docker-compose.yaml')
|
output_path = os.path.join(root_dir, 'docker-compose.yaml')
|
||||||
with open(output_path, 'w', encoding='utf-8') as f:
|
try:
|
||||||
yaml.dump(
|
with open(output_path, 'w', encoding='utf-8') as f:
|
||||||
merged_data,
|
yaml.dump(
|
||||||
f,
|
merged_data,
|
||||||
sort_keys=False, # 保持键的顺序
|
f,
|
||||||
allow_unicode=True, # 支持中文
|
sort_keys=False,
|
||||||
default_flow_style=False # 使用块样式
|
allow_unicode=True,
|
||||||
)
|
default_flow_style=False
|
||||||
print(f"已生成合并后的 docker-compose.yaml: {output_path}")
|
)
|
||||||
|
print(f"已生成合并后的 docker-compose.yaml: {output_path}")
|
||||||
|
|
||||||
# 将新的docker-compose.yaml以替换方式复制到根目录的deploy/下
|
# 将新的docker-compose.yaml以替换方式复制到根目录的deploy/下
|
||||||
deploy_dir = os.path.join(root_dir, 'deploy')
|
deploy_dir = os.path.join(root_dir, 'deploy')
|
||||||
os.makedirs(deploy_dir, exist_ok=True) # 确保deploy目录存在
|
os.makedirs(deploy_dir, exist_ok=True)
|
||||||
dest_compose_path = os.path.join(deploy_dir, 'docker-compose.yaml')
|
# 确保deploy目录可写
|
||||||
# 替换方式复制:若目标存在则先删除
|
try:
|
||||||
if os.path.exists(dest_compose_path):
|
os.chmod(deploy_dir, 0o755)
|
||||||
os.remove(dest_compose_path)
|
except PermissionError:
|
||||||
shutil.copy2(output_path, dest_compose_path)
|
print(f"警告:无法修改目录权限 {deploy_dir}")
|
||||||
print(f"已将 {output_path} 替换复制到 {dest_compose_path}")
|
|
||||||
|
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===== 清理虚悬镜像 =====")
|
print("\n===== 清理虚悬镜像 =====")
|
||||||
if not cleanup_dangling_images():
|
if not cleanup_dangling_images():
|
||||||
|
Reference in New Issue
Block a user