1. 环境要求
| 项目 | 要求 |
|---|---|
| 操作系统 | OpenCloudOS 9.4 |
| 内存 | 最低 2GB,推荐 4GB+ |
| 磁盘 | 最低 20GB 可用空间 |
| 网络 | 可访问外网(拉取镜像)或配置私有镜像仓库 |
| 用户 | root 或具有 sudo 权限的用户 |
2. Docker 安装
2.1 卸载旧版本
sudoyum remove-ydockerdocker-client docker-client-latest\docker-common docker-latest docker-latest-logrotate\docker-logrotate docker-enginepodmanrunc2.2 安装依赖
sudoyuminstall-yyum-utils device-mapper-persistent-data lvm22.3 添加 Docker 仓库
# 使用阿里云镜像源(国内服务器推荐)sudoyum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 替换仓库中的下载地址为阿里云加速(OpenCloudOS 兼容 CentOS 9 仓库)sudosed-i's+download.docker.com+mirrors.aliyun.com/docker-ce+'/etc/yum.repos.d/docker-ce.repo2.4 安装 Docker
sudoyum makecachesudoyuminstall-ydocker-ce docker-ce-cli containerd.io docker-compose-plugin2.5 启动并设置开机自启
sudosystemctl startdockersudosystemctlenabledockersudosystemctlenablecontainerd2.6 验证安装
docker--versiondockercompose versiondockerrun--rmhello-world2.7 配置 Docker 镜像加速
sudomkdir-p/etc/dockersudotee/etc/docker/daemon.json<<'EOF' { "registry-mirrors": [ "https://docker.mirror.example.com" ], "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "3" } } EOFsudosystemctl daemon-reloadsudosystemctl restartdocker2.8 配置用户权限(可选)
# 将当前用户加入 docker 组,免 sudo 执行 docker 命令sudousermod-aGdocker$USER# 使组变更立即生效newgrpdocker2.9 防火墙配置
# 开放所需端口sudofirewall-cmd--permanent--add-port=80/tcpsudofirewall-cmd--permanent--add-port=5003/tcpsudofirewall-cmd--reload# 查看已开放端口sudofirewall-cmd --list-ports3. 项目目录结构
部署时在服务器上创建如下目录结构:
/home/shoot.example.tech/ ├── docker-compose.yml # 编排文件 ├── api/ # 后端 API 服务 │ ├── Dockerfile │ ├── shooting # 可执行文件 │ ├── appsettings.json │ └── wwwroot/ ├── manage/ # 管理后台前端 │ └── dist/ # 构建产物 ├── debugpage/ # 调试页面 │ └── dist/ ├── nginx/ # Nginx 配置 │ └── nginx.conf ├── do.sh # 容器/镜像清理脚本 └── logs/ # 日志目录 └── api/4. Docker Compose 编排
创建docker-compose.yml文件:
version:"3.8"services:# ==================== API 服务 ====================api:build:context:./apidockerfile:Dockerfilecontainer_name:shooting-apirestart:alwaysports:-"5003:5003"volumes:-./api/wwwroot:/app/wwwroot-./logs/api:/app/logsenvironment:-ASPNETCORE_ENVIRONMENT=Production-ASPNETCORE_URLS=http://+:5003networks:-shooting-net# ==================== Nginx 反向代理 ====================nginx:image:nginx:1.24container_name:shooting-nginxrestart:alwaysports:-"80:80"volumes:-./nginx/nginx.conf:/etc/nginx/nginx.conf:ro-./manage/dist:/home/manage:ro-./debugpage/dist:/home/debugpage:rodepends_on:-apinetworks:-shooting-netnetworks:shooting-net:driver:bridge注意:TTS(5005)、串口(5004)、摄像头(5006)等服务如需容器化部署,可参照 api 服务格式在
docker-compose.yml中追加服务定义。
5. Dockerfile 说明
项目 API 的 Dockerfile(位于src/api/Dockerfile):
# 基于 ASP.NET 8.0 运行时镜像 FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app # 暴露端口 5003 EXPOSE 5003 # 设置环境变量 ENV ASPNETCORE_URLS=http://+:5003 ENV ASPNETCORE_ENVIRONMENT=Production # 复制已发布的应用程序文件 COPY . . # 创建日志和静态资源目录 RUN mkdir -p /app/logs /app/wwwroot # 给可执行文件添加执行权限 RUN chmod +x ./shooting # 确保目录权限 RUN chmod -R 755 /app # 设置入口点 ENTRYPOINT ["./shooting"]发布与构建
# 1. 在开发机上发布 API 项目dotnet publish src/api/shooting.csproj-cRelease-opublish/api# 2. 将 Dockerfile 复制到发布目录cpsrc/api/Dockerfile publish/api/# 3. 上传到服务器后构建镜像cd/home/shoot.example.techdockerbuild-tshooting-api:latest ./api6. 部署操作
6.1 首次部署
# 上传项目文件到服务器后执行cd/home/shoot.example.tech# 构建并启动所有服务dockercompose up-d--build# 查看运行状态dockercomposeps# 查看日志dockercompose logs-fapidockercompose logs-fnginx6.2 更新部署
cd/home/shoot.example.tech# 方式一:仅更新 API 服务dockercompose build apidockercompose up-dapi# 方式二:使用清理脚本后重新部署bashdo.sh shooting-apidockercompose up-d--buildapi# 方式三:全量更新dockercompose downdockercompose up-d--build6.3 停止服务
# 停止所有服务dockercompose down# 停止单个服务dockercompose stop api7. 数据库连接配置
API 服务在 Docker 容器中运行时,数据库和 Redis 连接地址需使用host.docker.internal替代localhost,以访问宿主机服务:
{"ConnectionStrings":{"DbContext":"server=host.docker.internal;port=3306;user id=root;password=xxx;database=dbshoot;","Redis":"host.docker.internal,password=xxx,defaultDatabase=2,poolsize=50,ssl=false,writeBuffer=10240,prefix="}}Linux 系统注意:
host.docker.internal在 Linux 上需在docker-compose.yml中显式添加:extra_hosts:-"host.docker.internal:host-gateway"
8. Nginx 反向代理配置
Nginx 负责统一入口,将请求转发到各后端服务:
| 路径 | 目标服务 | 说明 |
|---|---|---|
/ | 静态文件/home/manage | 管理后台前端 |
/debug/ | 静态文件/home/debugpage | 调试页面 |
/interface/ | http://api:5003/ | API 服务 |
/tts/ | http://127.0.0.1:5005/ | 文本转语音服务 |
/serial/ | http://127.0.0.1:5004/ | 串口服务 |
/camera/ | http://127.0.0.1:5006/ | 摄像头服务 |
容器化后,
127.0.0.1应改为 Docker 服务名,如http://api:5003/。
9. 常用运维命令
# 查看所有容器状态dockercomposeps# 查看容器日志dockercompose logs-f--tail100api# 进入容器调试dockercomposeexecapi /bin/bash# 重启单个服务dockercompose restart api# 查看资源占用dockerstats# 清理无用镜像和容器dockersystem prune-a# 查看镜像列表dockerimages# 查看容器详情dockerinspect shooting-api10. 常见问题
Q1: 容器内无法连接宿主机数据库
确认appsettings.json中数据库地址使用host.docker.internal,并在docker-compose.yml的 api 服务中添加:
extra_hosts:-"host.docker.internal:host-gateway"Q2: 端口被占用
# 查看端口占用netstat-tlnp|grep5003# 修改 docker-compose.yml 中的端口映射ports: -"5004:5003"# 将宿主机 5004 映射到容器 5003Q3: 镜像拉取失败
检查 Docker 镜像加速配置,确保daemon.json中的镜像源可用,然后重启 Docker:
sudosystemctl daemon-reloadsudosystemctl restartdockerQ4: 容器启动后立即退出
# 查看退出日志dockercompose logs api# 常见原因:# - appsettings.json 配置错误# - 可执行文件缺少执行权限# - 端口冲突Q5: Nginx 502 Bad Gateway
确认 API 容器正常运行,且nginx.conf中的代理地址与 Docker 网络中的服务名一致:
# 容器化部署时使用服务名 proxy_pass http://api:5003/;