ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

树莓派4B搭建Minecraft服务器:Docker部署与内网穿透实战

树莓派4B搭建Minecraft服务器:Docker部署与内网穿透实战 1. 为什么我选择用树莓派4B跑MC服务器1.1 一台闲置开发板的再利用思路手里有块树莓派4B4GB内存版本买来原本是想做家庭自动化网关结果折腾了两周就吃灰了。后来几个朋友想开个Minecraft服务器一起玩租云服务器一个月几十块长期下来也不便宜我就琢磨着能不能用这块板子顶上。先说结论树莓派4B跑原版MC服务器4GB内存版本可以稳定支撑3到5人同时在线前提是视距不要拉太高、不做大型红石机器。如果你手里是8GB版本6到8人问题不大。这个结论是我实测出来的不是拍脑袋。为什么是树莓派4B而不是其他型号几个硬指标摆在这里CPU博通BCM2711四核Cortex-A72主频1.5GHz。A72架构的每时钟指令数比树莓派3B的A53高出一大截单核性能大概翻倍。MC服务端是典型的单线程吃紧型应用主世界tick逻辑跑在一个线程上所以单核性能比核心数更重要。内存4GB LPDDR4-3200。原版服务端启动后基础占用大概1.2到1.5GB加上区块加载和玩家数据3人左右会到2.5GB上下。留出系统本身的开销4GB是及格线。网络千兆以太网口。这点很关键树莓派4B的有线网口是独立控制器不像3B那样挂在USB总线上。MC的区块同步对延迟敏感有线连接比WiFi稳太多。存储我用的是一块USB 3.0接口的SSD不是SD卡。原因后面会详细说这是踩过坑之后的教训。1.2 树莓派跑MC的三个真实瓶颈很多人觉得树莓派性能弱跑不了MC。这话对也不对。我实际跑下来瓶颈主要在这三个地方第一是存储I/O。MC服务端会频繁读写区块文件尤其是玩家跑图的时候。SD卡的随机读写性能极差4K随机写入可能只有几百IOPS而SSD能到几万。用SD卡跑玩家一跑图就卡顿区块加载慢得像幻灯片。我一开始用Class 10的SD卡三个人在线时TPS每秒tick数经常掉到15以下换成USB SSD之后稳定在19.8到20。第二是单核性能。前面说了MC主逻辑是单线程的。树莓派4B单核性能大概相当于十年前的低端x86处理器。原版服务端在默认配置下3人同时在线、视距10区块单核占用率会到70%到85%。如果开红石机器或者大量实体直接跑满TPS就掉了。第三是散热。树莓派4B满载时SoC温度能到80度以上触发降频。降频之后性能直接砍半TPS跟着崩。我加了一个带风扇的铝合金外壳温度压在55度以下就没再出现过热降频。提示如果你打算长期跑MC服务器散热和存储这两块千万别省。这两处的投入比换更高配的板子性价比高得多。1.3 这套方案适合谁这套方案适合以下几类人想和朋友开个小服人数不多预算有限手里已经有树莓派4B想物尽其用想学Linux运维和Docker拿MC服务器当练手项目对延迟要求不是极致能接受偶尔的卡顿不适合的场景也很明确十几人以上的公开服、大量模组、需要24小时高负载运行的生产环境。这些场景还是老老实实上x86服务器或者租云主机。2. 系统层面的准备工作从烧录到远程连接2.1 Ubuntu Server 22.04的安装与首次启动树莓派官方系统是Raspberry Pi OS但我建议用Ubuntu Server 22.04 LTS。原因有三个一是Ubuntu的软件源更新更快Docker和Java的版本更省心二是Ubuntu Server对ARM64的支持成熟社区文档多三是长期支持周期到2027年不用频繁折腾系统升级。烧录步骤不复杂但有几个细节容易翻车下载镜像去Ubuntu官网找Raspberry Pi版本选64位。注意是预装桌面还是Server版我们选Server版省资源。烧录工具用Raspberry Pi Imager或者balenaEtcher都行。我习惯用Raspberry Pi Imager因为它可以在烧录前直接配置WiFi、主机名、SSH密钥省得烧完还要接显示器改配置。烧录目标如果你用SSD需要先通过USB转接盒接到电脑上再烧录。注意树莓派4B的USB启动需要先更新EEPROM固件新出厂的板子一般已经支持老板子需要先插SD卡启动一次执行sudo rpi-eeprom-update -a更新。烧录完成后插卡或SSD上电第一次启动大概需要2到3分钟因为要扩展文件系统和初始化。看到HDMI输出登录提示或者通过路由器找到它的IP就说明启动成功了。默认用户名密码是ubuntu/ubuntu首次登录会强制要求改密码。2.2 静态IP与SSH密钥登录服务器要长期跑IP不能变。两种做法路由器里绑定MAC地址或者在系统里配静态IP。我推荐在路由器里绑定简单且不会因为系统重装丢失。SSH方面强烈建议用密钥登录关掉密码登录。树莓派暴露在网络上密码登录被暴力破解是迟早的事。操作如下# 在本地电脑生成密钥对如果还没有 ssh-keygen -t ed25519 -C mc-server # 把公钥传到树莓派 ssh-copy-id ubuntu192.168.1.100 # 登录后编辑SSH配置 sudo nano /etc/ssh/sshd_config把这几项改成PasswordAuthentication no PubkeyAuthentication yes PermitRootLogin no然后重启SSH服务sudo systemctl restart ssh。注意改配置之前先确认密钥登录已经能成功否则改完密码登录关掉自己都进不去了。这是新手最容易犯的错。2.3 系统基础调优时区、交换空间、文件句柄Ubuntu Server默认配置对MC服务器来说有几个地方需要调整时区改成你所在时区否则日志时间对不上。sudo timedatectl set-timezone Asia/Shanghai交换空间树莓派默认的swap只有100MB到200MB对MC来说太小。虽然我们不希望频繁用swapSSD写入寿命有限但留一些作为缓冲是必要的。我一般设2GBsudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 写入fstab使其永久生效 echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab同时调整swappiness降低系统主动使用swap的倾向echo vm.swappiness10 | sudo tee -a /etc/sysctl.conf sudo sysctl -p文件句柄数MC服务端会打开大量文件默认的1024可能不够。改到65535echo ubuntu soft nofile 65535 | sudo tee -a /etc/security/limits.conf echo ubuntu hard nofile 65535 | sudo tee -a /etc/security/limits.conf改完需要重新登录生效。3. Docker化部署MC服务端的完整流程3.1 为什么用Docker而不是直接跑JAR直接跑JAR当然可以java -jar server.jar一行命令就起来了。但我选择Docker理由如下环境隔离Java版本、依赖库全部封装在容器里不会污染宿主机。以后想换Java版本或者换服务端类型删掉容器重来就行。数据持久化清晰通过volume把世界数据、配置、插件挂载到宿主机容器删了数据还在。重启策略Docker的--restart unless-stopped策略让服务器崩溃后自动拉起省心。资源限制可以精确限制容器的CPU和内存防止MC服务端把树莓派吃干。在树莓派上装Docker用官方脚本最省事curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker ubuntu最后一行是把当前用户加入docker组这样不用每次敲sudo。执行完要重新登录才生效。验证安装docker version和docker compose version都能正常输出就OK。提示树莓派是ARM64架构拉镜像时要注意选支持arm64的。Docker Hub上很多镜像只提供amd64拉下来跑不了。后面选MC服务端镜像时会专门说这个。3.2 选对服务端镜像原版、Paper还是FabricMC服务端有好几种实现选哪个直接决定性能和功能服务端类型特点树莓派4B适配度适用场景原版VanillaMojang官方无优化一般纯净生存人数少Paper基于Spigot优化性能好推荐生存服支持插件Fabric轻量模组加载器推荐想加模组但不想太重Forge模组生态最全不推荐大型模组包树莓派扛不住我最终选的是Paper。它在原版基础上做了大量性能优化比如异步区块加载、实体激活范围优化、红石算法改进在树莓派这种弱CPU上提升很明显。而且Paper兼容Bukkit插件生态想加个领地保护、经济系统都很方便。镜像方面我用的是itzg/minecraft-server。这个镜像维护活跃支持arm64环境变量配置丰富文档也全。拉取命令docker pull itzg/minecraft-server这个镜像会自动检测架构树莓派上拉到的就是arm64版本。3.3 docker-compose配置详解与参数调优我不用docker run而是用docker-compose.yml管理。原因是配置项太多命令行写起来又长又容易错compose文件可以版本控制改起来也方便。version: 3.8 services: minecraft: image: itzg/minecraft-server container_name: mc-server restart: unless-stopped ports: - 25565:25565 environment: EULA: TRUE TYPE: PAPER VERSION: 1.20.4 MEMORY: 2560M ONLINE_MODE: TRUE DIFFICULTY: normal MAX_PLAYERS: 5 VIEW_DISTANCE: 8 SIMULATION_DISTANCE: 6 MOTD: 树莓派小服 TZ: Asia/Shanghai USE_AIKAR_FLAGS: true volumes: - ./data:/data deploy: resources: limits: cpus: 3.0 memory: 3G几个关键参数逐个解释MEMORY: 2560M分配给Java堆的内存。树莓派4B总共4GB系统本身占500MB左右留出一些给文件缓存堆内存给2.5GB比较合适。给太多会导致系统OOM给太少会频繁GC。VIEW_DISTANCE: 8视距单位是区块。默认是10树莓派上降到8能明显减轻CPU和内存压力。每降低1区块加载量大概减少20%。SIMULATION_DISTANCE: 6模拟距离比视距小。这个参数控制实体和方块更新的范围降低它能大幅减少CPU占用但玩家会感觉远处的怪不动、作物不长。6是比较平衡的值。USE_AIKAR_FLAGS: true启用Aikar的JVM调优参数。这是一套经过大量实践验证的GC参数组合能显著减少GC停顿。对于MC这种内存分配频繁的应用效果很明显。deploy.resources.limits限制容器最多用3个CPU核心和3GB内存。留一个核心给系统和Docker本身避免MC把树莓派吃满导致SSH都卡。启动命令docker compose up -d第一次启动会下载Paper服务端JAR并初始化世界大概需要3到5分钟。用docker compose logs -f看日志看到Done (XX.XXXs)! For help, type help就说明启动成功了。3.4 首次启动后的验证与基础配置服务端起来之后先别急着让朋友进。自己用客户端连一下确认几件事能正常进入世界区块加载正常走动时不卡顿TPS稳定在20控制台没有报错进游戏后按F3看调试信息重点看这几个指标TPS应该在19.5以上低于18就说明性能不够内存占用看已用堆内存如果接近上限说明要给更多内存或者降视距实体数量如果某个区域实体特别多考虑清理服务端配置文件在./data目录下主要改这几个server.propertiesview-distance8 simulation-distance6 max-players5 spawn-protection0 enable-command-blocktruespawn-protection设0是因为小服不需要出生点保护设了反而碍事。Paper专属配置在./data/config/paper-global.yml可以进一步优化chunk-loading: autoconfig-send-distance: true max-concurrent-sends: 2 target-player-chunk-send-rate: 50max-concurrent-sends降到2减少同时发送区块的数量避免网络和CPU瞬时压力。4. 让朋友连进来内网穿透的选型与落地4.1 为什么需要内网穿透MC服务器跑在树莓派上树莓派在你家路由器后面用的是内网IP比如192.168.1.100。外网的朋友要连进来必须解决一个问题如何从公网访问到你家里的内网设备。常规做法是在路由器上做端口映射把公网IP的25565端口转发到树莓派。但这有两个前提一是你家宽带得有公网IP现在很多运营商默认给的是内网IP二是你得能控制路由器。如果这两个条件不满足就需要内网穿透工具。内网穿透的原理说白了就是你的树莓派主动连接一台有公网IP的服务器建立一条隧道外部流量通过这台服务器转发到你的树莓派。这样就不需要公网IP也不需要动路由器。4.2 几种主流方案的对比市面上内网穿透工具不少我试过几种各有优劣方案免费额度延迟配置难度适合场景ngrok有限随机域名中等低临时测试frp需自备服务器低中长期稳定花生壳有限中等低小白用户Cloudflare Tunnel免费中等中有域名的用户我最终选的是frp因为我有台便宜的云服务器一年几十块自建frp服务端延迟低、带宽足、完全可控。如果你没有云服务器ngrok的免费版可以先用着测试但免费版域名每次重启都变而且带宽有限不适合长期开服。4.3 frp服务端与客户端的配置服务端跑在你的云服务器上下载frp release包解压后编辑frps.tomlbindPort 7000 auth.method token auth.token 你的密钥改复杂点 # dashboard配置方便查看连接状态 webServer.addr 0.0.0.0 webServer.port 7500 webServer.user admin webServer.password 改个强密码用systemd管理frpssudo nano /etc/systemd/system/frps.service内容[Unit] Descriptionfrp server Afternetwork.target [Service] Typesimple ExecStart/usr/local/bin/frps -c /etc/frp/frps.toml Restartalways [Install] WantedBymulti-user.target启动并设置开机自启sudo systemctl enable --now frps客户端跑在树莓派上编辑frpc.tomlserverAddr 你的云服务器IP serverPort 7000 auth.method token auth.token 你的密钥 [[proxies]] name minecraft type tcp localIP 127.0.0.1 localPort 25565 remotePort 25565同样用systemd管理启动后检查云服务器上的frp dashboard看到minecraft这条代理是running状态就成功了。朋友在MC客户端里输入你的云服务器IP:25565就能连进来。注意云服务器的安全组要放行7000frp通信和25565MC连接两个端口。很多人配置都对就是忘了放行安全组卡半天找不到原因。4.4 内网穿透的延迟与稳定性实测我用frp方案实测下来从朋友那边同城连进来的延迟大概在30到50毫秒跨省的话60到100毫秒。这个延迟玩MC完全够用挖矿、打怪都感觉不到明显延迟。稳定性方面frp跑了三个月没掉过线。唯一一次断连是云服务器到期忘了续费续上重启就好了。建议在frpc配置里加上自动重连参数transport.heartbeatInterval 10 transport.heartbeatTimeout 30这样网络抖动时能自动恢复。带宽方面MC每个玩家大概需要50到100KB/s的上行带宽。frp走的是云服务器中转云服务器的带宽决定了上限。我用的云服务器是5Mbps带宽3个人同时在线完全够用。如果人数多要么升级带宽要么考虑其他方案。5. 长期运行中的性能监控与故障处理5.1 用docker stats和系统工具盯住资源服务器跑起来只是开始长期稳定运行才是考验。我习惯每天花一分钟看一眼资源占用# 看容器资源占用 docker stats mc-server # 看系统整体负载 htop # 看CPU温度 vcgencmd measure_tempdocker stats输出的几个关键指标CPU %持续超过300%即3个核心满载说明CPU吃紧考虑降视距或模拟距离MEM USAGE / LIMIT接近limit说明内存不够要么加内存要么降配置BLOCK I/O如果读写量很大说明区块加载频繁SSD是必须的CPU温度方面树莓派4B的SoC在80度以上会降频。我加了风扇之后满载温度在55到60度很安全。如果你没加风扇建议至少贴个散热片并且把容器CPU限制在2.5核以内。5.2 常见故障的排查链路故障一服务器启动后玩家连不上排查顺序docker compose logs看服务端有没有正常启动有没有报错docker ps确认容器在运行端口映射正确本地用telnet 127.0.0.1 25565测试端口是否监听检查frpc是否运行dashboard里代理是否在线检查云服务器安全组和防火墙这个顺序是从内到外先确认服务端本身没问题再排查网络链路。故障二TPS掉到15以下游戏卡顿排查顺序进游戏按F3看实体数量和区块数量是不是某个区域实体爆炸docker stats看CPU占用是不是跑满了看温度是不是过热降频了检查是不是有玩家在跑图大量新区块加载如果是实体太多可以用Paper的/kill命令清理或者装个实体清理插件。如果是跑图导致等区块加载完TPS会恢复。故障三服务器突然崩溃容器自动重启看日志找崩溃原因docker compose logs --tail 200 mc-server常见原因内存溢出OOM、Java版本不兼容、世界文件损坏。如果是OOM降低MEMORY值或者减少在线人数。如果是世界文件损坏从备份恢复。5.3 数据备份与恢复策略MC服务器最怕的就是世界数据丢失。我设置了两层备份第一层Docker volume定期快照写个脚本每天凌晨3点打包一次世界数据#!/bin/bash BACKUP_DIR/home/ubuntu/mc-backups DATE$(date %Y%m%d) mkdir -p $BACKUP_DIR tar -czf $BACKUP_DIR/world-$DATE.tar.gz -C /home/ubuntu/mc-server/data world world_nether world_the_end # 只保留最近7天的备份 find $BACKUP_DIR -name world-*.tar.gz -mtime 7 -delete加到crontab0 3 * * * /home/ubuntu/backup.sh第二层手动备份重要节点每次大版本更新、加新插件之前手动备份一次。命令很简单docker compose exec minecraft rcon-cli save-all docker compose stop tar -czf ~/mc-manual-backup-$(date %Y%m%d).tar.gz ./data docker compose start先save-all让服务端把内存里的数据写盘再停容器打包这样数据最完整。恢复的时候把备份包解压覆盖./data目录重启容器就行。提示备份文件最好同步一份到云服务器或者NAS上。树莓派的SSD万一挂了本地备份也跟着没了。我用rclone每天把备份同步到云存储多一层保障。5.4 玩家管理与白名单配置小服不需要复杂的权限系统但白名单是必须的。开着ONLINE_MODE: TRUE的情况下只有正版账号能进。如果朋友有离线账号需要关掉在线模式但这样任何人都能进必须配白名单。白名单配置在./data/whitelist.json[ { uuid: 玩家的UUID, name: 玩家ID } ]UUID可以通过docker compose exec minecraft rcon-cli进控制台用whitelist add 玩家ID自动添加。服务端配置里开启白名单white-listtrue enforce-whitelisttrueenforce-whitelist设为true白名单变更后立即踢掉不在名单里的玩家不用重启。6. 这套方案跑下来的真实体会6.1 性能与成本的平衡点整套方案的成本算一下树莓派4B已有不算、USB SSD 128GB大概80块、带风扇外壳40块、云服务器一年60块。总共不到200块换来一个能长期跑的小型MC服务器。性能上3人同时在线、视距8、模拟距离6TPS稳定在19.8到20CPU占用率60%到75%内存占用2.2GB左右。这个表现对于树莓派来说已经超出我预期了。如果你要跑更多人我的建议是优先降视距和模拟距离而不是加内存。因为瓶颈主要在CPU单核性能内存加到8GB也解决不了CPU跑满的问题。6.2 几个容易忽略的细节Java版本Paper 1.20.4需要Java 17。itzg/minecraft-server镜像会自动处理但如果你手动跑JAR记得装对版本。树莓派上装Java 17sudo apt install openjdk-17-jre-headless用headless版本不带图形界面省资源。时区问题容器内时区默认是UTC日志时间比北京时间晚8小时。compose文件里加TZ: Asia/Shanghai解决。自动重启restart: unless-stopped策略下树莓派意外断电恢复后容器会自动启动。但要注意如果世界文件正在写入时断电可能损坏。所以UPS不间断电源对长期运行的服务器来说是个值得考虑的投资哪怕是个小型的。系统更新Ubuntu Server的安全更新要定期打但内核更新后需要重启。我一般选在服务器没人玩的时候重启重启前先docker compose stop重启后再docker compose start。6.3 后续可以折腾的方向这套基础方案跑稳之后还有不少可以折腾的地方加插件Paper支持Bukkit插件领地保护如LuckPermsGriefPrevention、经济系统、小游戏都可以加。但注意插件也会吃CPU加之前评估一下。多世界用Multiverse插件开资源世界、创造世界定期重置资源世界保持主世界整洁。网页地图用Dynmap或者Squaremap生成实时网页地图朋友可以在浏览器里看服务器全貌。这个会额外吃一些CPU和内存。自动化备份到云端用rclone把备份同步到对象存储实现异地容灾。监控告警用PrometheusGrafana监控服务器状态TPS低于阈值时发通知。这套在树莓派上跑有点重可以只跑轻量的node_exporter。我个人觉得树莓派跑MC服务器最大的乐趣不在于性能多强而在于用有限的资源把一件事跑通、跑稳。每次看到TPS稳定在20朋友在里面玩得开心就觉得这块吃灰的板子总算没白买。
返回列表