🔑 關鍵洞察
✦ AI·GEN這篇記錄了作者幫朋友用 Docker 在自己 24/7 的家用機上架設幻獸帕魯(Palworld)專用伺服器的完整過程,整理成一份能照做的教學。緣起是朋友原本用 Radmin VPN 連線,但那類 P2P 服務穿不過 NAT 就會退回中繼、流量繞經第三方,作者索性用自己的常開主機自架。文章先破除一個迷思:主機商規格頁清一色寫「16GB 起」,但小團隊日常很省,作者實測 3~5 人約 1.2GB;真正要防的是 Palworld 知名的記憶體洩漏,靠容器 mem_limit + 每日重啟壓住即可。接著給出一份去蕪存菁的 docker-compose(port 記得加 /udp、RCON 綁 127.0.0.1),把架好之後最卡人的 UDP 連線三關逐一走通:ufw 放行 udp、路由器 port forwarding(必須 UDP)、DDNS,並拆穿兩個高頻誤區——Cloudflare 一定要用灰雲(橘雲代理不轉 UDP,開了必連不上)、UDP 遊戲封包根本不經過 nginx。後半談世界設定的坑(改 ini 會被環境變數重新生成蓋掉)、朋友「版本不符」進不去怎麼修(比對 buildid、重啟觸發 SteamCMD 更新、更新前先 RCON 廣播存檔),以及別讓 18GB 遊戲本體天天進備份碟。結尾附一份自架檢查清單。
朋友看到幻獸帕魯(Palworld)出了 1.0,揪我一起玩。他們兩年前就破過一輪,想趁這次大改版重破一次,而我那陣子剛好有空。
老實說我原本對這遊戲印象不太好,當年那個「抄寶可夢」的爭議擺在那裡。但後來它的官司打贏了,加上 1.0 的更新幅度是真的大,我想或許沒想像中嚴重,就跟著入手了。
朋友一開始是用 Radmin VPN 把大家串起來連的。這方法不能說不行,但它總讓我有點資安上的疙瘩。Radmin 這類虛擬區網走的是 P2P:兩端能直連就直連,穿不過對方的 NAT 或防火牆,就退回走它自己的。以我朋友家的網路,我不太相信每組連線都打得穿,大概率會落到中繼。中繼的代價有兩層:一是慢(封包多繞一圈遠路),二是遊戲流量得經過一家免費閉源服務的伺服器。它確實全程加密,但要不要把連線交給第三方繞一趟,對我來說是個不必要的風險。而我手上剛好有一台 24/7 開著的家用機,趁他們進度還沒推多久,我說:不如我來架一台專用伺服器,大家直接連我家。
於是有了這篇。用 Docker 架一個幻獸帕魯專用伺服器其實不難,docker compose up 幾分鐘就跑起來了。真正難的是下一步:架好了,朋友卻連不進來。 這一關卡住的人,遠比卡在「怎麼架」的人多。這篇把整條路走一遍,從資源評估、docker-compose,到最容易卡關的那道 UDP 連線,再到「朋友說版本不符進不去」怎麼修。所有指令都能照著跑,密碼跟 IP 我用佔位符,你換成自己的。
先說用哪個 image,和記憶體到底吃多少#
先講一句:多數人自架其實是用官方的專用伺服器工具(SteamCMD 直接拉 PalServer),不一定要 Docker。 我走 Docker 純粹是自己用習慣了、跟機器上其他服務一致好管理;如果你也有一台常開的 server、docker 用得順手,這條路會很舒服。我用的 image 是社群維護的 ,它把 SteamCMD 下載、設定檔生成、備份、RCON 都包好了。
記憶體要先破除一個迷思:你查主機商的規格頁,清一色寫「16GB 起、32GB 更穩」,那數字偏保守(他們也在賣 RAM)。實際上小團隊日常很省,我這台 Linux docker 跑 3~5 個人,實測大約落在 1.2GB(沒有長時間監控,是隨手看的值)。
那為什麼還要在意記憶體?因為幻獸帕魯有個的老毛病:進程本身會隨時間慢慢變肥,跟你們在遊戲裡蓋了多少東西無關。社群實測一個 4 人服連續跑、都不重啟,一週內能從 5G 爬到 8~12G。所以真正該做的不是準備 32G,而是設一個 mem_limit 擋住上限、再配每天定時重啟(重啟會釋放記憶體,有人在線就延後),把洩漏壓在合理範圍——這樣它跑再久也不會拖垮同機的其他服務。
一份最小可用的 docker-compose#
核心設定其實不多。下面這份去掉了枝節,留下真正該懂的幾行:
services:
palworld:
image: thijsvanloef/palworld-server-docker:latest
restart: unless-stopped
container_name: palworld
stop_grace_period: 30s # 收到停止訊號後,留 30 秒讓它存檔
ports:
- "8211:8211/udp" # 遊戲連線,UDP(重點,下面詳談)
- "27015:27015/udp" # Steam query,UDP
- "127.0.0.1:25575:25575" # RCON,只綁本機,外面碰不到
environment:
PLAYERS: "16"
SERVER_NAME: "My Palworld"
SERVER_PASSWORD: "<你的伺服器密碼>"
ADMIN_PASSWORD: "<你的管理密碼>"
UPDATE_ON_BOOT: "true" # 容器啟動時檢查遊戲更新
RCON_ENABLED: "true" # 自動備份/重啟要靠它優雅關機
BACKUP_ENABLED: "true"
AUTO_REBOOT_ENABLED: "true" # 每日重啟,釋放膨脹的記憶體
mem_limit: 16g
volumes:
- ./data:/palworld # 遊戲本體 + 存檔都在這幾個當下不明顯、之後會踩到的點:
8211和27015後面那個/udp不能漏。Palworld 走的是 UDP,漏了寫成 TCP,server 起得來、你本機也連得上,但外面的人一個都進不來。- RCON 綁
127.0.0.1:它是拿來讓自動備份/重啟能先廣播警告再優雅關機的管理通道,只給本機用,不該對外開。 mem_limit跟AUTO_REBOOT_ENABLED是一組的,專門對付上面說的記憶體膨脹。
真正卡人的是網路:UDP 連線三關#
docker compose up -d 之後,server 就在 8211 上跑了,你自己在同一個網段連 區網IP:8211 通常沒問題。然後朋友一連,連不進來。
因為封包要從網際網路走到你家那個容器,中間有三道關,少一道就進不來:
先讓封包進得了主機。 開兩個 UDP port:
sudo ufw allow 8211/udp comment 'Palworld game'
sudo ufw allow 27015/udp comment 'Palworld query'協定一定是 udp。這是三關裡最常被寫成 tcp 的一關。
封包從網際網路進到你家,要靠路由器把它轉發給那台主機。到路由器管理介面加兩條轉發規則:
| 外部 (WAN) | → 內部主機 | 協定 |
|---|---|---|
| 8211 | 192.168.x.x : 8211 | UDP |
| 27015 | 192.168.x.x : 27015 | UDP |
家用網路的公網 IP 通常會變動,所以掛一個 ,讓朋友記一個固定網址就好,不用每次問你 IP。如果你用 Cloudflare 管網域,這裡有個致命細節在下一段。
WARNING
Cloudflare 要用「灰雲」(DNS only),不能開「橘雲」(Proxied) Cloudflare 的橘雲代理只轉發 HTTP/HTTPS 流量,它不轉任意的 UDP 封包。你把 Palworld 的網域開成橘雲,朋友會 100% 連不上,而且錯得很安靜(網頁類服務照常,只有遊戲連不進來,很難聯想到是這裡)。一定要點成灰雲,讓網域直接解析到你家 IP。
兩個高頻誤區,先講清楚免得你白忙:
NOTE
不用改 nginx,一個字都不用動
很多人架網頁服務習慣了,一遇到「對外」就想到反向代理。但 ,而 Palworld 是 UDP 遊戲封包,走「路由器 → ufw → 容器」直通,跟 nginx 完全無關。這次 /etc/nginx 一個字都不用改。
那 27015 到底要不要開?它是 ,只影響「能不能在 Steam 的伺服器瀏覽器看到你的 server 狀態」。想極簡的話,先只開 8211,朋友直連 你的網址:8211 就能玩;之後真的有人想從 Steam 最愛清單看在線狀態,再補 27015。
世界設定的坑:直接改 ini 會被蓋掉#
server 通了之後,你大概想調一下經驗倍率之類的。這裡有個一定會踩的坑:這個 image 每次開機,會用環境變數重新生成 PalWorldSettings.ini。 你手動去改那個 ini 檔,下一次容器重啟就被蓋回去了,改了像沒改。
正確做法是把設定寫進 docker-compose.yml 的 environment 區塊,讓它生成的時候就帶上你的值。常見的幾項:
常用的世界設定(寫進 compose 的 environment)
| 環境變數 | 效果 | 範例值 |
|---|---|---|
EXP_RATE | 經驗值倍率 | 3.0 |
COLLECTION_DROP_RATE | 採集掉落倍率 | 3.0 |
DEATH_PENALTY | 死亡懲罰 | Item(只掉道具、裝備保留) |
PAL_EGG_DEFAULT_HATCHING_TIME | 蛋孵化時間(小時) | 1(預設 72) |
BASE_CAMP_WORKER_MAX_NUM | 基地工作 Pal 上限 | 20 |
SERVER_PLAYER_MAX_NUM | 人數上限 | 32 |
PVP / ENABLE_FRIENDLY_FIRE | PvP / 友軍傷害 | true / false |
改完 docker compose up -d,容器重建、用新環境變數重新生成 ini,設定就生效了。要驗證有沒有吃到,可以進容器看生成出來的 ini(docker exec palworld cat .../PalWorldSettings.ini),確認是你的值再收工。
朋友說「版本不符」進不去:是 server 落後了#
玩了幾天,某個朋友回報「進不去,顯示版本不符」。這幾乎都是同一個原因:他的 client 已經自動更新到新版,而你的 server 還停在舊版。
怎麼確認?比對 :本地 server 的 buildid 對上 Steam 最新的 buildid,不一樣就是落後了。
這裡有個很坑的假象要拆穿:容器日誌可能寫著 container is up to date,你以為已經是最新——那句話指的是 Docker image 最新,不是遊戲檔最新。 遊戲更新是 UPDATE_ON_BOOT 在容器啟動時跑一次 SteamCMD 抓的,如果你的容器已經連續跑了好幾天沒重啟,它就沒機會抓到這幾天的新版。
修法是重啟容器,觸發一次 SteamCMD 更新:
docker compose up -d --force-recreate但重啟會把線上的人踢下線,別直接動手。優雅的做法是先用 RCON 廣播、存檔,再重啟:
TIP
更新前先廣播 + 存檔,別在人家玩到一半直接踢
透過 RCON 送一句廣播(「伺服器 5 分鐘後更新重啟」)給線上玩家、觸發一次存檔,再 --force-recreate。被踢的人等他們的 client 也更新完(通常自動、幾分鐘),直接重連就好,存檔不受影響。更新約一兩分鐘(下載 ~5GB),完成後本地 buildid 就跟朋友的 client 對上了。
如果不想每次都手動盯,把 AUTO_UPDATE_ENABLED 打開,server 會定時自己檢查更新(一樣可以設有人在線先廣播再更新),遊戲一出新版就不會再卡朋友進不來。
別讓 18GB 遊戲本體天天進你的備份碟#
最後一個容易忽略的維運陷阱。如果你跟我一樣有一套每日 rsync 備份整個伺服器目錄的機制,加了 Palworld 之後要注意:那個 data/ 資料夾裝著整包遊戲本體,將近 18GB,不處理的話它會天天被塞進你的備份碟。
真正需要備份的只有存檔,不是那 18GB 遊戲檔(遊戲檔隨時能重新下載)。所以:
- 主
rsync排除掉palworld/data(遊戲本體) - 單獨備份存檔目錄(
Pal/Saved),那才是刪了會心痛的東西 - 把 Palworld 存檔也納入你既有的舊備份清理迴圈(例如只留 7 天)
.gitignore 那邊也順手確認 data/ 有被排除,免得 18GB 遊戲檔跟著進版控。
一頁式清單#
把整條路濃縮成可照抄的順序:
幻獸帕魯自架檢查清單
- 記憶體別被嚇到:小團隊實測 1~2G 就夠(主機商的 16G 偏保守);真正要防的是記憶體洩漏,靠容器
mem_limit+ 每日重啟壓住。 - compose:port 記得加
/udp;RCON 綁127.0.0.1;密碼寫環境變數。 - 網路三關:ufw 放行
udp→ 路由器 port forwarding(UDP!) → DDNS。 - Cloudflare 用灰雲,橘雲代理不轉 UDP,開了必連不上。
- 不用碰 nginx,UDP 遊戲封包不經過反向代理。
- 世界設定寫進 compose 的 environment,別手改 ini(會被重新生成蓋掉)。
- 朋友版本不符 = server 落後;比對 buildid,重啟容器觸發 SteamCMD 更新,更新前先 RCON 廣播 + 存檔。
- 備份排除遊戲本體(18GB),只單獨備份存檔目錄。
- thijsvanloef/palworld-server-docker —— 這篇用的 Docker 映像GitHub
- Palworld 官方專用伺服器說明Palworld Wiki
- Cloudflare —— 為什麼 Proxy(橘雲)只走 HTTP/HTTPSCloudflare Docs
還沒有留言
✨ 成為第一個留言的人吧