搭建怀旧游戏网站

什么是 RetroAssembly

RetroAssembly 是一个开源的网页版怀旧游戏收藏柜。把 ROM 文件上传到自己的服务器上,就能在浏览器里直接玩 NES、SNES、Genesis、GameBoy、街机 等 23 个平台的经典游戏。

主打优点:

  • 一条 Docker 命令部署,64MB 镜像极其轻量
  • 自动刮削封面,游戏库看起来整整齐齐
  • 多用户 + 云存档,家人朋友各玩各的
  • MIT 协议,随便改
  • PWA 支持,手机也能当 APP 用
RetroAssembly 成果预览

部署步骤

前提条件

  • 一台有公网 IP 的服务器(本文以 Ubuntu + Oracle Cloud 为例)
  • 服务器已安装 Docker 和 Docker Compose

第一步:确认 Docker 已安装

1
2
docker --version
docker compose version

第二步:创建项目目录

1
mkdir -p ~/retroassembly && cd ~/retroassembly

第三步:编写 docker-compose.yml

1
2
3
4
5
6
7
8
9
services:
retroassembly:
image: arianrhodsandlot/retroassembly:latest
container_name: retroassembly
ports:
- 8000:8000
volumes:
- ./data:/app/data
restart: unless-stopped

如果使用 cat 写入,注意用 heredoc 防止缩进破坏:

1
2
3
4
5
6
7
8
9
10
11
cat > compose.yaml << 'EOF'
services:
retroassembly:
image: arianrhodsandlot/retroassembly:latest
container_name: retroassembly
ports:
- 8000:8000
volumes:
- ./data:/app/data
restart: unless-stopped
EOF

第四步:启动容器

1
docker compose up -d

检查运行状态:

1
2
docker ps | grep retroassembly
docker logs retroassembly

看到 ASCII art Logo 和 Running at http://0.0.0.0:8000/ 就说明启动成功了。

第五步:防火墙放行

1
sudo ufw allow 8000/tcp

如果是云服务器,还要在云控制台的安全组/安全列表添加一条入站规则

  • 协议:TCP
  • 端口:8000
  • 来源:0.0.0.0/0

第六步:绑定域名并开始使用

在cloudflare中给域名新加个DNS记录,game.clovee.qzz.io,指向服务器IP。用1panel面板开启反代,搭配之前的通配符域名证书,美美使用。(本篇唯一手写的一句话)

浏览器打开 https://game.clovee.qzz.io

  1. 点击右上角 Library → Log in → 注册账号
  2. 点击 Add → 选择游戏平台 → 上传 ROM 文件
  3. 封面自动抓取,点击游戏直接开玩

踩坑记录:Oracle Cloud 的 Docker 网络问题

症状

容器正常启动,docker logs 显示服务正在监听,本地 curl 也能拿到响应(302 跳转),但从外部浏览器始终无法访问。telnet 显示连接超时。

排查过程:

  1. ss -tlnp | grep 8000 → 容器已绑定 0.0.0.0:8000
  2. ufw status → inactive,系统防火墙没开 ✅
  3. iptables -L INPUT -n → 规则干净,没有 DROP ✅
  4. 云控制台安全组配置正确 ✅
  5. 其他非 Docker 服务(如 Nginx 直接跑在宿主机上)访问正常 ✅

原因

Oracle Cloud 的网络模型不同于大多数云厂商。它的公网 IP 直接绑定在宿主机网卡上(而非走 NAT 转换),而 Docker 默认的 bridge 网络模式依赖 iptables DNAT 做端口映射,与 Oracle 的网络模型存在兼容性问题。

具体表现为 iptables -t nat -L -n 中 DNAT 规则生成了,但包无法正确转发到 Docker 容器。

解决方案

将 Docker 容器的网络模式改为 host,让容器直接与宿主机共享网络栈,绕开 Docker 的端口映射层。

1
2
3
4
5
6
7
8
services:
retroassembly:
image: arianrhodsandlot/retroassembly:latest
container_name: retroassembly
network_mode: host # ← 关键改动
volumes:
- ./data:/app/data
restart: unless-stopped

修改后重建容器:

1
2
docker compose down
docker compose up -d

host 模式下容器直接使用宿主机网络,无需端口映射,http://服务器IP:8000 即可直接访问。

验证

启动一个测试 Nginx 容器印证了这一结论——同样 bridge + port 映射无法访问,改成 host 即恢复正常。

总结

RetroAssembly 是我目前用过最顺手的自托管怀旧游戏方案,完整体验可以总结为:

维度 评价
部署难度 ⭐(Docker 一把梭)
维护成本 极低,就一个容器
平台覆盖 23 个,主流老平台都有
UI 体验 美观,手柄/键盘/手机全适配
多用户 自带,家人朋友分账号
许可证 MIT,随便改

唯一要注意的是 Oracle Cloud 等特殊网络环境下的 Docker 网络问题,network_mode: host 一招搞定。

祝怀旧愉快 🎮