Docker Compose 部署 Nginx 静态站并配置 HTTPS:一份最小可用模板

举报
yd_224601470 发表于 2026/10/29 13:39:03 2026/10/29
【摘要】 把内部小工具从 http.server 迁到云上时整理的一套 Nginx + Docker Compose 模板,覆盖目录结构、反向代理、gzip 与缓存、HTTPS 续期和五个常见坑,直接复制即可用。

最近把一个内部小工具从本地 http.server 迁移到云主机,顺手整理了一份可以直接复用的 Nginx + Docker Compose 模板。它不依赖任何云厂商专属能力,本地和云上都能跑,适合文档站、活动页、演示 Demo 这类轻量站点。

一、目录结构

site/
├── docker-compose.yml
├── nginx.conf
└── html/
    └── index.html

二、docker-compose.yml

镜像固定小版本号,避免 latest 带来的不可预期升级;静态文件与配置都以只读方式挂载。

services:
  web:
    image: nginx:1.27-alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./html:/usr/share/nginx/html:ro
      - ./certs:/etc/nginx/certs:ro
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

三、nginx.conf 的三个要点

第一,开启 gzip 并设置合理的缓存策略:带哈希的静态资源可以长缓存,HTML 必须短缓存甚至不缓存,否则更新后用户看到旧页面。

server {
  listen 80;
  server_name example.com;
  root /usr/share/nginx/html;
  index index.html;

  gzip on;
  gzip_types text/css application/javascript application/json image/svg+xml;

  location ~* \.(js|css|png|jpg|svg|woff2)$ {
    expires 7d;
    add_header Cache-Control "public, max-age=604800, immutable";
  }

  location / {
    try_files $uri $uri/ /index.html;
  }
}

第二,try_files 是单页应用的关键。刷新深链接时如果没有这条规则,Nginx 会直接返回 404。

第三,补上基础安全头,成本很低但收益明显:X-Content-Type-Options: nosniff、X-Frame-Options: SAMEORIGIN、Referrer-Policy: no-referrer-when-downgrade。

四、HTTPS 与自动续期

证书可以用云厂商签发的免费证书,也可以用 certbot 走 webroot 方式签发。后者更适合容器场景:把 /.well-known/acme-challenge 映射到本地目录,续期时不需要停服务。

location ^~ /.well-known/acme-challenge/ {
  root /var/www/certbot;
}

续期命令放进定时任务即可:certbot renew --webroot -w /var/www/certbot --deploy-hook "docker compose exec web nginx -s reload"。注意 --deploy-hook 只在真正续期成功时执行,避免每天无意义重载。

五、五个常见坑

  • 容器内 403:只读挂载的目录权限过严,Nginx worker 用户读不到文件,检查目录的 o+rx。
  • 端口被占用:云主机上可能已有系统自带服务监听 80,先 ss -lntp 确认。
  • 静态资源 404:root 指向了容器内路径,却把文件挂到了别的位置,两边要一致。
  • 刷新页面 404:缺少 try_files,这是单页应用最常见的上线问题。
  • 磁盘被日志写满:Docker 默认 json-file 驱动不限制大小,务必设置 max-size。

六、上线后的三行体检

curl -sI http://127.0.0.1/ | head -n 5
curl -sI https://example.com/ | grep -i strict-transport-security
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

小结

这套模板的核心只有三点:固定镜像版本、静态资源长缓存而 HTML 不缓存、用 try_files 兜住前端路由。把这三点做对,轻量站点基本不会再出问题。后续如果要加反向代理或灰度,直接在同一个 server 块里加 location 即可,不需要引入更重的网关。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。