Docker Compose 部署 Nginx 静态站并配置 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 即可,不需要引入更重的网关。
- 点赞
- 收藏
- 关注作者
评论(0)