树莓派4B搭建Minecraft服务器:Docker部署与内网穿透实战
2026/9/21 20:31:20 网站建设 项目流程

1. 为什么我选择用树莓派4B跑MC服务器

1.1 一台闲置开发板的再利用思路

手里有块树莓派4B,4GB内存版本,买来原本是想做家庭自动化网关,结果折腾了两周就吃灰了。后来几个朋友想开个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年,不用频繁折腾系统升级。

烧录步骤不复杂,但有几个细节容易翻车:

  1. 下载镜像:去Ubuntu官网找Raspberry Pi版本,选64位。注意是预装桌面还是Server版,我们选Server版,省资源。
  2. 烧录工具:用Raspberry Pi Imager或者balenaEtcher都行。我习惯用Raspberry Pi Imager,因为它可以在烧录前直接配置WiFi、主机名、SSH密钥,省得烧完还要接显示器改配置。
  3. 烧录目标:如果你用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 ubuntu@192.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来说太小。虽然我们不希望频繁用swap(SSD写入寿命有限),但留一些作为缓冲是必要的。我一般设2GB:

sudo 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.swappiness=10' | sudo tee -a /etc/sysctl.conf sudo sysctl -p

文件句柄数:MC服务端会打开大量文件,默认的1024可能不够。改到65535:

echo '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 versiondocker compose version都能正常输出就OK。

提示:树莓派是ARM64架构,拉镜像时要注意选支持arm64的。Docker Hub上很多镜像只提供amd64,拉下来跑不了。后面选MC服务端镜像时会专门说这个。

3.2 选对服务端镜像:原版、Paper还是Fabric

MC服务端有好几种实现,选哪个直接决定性能和功能:

服务端类型特点树莓派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.properties

view-distance=8 simulation-distance=6 max-players=5 spawn-protection=0 enable-command-block=true

spawn-protection设0是因为小服不需要出生点保护,设了反而碍事。

Paper专属配置./data/config/paper-global.yml,可以进一步优化:

chunk-loading: autoconfig-send-distance: true max-concurrent-sends: 2 target-player-chunk-send-rate: 50

max-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.toml

bindPort = 7000 auth.method = "token" auth.token = "你的密钥,改复杂点" # dashboard配置,方便查看连接状态 webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "admin" webServer.password = "改个强密码"

用systemd管理frps:

sudo nano /etc/systemd/system/frps.service

内容:

[Unit] Description=frp server After=network.target [Service] Type=simple ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml Restart=always [Install] WantedBy=multi-user.target

启动并设置开机自启:

sudo systemctl enable --now frps

客户端(跑在树莓派上):

编辑frpc.toml

serverAddr = "你的云服务器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就能连进来。

注意:云服务器的安全组要放行7000(frp通信)和25565(MC连接)两个端口。很多人配置都对,就是忘了放行安全组,卡半天找不到原因。

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_temp

docker stats输出的几个关键指标:

  • CPU %:持续超过300%(即3个核心满载)说明CPU吃紧,考虑降视距或模拟距离
  • MEM USAGE / LIMIT:接近limit说明内存不够,要么加内存要么降配置
  • BLOCK I/O:如果读写量很大,说明区块加载频繁,SSD是必须的

CPU温度方面,树莓派4B的SoC在80度以上会降频。我加了风扇之后,满载温度在55到60度,很安全。如果你没加风扇,建议至少贴个散热片,并且把容器CPU限制在2.5核以内。

5.2 常见故障的排查链路

故障一:服务器启动后玩家连不上

排查顺序:

  1. docker compose logs看服务端有没有正常启动,有没有报错
  2. docker ps确认容器在运行,端口映射正确
  3. 本地用telnet 127.0.0.1 25565测试端口是否监听
  4. 检查frpc是否运行,dashboard里代理是否在线
  5. 检查云服务器安全组和防火墙

这个顺序是从内到外,先确认服务端本身没问题,再排查网络链路。

故障二:TPS掉到15以下,游戏卡顿

排查顺序:

  1. 进游戏按F3看实体数量和区块数量,是不是某个区域实体爆炸
  2. docker stats看CPU占用,是不是跑满了
  3. 看温度,是不是过热降频了
  4. 检查是不是有玩家在跑图,大量新区块加载

如果是实体太多,可以用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

加到crontab:

0 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-list=true enforce-whitelist=true

enforce-whitelist设为true,白名单变更后立即踢掉不在名单里的玩家,不用重启。

6. 这套方案跑下来的真实体会

6.1 性能与成本的平衡点

整套方案的成本算一下:树莓派4B(已有,不算)、USB SSD 128GB大概80块、带风扇外壳40块、云服务器一年60块。总共不到200块,换来一个能长期跑的小型MC服务器。

性能上,3人同时在线、视距8、模拟距离6,TPS稳定在19.8到20,CPU占用率60%到75%,内存占用2.2GB左右。这个表现对于树莓派来说已经超出我预期了。

如果你要跑更多人,我的建议是优先降视距和模拟距离,而不是加内存。因为瓶颈主要在CPU单核性能,内存加到8GB也解决不了CPU跑满的问题。

6.2 几个容易忽略的细节

Java版本:Paper 1.20.4需要Java 17。itzg/minecraft-server镜像会自动处理,但如果你手动跑JAR,记得装对版本。树莓派上装Java 17:

sudo 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插件,领地保护(如LuckPerms+GriefPrevention)、经济系统、小游戏都可以加。但注意插件也会吃CPU,加之前评估一下。
  • 多世界:用Multiverse插件开资源世界、创造世界,定期重置资源世界,保持主世界整洁。
  • 网页地图:用Dynmap或者Squaremap生成实时网页地图,朋友可以在浏览器里看服务器全貌。这个会额外吃一些CPU和内存。
  • 自动化备份到云端:用rclone把备份同步到对象存储,实现异地容灾。
  • 监控告警:用Prometheus+Grafana监控服务器状态,TPS低于阈值时发通知。这套在树莓派上跑有点重,可以只跑轻量的node_exporter。

我个人觉得,树莓派跑MC服务器最大的乐趣不在于性能多强,而在于用有限的资源把一件事跑通、跑稳。每次看到TPS稳定在20,朋友在里面玩得开心,就觉得这块吃灰的板子总算没白买。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询