Docker APT 讓 Ubuntu 更新不亂套
用 Docker 官方 APT repo 統一更新 Ubuntu 上的 Engine、Compose、Buildx,避免版本漂移與套件打架。

用 Docker 官方 APT repo,Ubuntu 上的 Engine、Compose、Buildx 可以一起更新,不用再跟版本漂移打架。
我在 Ubuntu 機器上管 Docker 很多年了,老實講,最煩的從來不是裝不起來,是「裝得起來但每台都長得不一樣」。這台 Engine 版本新一點,那台 Compose 還卡在舊插件;Buildx 有時候在,有時候不在;然後你照著某篇教學做,下一次更新又冒出一個奇怪的差異。那種感覺很像你以為自己在維護一套工具,結果其實是在收拾一堆歷史包袱。
我後來才慢慢想通:Docker 不該被當成一次性安裝,而是要當成一個完整套件來管。Engine、Compose、Buildx,全部從同一個來源來,Ubuntu 自己的 Docker 套件就別再混進來。這件事很無聊,但無聊通常才是對的,尤其是你不想在半夜追 package drift 的時候。
這次拆的方法論,起點是 Matija 的這篇 Update Docker to Latest Version on Ubuntu。他把 Ubuntu 26.04、24.04、22.04 的更新路徑講得很直白,重點也很實際:Docker 官方 APT repo、docker-ce、Compose、Buildx,還有怎麼處理版本不一致的問題。
別再讓 Ubuntu 和 Docker 各管各的
訂閱 AI 趨勢週報
每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。
不會寄垃圾信,隨時可取消。
Update Docker to the latest version on Ubuntu 26.04, 24.04, or 22.04 using Docker’s official APT repo. Covers docker-ce, Compose, Buildx, and mismatch fixes.
翻譯一下就是:不要讓 Ubuntu 的套件庫跟 Docker 自己的套件庫同時想當老大。你如果今天從這邊裝 Engine、明天又從另一邊裝 Compose,短期看起來像是有裝好,長期就是等著出怪事。Engine 先升、插件沒升;Buildx 被換掉;某台機器的 CLI 路徑跟另一台不一樣。這些都不是大爆炸,但很會偷時間。

我自己就踩過這種坑。兩台 Ubuntu 機器,一台是 distro repo 裝的 Docker,另一台是 Docker CE。表面上都能跑,真要 build image 的時候,行為差超多。不是那種一眼看得出來的錯,而是那種你會開始懷疑自己是不是記錯指令的怪問題。這種事最浪費的不是錯誤本身,是你對環境的信任感。
實操寫法很簡單:把 Docker 官方 repo 當唯一來源,Engine、Compose、Buildx 都從那裡來。已經混裝的機器,先清掉再升級,不要指望碰運氣。先看 apt 裡到底裝了什麼,移掉衝突套件,再重新裝回同一條供應鏈。重點不是帥,是一致。
- Docker Engine、Compose、Buildx 用同一個套件來源。
- 不要混 Ubuntu repo 和 Docker CE repo。
- 每次更新後都檢查版本,別只看 apt 成功訊息。
先把 repo 建好,再讓 apt 幫你做髒活
Docker 官方 repo 的好處不是炫技,是它夠穩。你先加 GPG key,再加官方 APT source,更新套件索引,最後一次把需要的套件裝齊。這樣 apt 知道要去哪裡拿更新,不會把你帶去奇怪的依賴地獄。
我喜歡這種做法,因為它讓升級變得可預期。新版本出來,apt 看得到;你想鎖版,也能鎖;哪天機器重建,流程還是同一套,不會變成「從某篇部落格複製一段 shell,然後祈禱明年還能用」。我真的做過太多這種事,壽命都不長。
翻譯一下就是:repo 是底座,底座錯了,後面全都不用談。你要的是一條穩定的更新路徑,不是每次都重新發明安裝流程。官方文件在這裡最有用:Docker Ubuntu 安裝文件。我不是要重寫它,我只是把它的思路說白一點。
實操寫法:照官方文件把 repo 建起來,然後一次裝 Engine 和 plugins。裝完立刻查版本,不要等到出事才回頭看。這種步驟最好放進腳本或 provisioning,別靠手打記憶。
- 先加 Docker repo,再裝任何 Docker 套件。
- Engine、Compose、Buildx 一次裝齊。
- 裝完用 docker version、docker compose version、docker buildx version 驗證。
Compose 和 Buildx 不該被當成附屬品
這一段很多人會跳過,然後之後才開始怪 Docker 不穩。Compose 和 Buildx 不是裝飾品,它們就是工作流的一部分。Engine 升了,插件沒跟上,行為差異就會開始冒出來,而且通常不是在最舒服的時候冒出來。

Matija 的文章會把 Compose 和 Buildx 一起講,我覺得這點很對。很多更新教學只講 Docker Engine,好像大家都不用 compose、也不用 multi-platform build。現實剛好相反,大多數人碰得最多的是 compose,Buildx 也是第一次做跨平台 image 或碰到新版 build 功能時才會真的在意。你不把它們一起管,Docker 就會看起來像老半天沒整理過。
也就是說,你應該把 Docker 當 bundle,不是單一 package。Engine、Compose plugin、Buildx plugin 要一起檢查。只要其中一個落後,整組體驗就會慢半拍。
實操寫法:更新後固定跑三個指令,直接把它變成肌肉記憶。
docker version
docker compose version
docker buildx version如果其中一個失敗,或版本跟你預期的不一樣,不要當沒看到。那就是警報。先修 package source 或重裝 plugin,再往下做。
版本檢查不是多餘,是便宜保險
我現在已經不太相信「apt 裝成功」這件事本身了。套件管理員很客氣,客氣到有點會騙人。它會跟你說安裝完成,但你之後才發現 CLI plugin 沒裝到、版本不是你要的、或某個 symlink 指到奇怪的地方。所以我每次升級完,都會立刻做版本檢查。
這聽起來很麻煩,但你被坑過一次之後就知道,這其實很省錢。快速查版本可以幫你確認 repo 對不對、plugin 有沒有真的落地、Docker 有沒有吃到你以為的那組 binaries。尤其 Ubuntu 上如果你以前手動裝過 Docker,舊檔案很愛陰魂不散。
翻譯一下就是:apt 說完工,不代表真的完工。真正完工是你常用的指令都回到正確版本,而且行為正常。這才算數。
實操寫法:每次更新 Docker 後,固定檢查 Engine、Compose、Buildx。你如果管多台 Ubuntu 主機,順手比對不同機器的輸出。版本一旦漂掉,你會比使用者先看到。
- 安裝完立刻跑版本檢查。
- 多台機器就比對輸出,別只看單台。
- 如果指令指到舊 binary,先清掉舊安裝。
Ubuntu 升級時,Docker 不能跟著一起亂掉
我會喜歡這種 repo-based 做法,還有一個原因:它比較扛得住 OS 升級。Ubuntu 22.04、24.04、26.04 本來就不是同一個環境,如果你的 Docker 是從一堆混雜套件拼起來的,OS 一升級,之前那些亂七八糟的選擇就會全部浮出來。很多人這時候會怪新版本 Ubuntu,其實常常是自己前面裝得太隨便。
Docker 官方 repo 至少讓路徑清楚一點。你可以在新 Ubuntu 版本上刷新 repo metadata,必要時重裝套件,然後回到一個已知狀態。我不是說升級會變輕鬆,還是要檢查,但它不會再像在垃圾堆裡找鑰匙。
也就是說,你的 container workflow 應該能跟著 OS 維護一起活下來。你如果跑的是 local dev machine、CI runner、或小型伺服器,Docker 安裝就該穩到不會因為 Ubuntu 升級而整套重來。
實操寫法:升級 Ubuntu 前先記錄 Docker 版本和已裝套件。升級後刷新 repo 設定、必要時重裝官方套件,再驗證一次指令。若你有 automation,把這些檢查直接寫進 playbook,不要靠記憶。
把更新流程寫成規則,不要寫成手藝
我覺得這篇最有價值的地方,不是 Docker 本身,而是它逼你不要把 setup 當成一次性的手工活。我看過太多系統,之所以難維護,不是因為技術很複雜,是因為只有某個人記得六個月前手動改過什麼。那種系統不是運作中,是在等事故單。
Matija 的文章有用,因為它把流程收斂成幾個固定動作:官方 repo、一致套件、版本檢查、必要時處理 mismatch。這就是我想留在任何會重複碰到的機器上的做法。以後再回來看,也要一眼就知道該怎麼走,不要有神秘套件,也不要有「先 curl 再 pipe bash」那種讓人心累的東西。
實操寫法:把安裝與更新步驟放進內部文件、shell script,或 provisioning tool。版本檢查命令就放在安裝命令旁邊。團隊裡任何一個人要更新 Docker,都應該不用猜哪個來源才安全。
再講白一點,如果你現在那台機器已經很亂,不要想著遮掩。直接整理掉。把壞掉的 Docker install 清乾淨,通常比你之後追 weird behavior 省時間得多。
可抄的模板
# Ubuntu 上用 Docker 官方 APT repo 更新 Docker
# 適用 Ubuntu 22.04 / 24.04 / 26.04
set -euo pipefail
# 1) 移除可能衝突的舊套件
sudo apt-get remove -y docker docker-engine docker.io containerd runc || true
# 2) 安裝前置套件
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
# 3) 加入 Docker 官方 GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 4) 加入 Docker 官方 APT repo
. /etc/os-release
ARCH=$(dpkg --print-architecture)
CODENAME=${UBUNTU_CODENAME:-$VERSION_CODENAME}
echo \
"deb [arch=${ARCH} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
${CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 5) 安裝 Engine、Compose、Buildx
sudo apt-get update
sudo apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
# 6) 驗證版本
docker version
docker compose version
docker buildx version
# 7) 可選:讓目前使用者不用 sudo 跑 Docker
sudo usermod -aG docker "$USER"
echo "請登出再登入,群組權限才會生效。"這段我會直接放進 repo 或內部 runbook。它不花俏,但它做對了幾件事:同一個來源、插件一起裝、版本可以驗證。這才是我想要的 Docker 更新方式。
原始靈感來自 Matija 的 Update Docker to Latest Version on Ubuntu;我這篇是把他的做法拆成可執行的版本,裡面有原創整理,也有從原文延伸出的實作模板。