化實(shí)戰(zhàn)指南)
1. 為什么要在樹莓派5上折騰Docker樹莓派5這塊板子出來(lái)之后我第一時(shí)間把手頭那臺(tái)跑了三年多的樹莓派4換了下來(lái)。原因很簡(jiǎn)單樹莓派4的USB 3.0和千兆網(wǎng)卡共享帶寬跑幾個(gè)容器之后IO就頂不住了而樹莓派5把PCIe通道單獨(dú)拉出來(lái)USB和網(wǎng)絡(luò)不再互相搶資源這對(duì)容器化部署來(lái)說(shuō)是個(gè)質(zhì)變。但很多人拿到樹莓派5之后第一反應(yīng)是我直接apt install docker.io不就行了。這個(gè)做法在樹莓派4上勉強(qiáng)能用在樹莓派5上卻會(huì)踩到幾個(gè)坑系統(tǒng)自帶的Docker版本太老不支持新版Compose的某些特性ARM64架構(gòu)下部分鏡像的拉取策略和x86不一樣再加上樹莓派5默認(rèn)的Debian Bookworm系統(tǒng)用的是cgroup v2一些老教程里的配置直接照搬會(huì)出問題。所以這篇內(nèi)容我打算把樹莓派5上Docker的安裝、配置、日常管理、常見故障排查完整講一遍。適合三類人看一是剛拿到樹莓派5想跑容器的新手二是從樹莓派4遷移過來(lái)發(fā)現(xiàn)配置不兼容的老玩家三是想把樹莓派5當(dāng)輕量級(jí)家庭服務(wù)器用、需要長(zhǎng)期穩(wěn)定運(yùn)行容器的朋友。我會(huì)把每一步為什么這么做講清楚而不是只丟一堆命令讓你復(fù)制。先說(shuō)一個(gè)核心結(jié)論樹莓派5上裝Docker不要用系統(tǒng)源里的docker.io要用Docker官方維護(hù)的APT倉(cāng)庫(kù)。原因后面會(huì)詳細(xì)展開但你可以先記住這個(gè)原則。2. 系統(tǒng)準(zhǔn)備裝Docker之前必須先做的幾件事2.1 確認(rèn)系統(tǒng)版本和架構(gòu)樹莓派5目前主流跑的是Raspberry Pi OS Bookworm基于Debian 12也有部分人刷Ubuntu Server 24.04。這兩個(gè)系統(tǒng)的包管理邏輯有差異裝Docker的步驟也不完全一樣。先確認(rèn)你手上是什么cat /etc/os-release uname -muname -m的輸出應(yīng)該是aarch64。如果是armv7l說(shuō)明你刷的是32位系統(tǒng)這時(shí)候裝Docker會(huì)遇到一堆鏡像架構(gòu)不匹配的問題。我的建議是樹莓派5直接上64位系統(tǒng)別猶豫。樹莓派5的BCM2712是四核Cortex-A7664位系統(tǒng)才能發(fā)揮它的全部性能而且現(xiàn)在絕大多數(shù)官方鏡像都有arm64版本32位反而成了累贅。2.2 更新系統(tǒng)并安裝基礎(chǔ)依賴這一步看起來(lái)是例行公事但樹莓派5剛發(fā)布那段時(shí)間官方源的固件包更新比較頻繁不更新的話可能會(huì)遇到網(wǎng)卡驅(qū)動(dòng)或者PCIe相關(guān)的兼容問題。sudo apt update sudo apt full-upgrade -y sudo apt install -y ca-certificates curl gnupg lsb-releaseca-certificates和curl是用來(lái)添加Docker官方GPG密鑰的gnupg負(fù)責(zé)密鑰管理lsb-release幫我們自動(dòng)識(shí)別系統(tǒng)代號(hào)。這幾個(gè)包在最小化安裝的Raspberry Pi OS上可能沒有預(yù)裝所以顯式裝一遍。注意full-upgrade和upgrade的區(qū)別在于前者會(huì)處理依賴關(guān)系變化可能卸載一些包。樹莓派5的內(nèi)核更新比較頻繁用full-upgrade更穩(wěn)妥。如果你有正在運(yùn)行的服務(wù)升級(jí)前先備份。2.3 關(guān)于cgroup的坑這是樹莓派5上最容易翻車的地方。Debian Bookworm默認(rèn)啟用cgroup v2而Docker從20.10版本開始才完整支持cgroup v2。如果你用的是系統(tǒng)源里的老版本Docker可能會(huì)出現(xiàn)容器啟動(dòng)后資源限制不生效、docker stats顯示異常等問題。檢查當(dāng)前cgroup版本stat -fc %T /sys/fs/cgroup/如果輸出cgroup2fs說(shuō)明是v2輸出tmpfs說(shuō)明是v1。樹莓派5的Bookworm系統(tǒng)基本都是v2。這個(gè)信息你記一下后面配置Docker的時(shí)候會(huì)用到。另外樹莓派5默認(rèn)可能沒有啟用memory cgroup需要手動(dòng)在/boot/firmware/cmdline.txt里加參數(shù)。不過實(shí)測(cè)下來(lái)只要你裝的是Docker官方最新版這一步通常不需要手動(dòng)做Docker會(huì)自動(dòng)處理。但如果你發(fā)現(xiàn)容器內(nèi)存限制不生效就要回來(lái)檢查這里。3. 安裝Docker官方倉(cāng)庫(kù)方案與系統(tǒng)源方案的取舍3.1 為什么不用apt install docker.io系統(tǒng)源里的docker.io包在Debian Bookworm上大概是20.10左右的版本。這個(gè)版本有幾個(gè)問題第一Docker Compose是獨(dú)立的Python版本docker-compose不是現(xiàn)在的Compose V2插件語(yǔ)法和功能都有差距第二對(duì)cgroup v2的支持不完整第三更新滯后遇到安全漏洞修復(fù)不及時(shí)。Docker官方倉(cāng)庫(kù)的方案裝出來(lái)的是docker-ce社區(qū)版版本新、更新快、對(duì)ARM64支持好。代價(jià)是多幾步配置但這是一次性的工作值得。3.2 添加Docker官方GPG密鑰和倉(cāng)庫(kù)sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg這里用/etc/apt/keyrings而不是老教程里的/etc/apt/trusted.gpg.d是因?yàn)楹笳邥?huì)把密鑰全局信任安全性差一些。--dearmor是把ASCII格式的密鑰轉(zhuǎn)成二進(jìn)制格式APT需要這種格式。然后添加倉(cāng)庫(kù)echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null注意這里用的是debian的倉(cāng)庫(kù)而不是raspbian。因?yàn)镽aspberry Pi OS Bookworm本質(zhì)上是Debian的arm64移植用Debian的arm64倉(cāng)庫(kù)完全兼容。如果你刷的是Ubuntu把debian換成ubuntu即可。3.3 安裝Docker引擎和Compose插件sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin這幾個(gè)包的分工docker-ce是引擎本體docker-ce-cli是命令行工具containerd.io是底層容器運(yùn)行時(shí)docker-buildx-plugin支持多架構(gòu)構(gòu)建docker-compose-plugin就是Compose V2用docker compose命令調(diào)用注意中間是空格不是橫杠。裝完之后驗(yàn)證sudo docker run hello-world如果看到Hello from Docker!就說(shuō)明裝好了。第一次運(yùn)行會(huì)拉取鏡像樹莓派5的網(wǎng)絡(luò)性能比4代好不少但國(guó)內(nèi)拉取Docker Hub鏡像可能還是慢這個(gè)后面講鏡像加速的時(shí)候再說(shuō)。3.4 把當(dāng)前用戶加入docker組默認(rèn)情況下只有root能跑Docker命令每次都要sudo很煩。把當(dāng)前用戶加到docker組sudo usermod -aG docker $USER然后必須重新登錄才生效。你可以退出SSH再連或者直接newgrp docker臨時(shí)切換。驗(yàn)證docker ps不報(bào)權(quán)限錯(cuò)誤就對(duì)了。注意docker組的權(quán)限等同于root因?yàn)槿萜骺梢話燧d宿主機(jī)任意目錄。這是Docker的設(shè)計(jì)決定不是bug。如果你的樹莓派5是多用戶共用慎重考慮是否加這個(gè)組。4. 樹莓派5特有的配置調(diào)優(yōu)4.1 配置daemon.jsonDocker的配置文件在/etc/docker/daemon.json默認(rèn)可能不存在手動(dòng)創(chuàng)建sudo nano /etc/docker/daemon.json寫入以下內(nèi)容{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 }, storage-driver: overlay2, exec-opts: [native.cgroupdriversystemd] }逐項(xiàng)解釋log-driver和log-opts是限制容器日志大小不加的話日志會(huì)無(wú)限增長(zhǎng)樹莓派的存儲(chǔ)卡很快就被寫滿這是新手最容易忽略的問題。storage-driver指定overlay2這是目前性能最好的存儲(chǔ)驅(qū)動(dòng)。exec-opts指定cgroup驅(qū)動(dòng)為systemd和Bookworm的init系統(tǒng)保持一致避免資源管理混亂。改完重啟Dockersudo systemctl restart docker4.2 鏡像加速與拉取策略國(guó)內(nèi)直接拉Docker Hub的鏡像速度不穩(wěn)定。可以配置鏡像加速器在daemon.json里加{ registry-mirrors: [https://your-mirror.example.com] }具體用哪個(gè)加速地址這里不展開因?yàn)榭捎玫牡刂方?jīng)常變你可以自行搜索當(dāng)前可用的。但我要提醒一點(diǎn)加速器只對(duì)Docker Hub的官方鏡像生效對(duì)ghcr.io、quay.io這些第三方registry無(wú)效。如果你要拉樹莓派相關(guān)的鏡像比如balena系列、linuxserver系列很多時(shí)候是從ghcr或者lscr.io拉的加速器幫不上忙只能靠網(wǎng)絡(luò)本身。另一個(gè)技巧是拉取時(shí)指定平臺(tái)。樹莓派5是arm64但有些鏡像的latest標(biāo)簽可能指向amd64拉下來(lái)跑不了。顯式指定docker pull --platform linux/arm64 nginx:alpine4.3 存儲(chǔ)位置遷移到外接SSD樹莓派5支持PCIe可以接NVMe SSD。如果你打算長(zhǎng)期跑容器強(qiáng)烈建議把Docker的數(shù)據(jù)目錄從SD卡遷到SSD。SD卡的隨機(jī)讀寫性能和壽命都不適合跑數(shù)據(jù)庫(kù)類容器。遷移步驟sudo systemctl stop docker sudo mkdir -p /mnt/ssd/docker sudo rsync -aP /var/lib/docker/ /mnt/ssd/docker/然后在daemon.json里加{ data-root: /mnt/ssd/docker }重啟Docker確認(rèn)數(shù)據(jù)目錄變了sudo systemctl start docker docker info | grep Docker Root Dir注意rsync的時(shí)候源目錄末尾的斜杠不能少/var/lib/docker/和/var/lib/docker含義不同前者是復(fù)制目錄內(nèi)容后者是復(fù)制目錄本身。這個(gè)細(xì)節(jié)搞錯(cuò)會(huì)導(dǎo)致數(shù)據(jù)路徑不對(duì)。5. 日常管理容器、鏡像、Compose的實(shí)操5.1 容器生命周期管理最常用的幾條命令我按使用頻率排docker ps # 查看運(yùn)行中的容器 docker ps -a # 查看所有容器包括已停止的 docker logs -f 容器名 # 實(shí)時(shí)查看日志 docker exec -it 容器名 bash # 進(jìn)入容器內(nèi)部 docker stats # 實(shí)時(shí)查看資源占用docker stats在樹莓派5上特別有用因?yàn)樗膬?nèi)存只有4GB或8GB跑幾個(gè)容器之后要盯著內(nèi)存別爆了。我一般會(huì)開一個(gè)終端專門跑docker stats觀察一段時(shí)間。停止和刪除docker stop 容器名 docker rm 容器名 docker rm -f 容器名 # 強(qiáng)制刪除運(yùn)行中的容器清理無(wú)用資源這個(gè)要定期做docker system prune -a # 清理所有未使用的鏡像、容器、網(wǎng)絡(luò) docker volume prune # 清理未使用的數(shù)據(jù)卷system prune -a會(huì)刪掉所有沒有被容器使用的鏡像包括你手動(dòng)pull下來(lái)還沒用的。執(zhí)行前想清楚。5.2 用Compose管理多容器應(yīng)用樹莓派5上跑單容器的情況其實(shí)不多更多是幾個(gè)容器配合比如一個(gè)Web服務(wù)加一個(gè)數(shù)據(jù)庫(kù)。這時(shí)候用Compose比手敲docker run命令清晰得多。一個(gè)典型的docker-compose.ymlservices: web: image: nginx:alpine ports: - 8080:80 volumes: - ./html:/usr/share/nginx/html restart: unless-stopped depends_on: - db db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: yourpassword volumes: - db_data:/var/lib/mysql restart: unless-stopped volumes: db_data:幾個(gè)關(guān)鍵點(diǎn)restart: unless-stopped讓容器在樹莓派重啟后自動(dòng)拉起除非你手動(dòng)停過它。depends_on只保證啟動(dòng)順序不保證db真正ready了web才啟動(dòng)這個(gè)坑后面講。數(shù)據(jù)卷用命名卷db_data而不是綁定掛載性能更好管理也更方便。啟動(dòng)docker compose up -d docker compose logs -f docker compose down注意Compose V2的命令是docker compose空格不是docker-compose橫杠。后者是V1的寫法已經(jīng)停止維護(hù)了。5.3 樹莓派5上的資源限制樹莓派5內(nèi)存有限給容器加限制是必須的。在Compose里services: web: image: nginx:alpine deploy: resources: limits: cpus: 1.0 memory: 512Mcpus: 1.0表示最多用一個(gè)核心memory: 512M表示內(nèi)存上限。注意在非Swarm模式下deploy.resources.limits在Compose V2里是生效的但如果你用的是老版本Compose可能要用mem_limit和cpus這兩個(gè)頂層字段。實(shí)測(cè)樹莓派5上Compose V2的deploy寫法沒問題。6. 踩坑實(shí)錄樹莓派5上Docker的典型故障6.1 容器啟動(dòng)報(bào)cgroup相關(guān)錯(cuò)誤現(xiàn)象容器啟動(dòng)失敗日志里出現(xiàn)failed to create cgroup或者cannot set memory limit。排查鏈路先確認(rèn)cgroup版本前面講過如果是v2檢查daemon.json里的exec-opts是否配了native.cgroupdriversystemd。然后確認(rèn)內(nèi)核命令行有沒有啟用cgroupcat /proc/cmdline | grep cgroup如果沒有cgroup_enablememory需要在/boot/firmware/cmdline.txt末尾加上注意是同一行不能換行cgroup_enablememory cgroup_memory1改完重啟樹莓派。這個(gè)坑在樹莓派4時(shí)代很常見樹莓派5的Bookworm系統(tǒng)默認(rèn)配置好一些但如果你刷的是精簡(jiǎn)版系統(tǒng)可能還是要手動(dòng)加。6.2 鏡像拉取失敗或架構(gòu)不匹配現(xiàn)象docker pull報(bào)no matching manifest for linux/arm64。原因這個(gè)鏡像沒有arm64版本。解決辦法有兩個(gè)一是找替代鏡像很多官方鏡像都有arm64版本比如nginx、redis、mysql都有二是用--platform參數(shù)強(qiáng)制拉amd64版本然后靠QEMU模擬運(yùn)行但性能會(huì)差很多樹莓派5上不推薦。排查時(shí)先看鏡像支持哪些架構(gòu)docker manifest inspect nginx:alpine | grep architecture6.3 網(wǎng)絡(luò)不通容器訪問不了外網(wǎng)現(xiàn)象容器內(nèi)ping不通外網(wǎng)或者DNS解析失敗。排查步驟先在宿主機(jī)上確認(rèn)網(wǎng)絡(luò)正常然后進(jìn)容器測(cè)試docker run --rm -it alpine ping -c 3 8.8.8.8如果IP能通但域名不通是DNS問題。檢查/etc/docker/daemon.json里有沒有配dns或者宿主機(jī)的/etc/resolv.conf是否正常。樹莓派5上如果用了某些網(wǎng)絡(luò)管理工具可能會(huì)覆蓋resolv.conf。如果IP都不通檢查iptables規(guī)則sudo iptables -L -n -t natDocker會(huì)在這里插入NAT規(guī)則。如果規(guī)則缺失重啟Docker服務(wù)通常會(huì)重新生成。6.4 存儲(chǔ)卡寫滿導(dǎo)致Docker異常這是樹莓派上最隱蔽的坑。SD卡寫滿之后Docker可能表現(xiàn)為容器啟動(dòng)失敗、鏡像拉取中斷、甚至docker ps都卡住。排查df -h du -sh /var/lib/docker/*如果/var/lib/docker/overlay2特別大說(shuō)明鏡像和容器層占了很多空間。清理docker system df # 查看Docker占用概覽 docker system prune -a --volumes--volumes會(huì)連數(shù)據(jù)卷一起清理慎用。日常維護(hù)建議每周跑一次docker system df看看趨勢(shì)別等到寫滿了才處理。7. 長(zhǎng)期運(yùn)行的經(jīng)驗(yàn)與建議樹莓派5跑Docker穩(wěn)定性比樹莓派4好很多但有幾個(gè)習(xí)慣我建議你養(yǎng)成。第一所有容器都配日志輪轉(zhuǎn)。前面daemon.json里的log-opts是全局配置但如果你有某個(gè)容器日志特別多可以在Compose里單獨(dú)給它配logging選項(xiàng)。我見過一個(gè)nginx容器因?yàn)闆]配輪轉(zhuǎn)三天寫了20GB日志直接把SD卡干滿。第二用watchtower之類的工具自動(dòng)更新鏡像要謹(jǐn)慎。自動(dòng)更新聽起來(lái)省事但樹莓派上鏡像更新后可能出現(xiàn)兼容問題尤其是數(shù)據(jù)庫(kù)類容器大版本升級(jí)可能破壞數(shù)據(jù)格式。我的做法是手動(dòng)更新更新前先docker compose pull看有哪些變化確認(rèn)沒問題再up -d。第三定期備份數(shù)據(jù)卷。Docker的數(shù)據(jù)卷在/var/lib/docker/volumes/下直接復(fù)制這個(gè)目錄可以備份但更穩(wěn)妥的方式是用一個(gè)臨時(shí)容器掛載卷然后打包docker run --rm -v db_data:/data -v $(pwd):/backup alpine tar czf /backup/db_data.tar.gz -C /data .這個(gè)命令把db_data卷的內(nèi)容打包到當(dāng)前目錄。恢復(fù)的時(shí)候反過來(lái)操作。第四監(jiān)控溫度。樹莓派5跑滿負(fù)載的時(shí)候發(fā)熱不小如果容器持續(xù)高負(fù)載建議加散熱片或者風(fēng)扇。查看溫度vcgencmd measure_temp超過80度就要考慮降負(fù)載或者加強(qiáng)散熱了長(zhǎng)期高溫會(huì)影響SD卡和板子壽命。最后說(shuō)一個(gè)我自己的體會(huì)樹莓派5上跑Docker最大的瓶頸不是CPU也不是內(nèi)存而是存儲(chǔ)IO。如果你認(rèn)真想把它當(dāng)服務(wù)器用一塊NVMe SSD是必須的投資比換更大的內(nèi)存條管用得多。我現(xiàn)在的配置是8GB版本加256GB NVMe跑十幾個(gè)容器毫無(wú)壓力docker stats里CPU常年個(gè)位數(shù)內(nèi)存用了不到一半。這套配置的性價(jià)比比買一臺(tái)低功耗x86小主機(jī)高不少。