用 Docker + Nginx 部署一个纯静态 2048 小游戏:10 分钟上线的最小实践
写在前面
想做一个"点开就能玩"的小应用,第一反应是上云、买服务器、配 Nginx——其实对于纯静态的小游戏来说,这套流程里 90% 的成本都是浪费。今天这篇就把这件事压缩到最简:用一个静态 HTML 文件 + 一个 Dockerfile + Nginx 镜像,本地打包、丢到服务器、用 Nginx 托管在子路径下,全程不超过十分钟。
文章末尾会给出完整的文件内容和部署命令,读者可以照着做一遍。
一、为什么静态游戏值得单独托管
像 2048 这种小游戏,逻辑全在浏览器里,服务器只需要做一件事:把一个 index.html 正确地吐给用户。既然如此,架构上就没什么可设计的——没有数据库,没有后端进程,没有会话状态。
但"简单"不等于"随便"。实际部署时我踩过三个坑:
- 子路径部署:如果你的应用挂在
/hc-activity/而不是根路径,资源引用必须写成相对路径,否则 JS、CSS 全部 404。 - 缓存与版本:浏览器会缓存
index.html,改完代码刷新没变化,多半是缓存而不是部署失败。 - 端口与占用:服务器上往往已经跑着别的服务,直接
docker run -p 80:80很可能端口冲突,得先确认。
二、准备一个"能跑"的 2048
不用从零手写。2048 的实现到处都有,挑一个逻辑清晰、样式干净的版本,核心代码大致长这样:
const SIZE = 4;
let board, score;
function reset() {
board = Array.from({ length: SIZE }, () => Array(SIZE).fill(0));
score = 0;
addTile(); addTile();
}
function addTile() {
const empty = [];
board.forEach((row, r) => row.forEach((v, c) => { if (!v) empty.push([r, c]); }));
if (!empty.length) return;
const [r, c] = empty[Math.floor(Math.random() * empty.length)];
board[r][c] = Math.random() < 0.9 ? 2 : 4;
}
把移动、合并、判定结束这几件事补齐,套上 CSS 网格布局,一个可玩的小游戏就成型了。关键的一点是所有资源都内联在同一个 HTML 文件里,或者用相对路径引用同目录下的资源——这是后面子路径部署能成立的前提。
三、Dockerfile:只有三行也有意义
静态站点的 Dockerfile 确实很短:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
虽然只有三行,但用容器仍然有几个实在的好处:
- 本地和线上跑的是同一份 nginx,配置行为一致,不会出现"我这儿好好的,上线就 404";
- 换版本只要改 FROM 那一行,运维成本接近零;
- 服务器上不需要装 Nginx,卸载只需要
docker rm加删镜像,干净。
构建和运行也很直接:
docker build -t game2048 .
docker run -d --name game2048 -p 8080:80 game2048
curl -sI http://127.0.0.1:8080/ | head -1 # 期望 HTTP/1.1 200 OK
四、放到服务器的子路径下
如果服务器上 80 端口已经被 Nginx 占用(大概率如此),就不要去抢端口,而是把静态文件交给现有的 Nginx。做法是:
# 1. 启动一个只做文件托管的容器,把目录挂出来
docker run -d --name game2048-files -v /srv/game2048:/usr/share/nginx/html:ro nginx:alpine
# 2. 在宿主机 Nginx 里加一段 location
location /hc-activity/ {
alias /srv/game2048/;
index index.html;
try_files $uri $uri/ /hc-activity/index.html;
}
这里的 alias 末尾那个斜杠很容易踩坑:alias 指向的目录必须带结尾斜杠,location 路径也必须以斜杠结尾,否则会出现路径拼接错位。
改完配置先验证再 reload:
nginx -t && nginx -s reload
五、从外部验证,别只信本地
很多"部署成功"其实是假象——容器起来了,但安全组没放行 80,外部访问依然不通。所以最后一定要从外面打一次:
curl -sI http://<公网IP>/hc-activity/index.html | head -1
看到 200 OK 才算真的完成。这一步能同时暴露端口未放行、Nginx 配置未生效、文件没挂进去三类问题。
如果返回 404,排查顺序是:容器内有没有文件(docker exec game2048-files ls /usr/share/nginx/html)→ location 路径和 alias 斜杠 → 页面内部资源是否用了绝对路径(把 /js/app.js 改成 js/app.js 试试)。
六、小结
整个过程其实只有三个关键决策:资源用相对路径、子路径用 alias 而不是 root、用外部 curl 验证。这三条记住了,把任何纯静态站点搬到服务器上都是十分钟内的事。
下一步想让它更有意思,可以加一个服务端计分排行榜(用 KV 存储或者最简单的文件写入),或者把部署过程写成一条 CI 流水线,推代码即上线。工具越简单,越值得把精力放在玩法本身。
- 点赞
- 收藏
- 关注作者
评论(0)