直接使用官方 nginx:alpine 镜像即可,无需自行安装 Nginx;其体积仅约 20MB,预装精简版 Nginx,开箱即用,监听 80 端口,静态文件根目录为 /usr/share/nginx/html,应通过 COPY 指令将构建产物(如 dist/)复制进镜像,并配置 try_files 支持 SPA history 路由,避免挂载方式用于生产环境。

直接用 nginx:alpine 镜像就行,别自己装 Nginx
自己在 Ubuntu/CentOS 容器里 apt install nginx 是最常见也最不该做的操作。它会让镜像体积暴涨(从 5MB 到 200MB+),启动慢、攻击面大、更新困难,而且根本没必要——官方 nginx:alpine 镜像已经预装好精简版 Nginx,开箱即用。
真正要做的只是把 HTML 文件放进去、配好路径、确保能响应请求。其他所有“安装”“配置服务”“写启动脚本”的动作,都是对容器理念的误读。
-
nginx:alpine默认监听80端口,静态文件根目录是/usr/share/nginx/html - 不要改
CMD或手动nginx -g daemon off;—— 官方镜像的 entrypoint 已经处理好了 - 如果用了
nginx:latest,可能拉到非 alpine 版本(比如 debian),体积翻倍且含冗余包,建议显式指定nginx:1.25-alpine
挂载(-v)只适合本地调试,上线必须 COPY 进镜像
用 docker run -v $(pwd)/dist:/usr/share/nginx/html:ro 确实快,但生产环境一跑就出问题:Kubernetes 不认裸挂载、重启后挂载失效、CI/CD 流水线无法保证路径一致性、安全策略常直接禁用 hostPath。
正确做法是在 Dockerfile 中用 COPY 把构建产物打进镜像,做到“一次构建、处处运行”。
立即学习“前端免费学习笔记(深入)”;
-
COPY ./dist/ /usr/share/nginx/html/—— 注意末尾斜杠,它表示“把 dist 下所有内容复制进去”,不是把 dist 文件夹整个复制 - 如果
index.html在dist/my-app/index.html,那访问会 404;必须确保index.html直接位于dist/下一级 - 构建命令必须在
dist所在目录执行:docker build -t my-site .,否则COPY找不到源文件
history 模式白屏?缺 try_files 就是硬伤
Vue Router / React Router 的 history 模式下,访问 /about 会 404,不是前端代码问题,是 Nginx 根本没把请求回退给 index.html。默认配置只服务真实存在的文件,不处理 SPA 路由。
解决方法只有一条:在 location / 块里加 try_files $uri $uri/ /index.html;,且必须放在 root 后面。
- 漏掉分号(
;)会导致 Nginx 启动失败,报错:nginx: [emerg] invalid number of arguments in "try_files" directive - 写成
alias替代root是常见误区:alias会拼接路径,容易导致 403;root更直观可靠 - 如果你用的是自定义
nginx.conf,记得删掉默认的default.conf:RUN rm /etc/nginx/conf.d/default.conf
缓存、压缩、权限这些细节,不设就等于没部署
一个“能打开”的页面 ≠ 一个“可上线”的服务。浏览器反复请求 JS/CSS、加载慢、日志无落盘、Linux 下容器读不到文件——这些问题全在部署时埋下,上线后才爆发。
- 静态资源加缓存:
location ~* \.(js|css|png|jpg|woff2)$ { expires 1y; },避免重复下载 - 开启 gzip:
gzip on; gzip_types text/css application/javascript;,JS/CSS 体积通常压掉 70% - Linux/macOS 下检查
ls -l dist,确保其他用户有读权限(other列至少有r),否则容器内 Nginx 读失败,返回 403 - 日志别丢进容器内存里:用
-v ./logs:/var/log/nginx持久化,或在Dockerfile中重定向access_log /dev/stdout
高可用不靠堆机器,靠配置健壮性。一个没设 try_files 的镜像,跑十台也是白屏;一个没开 gzip 的站点,带宽成本翻倍;一个权限锁死的 dist 目录,在 macOS 上本地能跑,上 Linux 服务器就 403。这些点不在文档最前面,但都在第一次上线失败的错误日志里藏着。



















