# 升級 Docker & Harbor on rhel9
* 升級 docker 26.0.0 -> 29.1.5
* 升級 docker compose v2.25.0 -> v5.0.1
* 升級 harbor v2.1.3 -> v2.10.1
- harbor 的升級路徑為 v2.1.3 -> v2.4.0 -> v2.6.0 -> v2.8.0 -> v2.10.1
## rhel 安裝舊版本 Docker & Harbor
### 安裝 docker
* 新增 docker repo
```
$ sudo dnf -y install dnf-plugins-core
$ sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
```
* 搜尋可安裝 docker 套件
```
$ sudo dnf list docker-ce --showduplicates | sort -r
Updating Subscription Management repositories.
docker-ce.x86_64 3:29.0.2-1.el9 docker-ce-stable
docker-ce.x86_64 3:29.0.1-1.el9 docker-ce-stable
docker-ce.x86_64 3:29.0.0-1.el9 docker-ce-stable
docker-ce.x86_64 3:28.5.2-1.el9 docker-ce-stable
docker-ce.x86_64 3:28.5.1-1.el9 docker-ce-stable
docker-ce.x86_64 3:28.5.0-1.el9 docker-ce-stable
$ sudo dnf list docker-ce-cli --showduplicates | sort -r
Updating Subscription Management repositories.
Last metadata expiration check: 0:03:12 ago on Fri 21 Nov 2025 10:57:35 AM CST.
docker-ce-cli.x86_64 1:29.0.2-1.el9 docker-ce-stable
docker-ce-cli.x86_64 1:29.0.1-1.el9 docker-ce-stable
docker-ce-cli.x86_64 1:29.0.0-1.el9 docker-ce-stable
docker-ce-cli.x86_64 1:28.5.2-1.el9 docker-ce-stable
docker-ce-cli.x86_64 1:28.5.1-1.el9 docker-ce-stable
docker-ce-cli.x86_64 1:28.5.0-1.el9 docker-ce-stable
$ sudo dnf list docker-compose-plugin --showduplicates | sort -r
Updating Subscription Management repositories.
Last metadata expiration check: 0:10:50 ago on Fri 21 Nov 2025 10:57:35 AM CST.
Installed Packages
docker-compose-plugin.x86_64 2.40.3-1.el9 docker-ce-stable
docker-compose-plugin.x86_64 2.40.3-1.el9 @docker-ce-stable
docker-compose-plugin.x86_64 2.40.2-1.el9 docker-ce-stable
docker-compose-plugin.x86_64 2.40.1-1.el9 docker-ce-stable
docker-compose-plugin.x86_64 2.40.0-1.el9 docker-ce-stable
docker-compose-plugin.x86_64 2.39.4-1.el9 docker-ce-stable
docker-compose-plugin.x86_64 2.39.2-1.el9 docker-ce-stable
```
* 下載舊版本
```
$ mkdir old-package
$ sudo yum install --downloadonly --downloaddir="$HOME"/old-package \
docker-ce-3:26.0.0-1.el9 \
docker-ce-cli-1:26.0.0-1.el9 \
containerd.io \
docker-buildx-plugin-0.13.1-1.el9 \
docker-compose-plugin-2.25.0-1.el9
```
* 安裝舊版本
```
$ sudo yum localinstall --nogpgcheck "$HOME"/old-package/*.rpm
```
```
$ sudo systemctl enable --now docker
```
```
$ sudo docker info
Client: Docker Engine - Community
Version: 26.0.0
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.13.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.25.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 26.0.0
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: dea7da592f5d1d2b7755e3a161be07f43fad8f75
runc version: v1.3.4-0-gd6d73eb8
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 5.14.0-427.13.1.el9_4.x86_64
Operating System: Red Hat Enterprise Linux 9.4 (Plow)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.505GiB
Name: upgrade
ID: 00d462e4-d14c-4c0e-b58b-81e0e6f50fcc
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
```
* 安裝 docker switch,目的是讓 docker compose 可以轉換成 docker-compose 指令
```
$ sudo curl -fL https://github.com/docker/compose-switch/releases/latest/download/docker-compose-linux-amd64 -o /usr/local/bin/compose-switch
$ sudo chmod +x /usr/local/bin/compose-switch
$ sudo update-alternatives --install /usr/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99
$ sudo docker-compose version
Docker Compose version v2.25.0
```
### 安裝 Harbor
```
$ wget https://github.com/goharbor/harbor/releases/download/v2.1.3/harbor-offline-installer-v2.1.3.tgz
$ tar xvf harbor-offline-installer-v2.1.3.tgz; cd harbor/
```
```
$ mkdir ssl;cd ssl
$ wget https://raw.githubusercontent.com/cooloo9871/SelfSigned-RootCA/master/mk
$ chmod +x mk
$ ./mk create harbor.example.com 10.10.7.16
$ cd ..
```
```
$ cp harbor.yml.tmpl harbor.yml
$ nano harbor.yml
# Configuration file of Harbor
# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: harbor.example.com
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 80
# https related config
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
certificate: /home/bigred/harbor/ssl/cert.pem
private_key: /home/bigred/harbor/ssl/cert-key.pem
```
* 啟動 harbor
```
$ sudo ./install.sh --with-trivy
```
## 準備離線檔
### 準備 docker
* 下載現在最新版本
```
$ mkdir package
$ sudo yum install --downloadonly --downloaddir="$HOME"/package \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
```
```
$ ls -l package/
總用量 96640
-rw-r--r--. 1 root root 37088865 1月 21 15:42 containerd.io-2.2.1-1.el9.x86_64.rpm
-rw-r--r--. 1 root root 17919221 1月 21 15:42 docker-buildx-plugin-0.30.1-1.el9.x86_64.rpm
-rw-r--r--. 1 root root 23144731 1月 21 15:42 docker-ce-29.1.5-1.el9.x86_64.rpm
-rw-r--r--. 1 root root 8744991 1月 21 15:42 docker-ce-cli-29.1.5-1.el9.x86_64.rpm
-rw-r--r--. 1 root root 3602234 1月 21 15:42 docker-ce-rootless-extras-29.1.5-1.el9.x86_64.rpm
-rw-r--r--. 1 root root 8446036 1月 21 15:42 docker-compose-plugin-5.0.1-1.el9.x86_64.rpm
$ tar -zcvf docker.tar.gz package/
```
### 準備 Harbor
```
$ wget https://github.com/goharbor/harbor/releases/download/v2.4.0/harbor-offline-installer-v2.4.0.tgz
$ wget https://github.com/goharbor/harbor/releases/download/v2.6.0/harbor-offline-installer-v2.6.0.tgz
$ wget https://github.com/goharbor/harbor/releases/download/v2.8.0/harbor-offline-installer-v2.8.0.tgz
$ wget https://github.com/goharbor/harbor/releases/download/v2.10.1/harbor-offline-installer-v2.10.1.tgz
```
### 打包所有檔案
```
$ tar -czvf harbor.tar.gz \
docker.tar.gz \
harbor-offline-installer-v2.4.0.tgz \
harbor-offline-installer-v2.6.0.tgz \
harbor-offline-installer-v2.8.0.tgz \
harbor-offline-installer-v2.10.1.tgz
$ ls -lh harbor.tar.gz
-rw-r--r--. 1 bigred bigred 2.6G Jan 21 16:28 harbor.tar.gz
```
## 開始升級
### 升級 docker 版本
* 安裝遇到 repo 報錯可以跳過有問題的 repo,添加參數`--disablerepo=rhel9.4-baseos,rhel9.4-appstream`
```
$ tar -zxvf harbor.tar.gz
$ tar -zxvf docker.tar.gz
$ sudo yum localinstall --nogpgcheck "$HOME"/package/*.rpm
```
```
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```
```
$ sudo docker info
Client: Docker Engine - Community
Version: 29.1.5
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.30.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v5.0.1
Path: /usr/libexec/docker/cli-plugins/docker-compose
```
### 升級 harbor v2.1.3 -> v2.4.0
* 關閉 harbor 服務
```
$ cd harbor
$ sudo docker compose down
```
* 建立備份目錄,建議直接備份 VM
```
$ cd ~
$ sudo mkdir /harbor-backup
```
* 備份 harbor
```
$ sudo mv harbor /harbor-backup/harbor
```
* 備份資料庫
```
$ sudo cp -r /data/database /harbor-backup/
```
* 解包新版 harbor,並匯入新版 image
```
$ tar -zxvf harbor-offline-installer-v2.4.0.tgz
$ sudo docker image load -i harbor/harbor.v2.4.0.tar.gz
```
* 升級 `harbor.yml` 文件,注意自己舊版的 `harbor.yml` 路徑,`migrate -i` 指令後面是放舊版 `harbor.yml` 位置,他會覆蓋掉原本的檔案,因此還要把他在做備份
```
$ cp /harbor-backup/harbor/harbor.yml /harbor-backup/harbor/harbor2.yml
$ sudo docker run -it --rm -v /:/hostfs goharbor/prepare:v2.4.0 migrate -i /harbor-backup/harbor/harbor.yml
# 將升級好的 harbor.yml 複製到 harbor/
$ cp /harbor-backup/harbor/harbor.yml harbor/
```
* 把原有憑證複製回來
```
$ cp -r /harbor-backup/harbor/ssl harbor/
```
* 安裝新版 harbor
```
$ cd harbor
$ sudo ./install.sh --with-trivy
```
* 檢查升級狀態
```
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
88759773d8bd goharbor/nginx-photon:v2.4.0 "nginx -g 'daemon of…" 12 seconds ago Up 10 seconds (health: starting) 0.0.0.0:80->8080/tcp, [::]:80->8080/tcp, 0.0.0.0:443->8443/tcp, [::]:443->8443/tcp nginx
173cb6fbc783 goharbor/harbor-jobservice:v2.4.0 "/harbor/entrypoint.…" 12 seconds ago Up 10 seconds (health: starting) harbor-jobservice
539434c87afd goharbor/harbor-core:v2.4.0 "/harbor/entrypoint.…" 12 seconds ago Up 10 seconds (health: starting) harbor-core
651160f11dd0 goharbor/trivy-adapter-photon:v2.4.0 "/home/scanner/entry…" 12 seconds ago Up 10 seconds (health: starting) trivy-adapter
ba62547d28aa goharbor/harbor-registryctl:v2.4.0 "/home/harbor/start.…" 12 seconds ago Up 11 seconds (health: starting) registryctl
6d53377e2d35 goharbor/redis-photon:v2.4.0 "redis-server /etc/r…" 12 seconds ago Up 11 seconds (health: starting) redis
4f3e024f5fa6 goharbor/registry-photon:v2.4.0 "/home/harbor/entryp…" 12 seconds ago Up 11 seconds (health: starting) registry
ff09cef7d623 goharbor/harbor-portal:v2.4.0 "nginx -g 'daemon of…" 12 seconds ago Up 11 seconds (health: starting) harbor-portal
7817a34ed7f5 goharbor/harbor-db:v2.4.0 "/docker-entrypoint.…" 12 seconds ago Up 11 seconds (health: starting) harbor-db
5b74384c46f4 goharbor/harbor-log:v2.4.0 "/bin/sh -c /usr/loc…" 12 seconds ago Up 11 seconds (health: starting) 127.0.0.1:1514->10514/tcp
```
* 清理備份
```
$ sudo rm -r /harbor-backup/*
```
### 升級 harbor v2.4.0 -> v2.6.0
* 關閉 harbor 服務
```
$ sudo docker compose down
$ cd ~
```
* 備份 harbor
```
$ sudo mv harbor /harbor-backup/harbor
```
* 備份資料庫
```
$ sudo cp -r /data/database /harbor-backup/
```
* 解包新版 harbor,並匯入新版 image
```
$ tar -zxvf harbor-offline-installer-v2.6.0.tgz
$ sudo docker image load -i harbor/harbor.v2.6.0.tar.gz
```
* 升級 `harbor.yml` 文件,注意自己舊版的 `harbor.yml` 路徑,`migrate -i` 指令後面是放舊版 `harbor.yml` 位置,他會覆蓋掉原本的檔案,因此還要把他在做備份
```
$ cp /harbor-backup/harbor/harbor.yml /harbor-backup/harbor/harbor2.yml
$ sudo docker run -it --rm -v /:/hostfs goharbor/prepare:v2.6.0 migrate -i /harbor-backup/harbor/harbor.yml
# 將升級好的 harbor.yml 複製到 harbor/
$ cp /harbor-backup/harbor/harbor.yml harbor/
```
* 把原有憑證複製回來
```
$ cp -r /harbor-backup/harbor/ssl harbor/
```
* 安裝新版 harbor
```
$ cd harbor
$ sudo ./install.sh --with-trivy
```
* 檢查升級狀態
```
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f98a19893c93 goharbor/nginx-photon:v2.6.0 "nginx -g 'daemon of…" 6 seconds ago Up 3 seconds (health: starting) 0.0.0.0:80->8080/tcp, [::]:80->8080/tcp, 0.0.0.0:443->8443/tcp, [::]:443->8443/tcp nginx
dc6583e305bc goharbor/harbor-jobservice:v2.6.0 "/harbor/entrypoint.…" 6 seconds ago Up 2 seconds (health: starting) harbor-jobservice
b3a3b8f12e1f goharbor/harbor-core:v2.6.0 "/harbor/entrypoint.…" 6 seconds ago Up 4 seconds (health: starting) harbor-core
9b4015223bb1 goharbor/trivy-adapter-photon:v2.6.0 "/home/scanner/entry…" 6 seconds ago Up 4 seconds (health: starting) trivy-adapter
9dfce4c75bac goharbor/redis-photon:v2.6.0 "redis-server /etc/r…" 6 seconds ago Up 5 seconds (health: starting) redis
82e81bd21793 goharbor/registry-photon:v2.6.0 "/home/harbor/entryp…" 6 seconds ago Up 5 seconds (health: starting) registry
095b9ceb1885 goharbor/harbor-db:v2.6.0 "/docker-entrypoint.…" 6 seconds ago Up 5 seconds (health: starting) harbor-db
dc402a4c9a67 goharbor/harbor-portal:v2.6.0 "nginx -g 'daemon of…" 6 seconds ago Up 5 seconds (health: starting) harbor-portal
d4059d90b0ee goharbor/harbor-registryctl:v2.6.0 "/home/harbor/start.…" 6 seconds ago Up 5 seconds (health: starting) registryctl
5727a3fa56ed goharbor/harbor-log:v2.6.0 "/bin/sh -c /usr/loc…" 6 seconds ago Up 5 seconds (health: starting) 127.0.0.1:1514->10514/tcp harbor-log
```
* 清理備份
```
$ sudo rm -r /harbor-backup/*
```
### 升級 harbor v2.6.0 -> v2.8.0
* 關閉 harbor 服務
```
$ sudo docker compose down
$ cd ~
```
* 備份 harbor
```
$ sudo mv harbor /harbor-backup/harbor
```
* 備份資料庫
```
$ sudo cp -r /data/database /harbor-backup/
```
* 解包新版 harbor,並匯入新版 image
```
$ tar -zxvf harbor-offline-installer-v2.8.0.tgz
$ sudo docker image load -i harbor/harbor.v2.8.0.tar.gz
```
* 升級 `harbor.yml` 文件,注意自己舊版的 `harbor.yml` 路徑,`migrate -i` 指令後面是放舊版 `harbor.yml` 位置,他會覆蓋掉原本的檔案,因此還要把他在做備份
```
$ cp /harbor-backup/harbor/harbor.yml /harbor-backup/harbor/harbor2.yml
$ sudo docker run -it --rm -v /:/hostfs goharbor/prepare:v2.8.0 migrate -i /harbor-backup/harbor/harbor.yml
# 將升級好的 harbor.yml 複製到 harbor/
$ cp /harbor-backup/harbor/harbor.yml harbor/
```
* 把原有憑證複製回來
```
$ cp -r /harbor-backup/harbor/ssl harbor/
```
* 安裝新版 harbor
```
$ cd harbor
$ sudo ./install.sh --with-trivy
```
* 檢查升級狀態
```
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f1d634f75505 goharbor/harbor-jobservice:v2.8.0 "/harbor/entrypoint.…" 11 seconds ago Up 8 seconds (health: starting) harbor-jobservice
37a67f3e310b goharbor/nginx-photon:v2.8.0 "nginx -g 'daemon of…" 11 seconds ago Up 9 seconds (health: starting) 0.0.0.0:80->8080/tcp, [::]:80->8080/tcp, 0.0.0.0:443->8443/tcp, [::]:443->8443/tcp nginx
e1f959fac081 goharbor/trivy-adapter-photon:v2.8.0 "/home/scanner/entry…" 11 seconds ago Up 9 seconds (health: starting) trivy-adapter
0ecbacc2295b goharbor/harbor-core:v2.8.0 "/harbor/entrypoint.…" 11 seconds ago Up 9 seconds (health: starting) harbor-core
6065f5c8c4d9 goharbor/harbor-registryctl:v2.8.0 "/home/harbor/start.…" 11 seconds ago Up 10 seconds (health: starting) registryctl
32e31ae860d7 goharbor/redis-photon:v2.8.0 "redis-server /etc/r…" 11 seconds ago Up 10 seconds (health: starting) redis
2427a30f17a5 goharbor/harbor-portal:v2.8.0 "nginx -g 'daemon of…" 11 seconds ago Up 10 seconds (health: starting) harbor-portal
399b274af332 goharbor/harbor-db:v2.8.0 "/docker-entrypoint.…" 11 seconds ago Up 10 seconds (health: starting) harbor-db
79e41b7824dd goharbor/registry-photon:v2.8.0 "/home/harbor/entryp…" 11 seconds ago Up 10 seconds (health: starting) registry
ff2c1f8c6e56 goharbor/harbor-log:v2.8.0 "/bin/sh -c /usr/loc…" 11 seconds ago Up 10 seconds (health: starting) 127.0.0.1:1514->10514/tcp harbor-log
```
* 清理備份
```
$ sudo rm -r /harbor-backup/*
```
### 升級 harbor v2.8.0 -> v2.10.1
* 關閉 harbor 服務
```
$ sudo docker compose down
$ cd ~
```
* 備份 harbor
```
$ sudo mv harbor /harbor-backup/harbor
```
* 備份資料庫
```
$ sudo cp -r /data/database /harbor-backup/
```
* 解包新版 harbor,並匯入新版 image
```
$ tar -zxvf harbor-offline-installer-v2.10.1.tgz
$ sudo docker image load -i harbor/harbor.v2.10.1.tar.gz
```
* 升級 `harbor.yml` 文件,注意自己舊版的 `harbor.yml` 路徑,`migrate -i` 指令後面是放舊版 `harbor.yml` 位置,他會覆蓋掉原本的檔案,因此還要把他在做備份
```
$ cp /harbor-backup/harbor/harbor.yml /harbor-backup/harbor/harbor2.yml
$ sudo docker run -it --rm -v /:/hostfs goharbor/prepare:v2.10.1 migrate -i /harbor-backup/harbor/harbor.yml
# 將升級好的 harbor.yml 複製到 harbor/
$ cp /harbor-backup/harbor/harbor.yml harbor/
```
* 把原有憑證複製回來
```
$ cp -r /harbor-backup/harbor/ssl harbor/
```
* 安裝新版 harbor
```
$ cd harbor
$ sudo ./install.sh --with-trivy
```
* 檢查升級狀態
```
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af05d85030db goharbor/nginx-photon:v2.10.1 "nginx -g 'daemon of…" 22 seconds ago Up 20 seconds (health: starting) 0.0.0.0:80->8080/tcp, [::]:80->8080/tcp, 0.0.0.0:443->8443/tcp, [::]:443->8443/tcp nginx
47a31a99de87 goharbor/harbor-jobservice:v2.10.1 "/harbor/entrypoint.…" 22 seconds ago Up 3 seconds (health: starting) harbor-jobservice
072b5df4adb4 goharbor/harbor-core:v2.10.1 "/harbor/entrypoint.…" 22 seconds ago Up 21 seconds (health: starting) harbor-core
dc97efd93e4e goharbor/trivy-adapter-photon:v2.10.1 "/home/scanner/entry…" 22 seconds ago Up 21 seconds (health: starting) trivy-adapter
4f81432d6421 goharbor/redis-photon:v2.10.1 "redis-server /etc/r…" 22 seconds ago Up 21 seconds (health: starting) redis
34c1b778accf goharbor/harbor-db:v2.10.1 "/docker-entrypoint.…" 22 seconds ago Up 21 seconds (health: starting) harbor-db
4e9f94654f7c goharbor/harbor-registryctl:v2.10.1 "/home/harbor/start.…" 22 seconds ago Up 21 seconds (health: starting) registryctl
f868269a3467 goharbor/harbor-portal:v2.10.1 "nginx -g 'daemon of…" 22 seconds ago Up 21 seconds (health: starting) harbor-portal
1ce6bb6887e0 goharbor/registry-photon:v2.10.1 "/home/harbor/entryp…" 22 seconds ago Up 21 seconds (health: starting) registry
84bde22878d4 goharbor/harbor-log:v2.10.1 "/bin/sh -c /usr/loc…" 22 seconds ago Up 22 seconds (health: starting) 127.0.0.1:1514->10514/tcp
```
* 清理備份
```
$ sudo rm -r /harbor-backup
```