当前位置: 首页 > ai >正文

Softhub软件下载站实战开发(二十):Docker部署全攻略

🐳 Softhub软件下载站实战开发(二十):Docker部署全攻略

随着本系列步入尾声,本篇文章将分享Softhub项目的Docker部署方案,这是一个包含前后端的完整Web应用。我们将深入探讨Dockerfile的编写技巧、Supervisor进程管理以及Nginx配置优化等关键内容。打包完成之后将实现一个docker镜像包含后台管理、后台管理、前台页面,非常适合个人部署使用。🚀

📦 多阶段构建的Dockerfile

我们的Dockerfile采用了多阶段构建技术,这是现代Docker实践中的重要优化手段:

# 阶段1:构建后端
FROM golang:1.23-alpine AS backend-builder
# ...构建步骤...# 阶段2:最终镜像
FROM alpine:latest
# ...复制构建产物...

这种设计带来了几个显著优势:

  1. 减小最终镜像体积 - 构建工具不会出现在最终镜像中
  2. 提高安全性 - 最终镜像只包含运行时必要的组件
  3. 优化构建缓存 - 可以更细粒度地控制缓存失效

🔧 关键构建技巧

基础镜像选择
alpine最小化镜像
多阶段构建
依赖缓存优化
静态编译Go程序
资源文件精确定位
  1. Go构建优化

    RUN go build -a -installsuffix cgo -ldflags="-s -w" -o main .
    
    • -a:强制重新构建所有包
    • -ldflags="-s -w":移除调试信息减小体积
  2. 依赖缓存

    RUN --mount=type=cache,target=/go/pkg/mod \go mod download
    

    使用BuildKit缓存特性加速后续构建

  3. 时区配置

    RUN apk --no-cache add tzdata
    ENV TZ=Asia/Shanghai
    

    确保容器内使用正确的时间

🎛 Supervisor进程管理

我们使用Supervisor来管理多个进程:

Supervisor的优势

  • 进程守护:自动重启崩溃的进程
  • 统一日志:集中管理所有子进程日志
  • 简单配置:一个配置文件管理所有服务
  • 启动顺序控制:可以定义依赖关系

🌐 Nginx高级配置

nginx配置一些细节

1. 前后端分离路由

# 后台管理
location /admin {try_files $uri $uri/ /admin/index.html;
}# 前台页面
location / {try_files $uri $uri/ /index.html;
}

2. 静态资源优化

location /assets {expires 1y;add_header Cache-Control "public, immutable";
}

设置长期缓存并添加immutable标记,避免不必要的验证请求

3. API代理配置

location /api {proxy_pass http://localhost:8808;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";# 大文件上传超时设置proxy_read_timeout 300s;
}

🏗 目录结构设计

容器内的目录结构经过精心设计:

/app
├── main                  # 后端可执行文件
├── manifest/config/      # 配置文件
└── resource/             # 资源文件├── casbin/├── data/└── log//usr/share/nginx/html
├── admin/                # 后台前端
└── client/               # 用户前端

🚨 错误处理机制

添加错误页面处理:

error_page 500 502 503 504 /50x.html;
location = /50x.html {root /usr/share/nginx/html/client;internal;
}

提供友好的用户体验。

🔍 健康检查

Docker健康检查确保服务可用性:

HEALTHCHECK --interval=30s --timeout=10s \CMD wget --spider http://localhost:8808/api/v1/client/health && \wget --spider http://localhost/ || exit 1

💡 最佳实践总结

  1. 最小化镜像:使用alpine基础镜像,移除不必要的文件
  2. 构建分离:多阶段构建减少最终镜像体积
  3. 缓存优化:利用BuildKit缓存加速构建
  4. 进程管理:Supervisor管理多个进程
  5. 静态资源优化:长期缓存+immutable标记
  6. 健康检查:确保服务可用性
  7. 日志集中:统一收集所有服务日志

通过这套部署方案,Softhub应用实现了:

  • 单容器部署前后端
  • 高效的资源利用
  • 稳定的服务运行
  • 便捷的运维管理

附录

服务器错误页面

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>服务器错误</title><style>body {font-family: Arial, sans-serif;text-align: center;padding: 50px;background-color: #f5f5f5;}.error-container {max-width: 600px;margin: 0 auto;background: white;padding: 40px;border-radius: 10px;box-shadow: 0 2px 10px rgba(0,0,0,0.1);}h1 {color: #e74c3c;font-size: 2.5em;margin-bottom: 20px;}p {color: #666;font-size: 1.2em;line-height: 1.6;}.back-btn {display: inline-block;margin-top: 20px;padding: 10px 20px;background: #3498db;color: white;text-decoration: none;border-radius: 5px;transition: background 0.3s;}.back-btn:hover {background: #2980b9;}</style>
</head>
<body><div class="error-container"><h1>服务器错误</h1><p>抱歉,服务器遇到了一些问题。请稍后再试。</p><a href="/" class="back-btn">返回首页</a></div>
</body>
</html>

mime.types

types {text/html                             html htm shtml;text/css                              css;text/xml                              xml;image/gif                             gif;image/jpeg                            jpeg jpg;application/javascript                js;application/atom+xml                  atom;application/rss+xml                   rss;text/mathml                           mml;text/plain                            txt;text/vnd.sun.j2me.app-descriptor      jad;text/vnd.wap.wml                      wml;text/x-component                      htc;image/png                             png;image/svg+xml                         svg svgz;image/tiff                            tif tiff;image/vnd.wap.wbmp                    wbmp;image/webp                            webp;image/x-icon                          ico;image/x-jng                           jng;image/x-ms-bmp                        bmp;font/woff                             woff;font/woff2                            woff2;application/java-archive              jar war ear;application/json                      json;application/mac-binhex40              hqx;application/msword                    doc;application/pdf                       pdf;application/postscript                ps eps ai;application/rtf                       rtf;application/vnd.apple.mpegurl         m3u8;application/vnd.google-earth.kml+xml  kml;application/vnd.google-earth.kmz      kmz;application/vnd.ms-excel              xls;application/vnd.ms-fontobject         eot;application/vnd.ms-powerpoint         ppt;application/vnd.oasis.opendocument.graphics        odg;application/vnd.oasis.opendocument.presentation    odp;application/vnd.oasis.opendocument.spreadsheet     ods;application/vnd.oasis.opendocument.text            odt;application/vnd.openxmlformats-officedocument.presentationml.presentation    pptx;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet             xlsx;application/vnd.openxmlformats-officedocument.wordprocessingml.document       docx;application/vnd.wap.wmlc              wmlc;application/x-7z-compressed           7z;application/x-cocoa                   cco;application/x-java-archive-diff       jardiff;application/x-java-jnlp-file          jnlp;application/x-makeself                run;application/x-perl                    pl pm;application/x-pilot                   prc pdb;application/x-rar-compressed          rar;application/x-redhat-package-manager  rpm;application/x-sea                     sea;application/x-shockwave-flash         swf;application/x-stuffit                 sit;application/x-tcl                     tcl tk;application/x-x509-ca-cert            der pem crt;application/x-xpinstall               xpi;application/xhtml+xml                 xhtml;application/xspf+xml                  xspf;application/zip                       zip;application/octet-stream              bin exe dll;application/octet-stream              deb;application/octet-stream              dmg;application/octet-stream              iso img;application/octet-stream              msi msp msm;audio/midi                            mid midi kar;audio/mpeg                            mp3;audio/ogg                             ogg;audio/x-m4a                           m4a;audio/x-realaudio                     ra;video/3gpp                            3gpp 3gp;video/mp2t                            ts;video/mp4                             mp4;video/mpeg                            mpeg mpg;video/quicktime                       mov;video/webm                            webm;video/x-flv                           flv;video/x-m4v                           m4v;video/x-mng                           mng;video/x-ms-asf                        asx asf;video/x-ms-wmv                        wmv;video/x-msvideo                       avi;
}

nginx.conf

server {listen 80;server_name _;# 包含 MIME 类型include /etc/nginx/mime.types;# 设置最大上传文件大小client_max_body_size 4G;# 大文件上传超时设置client_body_timeout 300s;client_header_timeout 300s;send_timeout 300s;# 禁用自动重定向absolute_redirect off;# 后台管理页面的 /sys 资源路径(映射到 admin 目录)location /sys {alias /usr/share/nginx/html/admin;expires 1y;add_header Cache-Control "public, immutable";try_files $uri =404;}# 后台管理页面路由(精确匹配)location = /admin {root /usr/share/nginx/html;try_files /admin/index.html =404;add_header Content-Type "text/html; charset=utf-8";}# 后台管理页面路由(带路径)location /admin/ {root /usr/share/nginx/html;try_files $uri $uri/ /admin/index.html;# 对 HTML 文件设置正确的 Content-Typelocation ~ \.html$ {add_header Content-Type "text/html; charset=utf-8";}}# 前台页面的静态资源(assets目录)location /assets {root /usr/share/nginx/html/client;expires 1y;add_header Cache-Control "public, immutable";try_files $uri =404;}# CDN资源路径location ~ ^/(at\.alicdn\.com|netdna\.bootstrapcdn\.com)/ {root /usr/share/nginx/html/client;try_files $uri =404;expires 1y;add_header Cache-Control "public, immutable";}# 前台页面路由(默认路由)location / {root /usr/share/nginx/html/client;index index.html;try_files $uri $uri/ /index.html;}# API代理到后端服务location /api {proxy_pass http://localhost:8808;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 $scheme;# 超时设置(支持大文件上传)proxy_connect_timeout 300s;proxy_send_timeout 300s;proxy_read_timeout 300s;# 支持WebSocketproxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";}# Swagger文档路由location /swagger {proxy_pass http://localhost:8808;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 $scheme;}# 错误页面(避免重定向循环)error_page 500 502 503 504 /50x.html;# 创建 50x.html 错误页面location = /50x.html {root /usr/share/nginx/html/client;internal;}# 日志配置access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;
}

supervisord.conf

[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid[program:backend]
command=/app/main
directory=/app
autorestart=true
stdout_logfile=/var/log/supervisor/backend.log
stderr_logfile=/var/log/supervisor/backend.log[program:nginx]
command=nginx -g "daemon off;"
autorestart=true
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.log

dockerfile

# 统一的 Dockerfile - 包含后端+两个前端
# 使用 BuildKit 语法
# syntax=docker/dockerfile:1.4# 阶段1:构建后端
FROM golang:1.23-alpine AS backend-builder# 安装必要的工具
RUN apk add --no-cache git# 设置Go代理环境变量
ENV GOPROXY=https://goproxy.cn,direct
ENV GOSUMDB=sum.golang.google.cn
ENV GOPRIVATE=*.gitlab.com,*.gitee.com
ENV CGO_ENABLED=0
ENV GOOS=linux# 设置工作目录
WORKDIR /app# 复制 go mod 文件
COPY go.mod go.sum ./# 下载依赖(使用缓存)
RUN --mount=type=cache,target=/go/pkg/mod \go mod download# 复制后端源码
COPY . .# 构建后端(使用更激进的优化)
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o main .# 阶段2:最终镜像
FROM alpine:latest# 安装必要的运行时依赖
RUN apk --no-cache add ca-certificates tzdata wget nginx supervisor ffmpeg curl# 设置时区
ENV TZ=Asia/Shanghai# 设置工作目录
WORKDIR /app# 从构建阶段复制后端二进制文件
COPY --from=backend-builder /app/main .# 复制后端配置文件
COPY manifest/config/config.yaml ./manifest/config/# 复制后端资源文件(只复制必要的)
COPY resource/casbin/ ./resource/casbin/
COPY resource/data/ ./resource/data/# 创建必要的目录结构
RUN mkdir -p resource/log/run \resource/log/server \resource/log/sql \resource/log/public \/var/log/nginx \/var/log/supervisor# 创建前端目录结构
RUN mkdir -p /usr/share/nginx/html/admin /usr/share/nginx/html/client# 复制前端dist目录(需要预先构建好)
COPY web/admin/dist /usr/share/nginx/html/admin
COPY web/client/dist /usr/share/nginx/html/client# 复制nginx配置文件
COPY nginx.conf /etc/nginx/http.d/default.conf# 复制MIME类型文件
COPY mime.types /etc/nginx/mime.types# 复制错误页面
COPY 50x.html /usr/share/nginx/html/client/50x.html# 复制supervisor配置文件
COPY supervisord.conf /etc/supervisord.conf# 暴露端口
EXPOSE 8808 80# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \CMD wget --no-verbose --tries=1 --spider http://localhost:8808/api/v1/client/health && \wget --no-verbose --tries=1 --spider http://localhost/ || exit 1# 启动命令
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

softhub系列往期文章

  1. Softhub软件下载站实战开发(一):项目总览
  2. Softhub软件下载站实战开发(二):项目基础框架搭建
  3. Softhub软件下载站实战开发(三):平台管理模块实战
  4. Softhub软件下载站实战开发(四):代码生成器设计与实现
  5. Softhub软件下载站实战开发(五):分类模块实现
  6. Softhub软件下载站实战开发(六):软件配置面板实现
  7. Softhub软件下载站实战开发(七):集成MinIO实现文件存储功能
  8. Softhub软件下载站实战开发(八):编写软件后台管理
  9. Softhub软件下载站实战开发(九):编写软件配置管理界面
  10. Softhub软件下载站实战开发(十):实现图片视频上传下载接口
  11. Softhub软件下载站实战开发(十一):软件分片上传接口实现
  12. Softhub软件下载站实战开发(十二):软件管理编辑页面实现
  13. Softhub软件下载站实战开发(十三):软件管理前端分片上传实现
  14. Softhub软件下载站实战开发(十四):软件收藏集设计
  15. Softhub软件下载站实战开发(十五):仪表盘API设计
  16. Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
  17. Softhub软件下载站实战开发(十七):用户端API设计
  18. Softhub软件下载站实战开发(十八):软件分类展示
  19. Softhub软件下载站实战开发(十九):软件信息展示
http://www.xdnf.cn/news/15892.html

相关文章:

  • WPF——自定义ListBox
  • 注解 + AOP 的方式记录日志到 t_ops_sync_log 表
  • 使用相机不同曝光时间测试灯光闪烁频率及Ai解释
  • 宝塔访问lnmp项目,跳转不到项目根目录问题解决
  • 后训练(Post-training)语言模型
  • Linux system-timesyncd时间同步机制详解
  • Django模板系统
  • Oracle 数据库共享池与大池调优指南
  • RuoYi配置多数据源失效
  • 【烧脑算法】拓扑排序:从“依赖”到“序列”,理解题目中的先后逻辑
  • 虚拟电厂蓄势:源网荷储联动如何实现电力系统的 “智慧蝶变”?
  • 如何升级到macOS Tahoe:全面指南与实用步骤
  • 从一开始的网络攻防(六):php反序列化
  • 关于JavaWeb的总结笔记
  • 云原生周刊:K8s 中的后量子密码学
  • 【学习路线】C#企业级开发之路:从基础语法到云原生应用
  • docker 容器学习
  • zabbix企业级分布式监控环境部署
  • 【Prometheus+Grafana篇】监控通过Keepalived实现的MySQL HA高可用架构
  • 在翻译语义相似度和会议摘要相似度评估任务中 ,分类任务 回归任务 生成任务区别
  • 布局AI +文化新赛道,浙江省文化产业投资集团赴景联文科技调研交流
  • uniapp【uni-ui】【vue3】样式覆盖方式记录
  • Git上传与下载GitHub仓库
  • Neo4j 5.x版本的导出与导入数据库
  • 【系统全面】Linux内核原理——基础知识介绍
  • Python-数据库概念-pymysql-元编程-SQLAlchemy-学习笔记
  • 【ASP.NET Core】ASP.NET Core中Redis分布式缓存的应用
  • Python day20 - 特征降维之奇异值分解
  • 隧道代理的动态IP切换机制与实现原理
  • 农村供水智慧化管理系统:从精准监测到智能调度,破解农村用水安全与效率难题