CentOS 7 上从 Docker 1.13 升级到 Docker CE

前言

CentOS 7 上自带的 docker 常见为 extras 源中的 1.13.x,与 Docker 官方仓库里的 docker-ce 不是同一套包。
不能单靠 yum update 把 1.13 升为当前 CE,需要先 卸下发行版自带的 docker 系列包,再 配置官方源并安装 docker-ce
镜像与容器数据默认在 /var/lib/docker,变更前请在业务允许的时间窗口执行,并做好卷与挂载路径的备份或核对。

为什么要升级Docker

Docker 1.13 发布于 2017 年,它主要使用较旧的 Registry V1 或早期的 V2 协议,现在的镜像源为了安全和效率,大多已经全面采用 Registry V2 API 和新的 Manifest 格式,这样就导致设置镜像源后镜像源能获取到但是不起作用。

事前确认

确认系统为 CentOS 7,并记下当前 Docker 版本与已装 RPM。

1
2
3
cat /etc/centos-release
rpm -qa | grep -E '^docker'
docker version

docker version1.13.x,且 rpm -qa 中仅有 docker 而无 docker-ce,可按下文迁移。

若仍在运行生产容器,建议在低峰窗口操作。
升级过程会重启 docker当时在跑的容器会停,见下文。

实现

影响简要

安装或重装引擎时通常会 重启 docker 服务运行中的容器会中断

镜像、命名卷、/var/lib/docker 下的数据一般不因本次升级而清空。

配置了 --restart(如 unless-stopped)的容器在守护进程起来后常会 自动再起

无策略的容器需稍后 docker start 或 Compose 再起。

添加官方仓库

CentOS 7 使用 yum
若尚未添加 Docker CE 源,优先使用官方地址:

1
2
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

改用国内 docker-ce 镜像的 repo 文件(与官方结构相同,仅 baseurl 指向镜像站)

例如 阿里云清华(以你环境能打开为准,任选其一):

1
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

或:

1
sudo yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo

清理缓存

1
2
sudo yum clean all
sudo yum makecache

卸掉 1.13

必须先卸掉与 docker-ce 冲突的旧包,否则会装不上或与旧二进制混用。
下列列表来自常见文档,可按本机 rpm -qa | grep docker 增删包名。

1
2
3
4
5
6
7
8
sudo systemctl stop docker
sudo yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-logrotate \
docker-engine

安装新版本

1
sudo yum install -y docker-ce docker-ce-cli containerd.io

可选:顺带安装 Compose 与 buildx 插件(按需)。

1
sudo yum install -y docker-compose-plugin docker-buildx-plugin

安装结束若未自动拉起服务,可参考下一节 systemctl

启服与开机自启

执行下列命令启用并启动 docker,并查看状态:

1
2
3
sudo systemctl daemon-reload
sudo systemctl enable docker --now
sudo systemctl status docker

若曾改过 /etc/docker/daemon.json,升级后核对文件是否仍在、内容是否合理。

存储路径

注意

卸载旧版本的时候 /etc/docker/daemon.json 会被删除导致,安装的新版本数据位置不对。

停止Docker

1
2
3
# 停止服务和 socket
sudo systemctl stop docker.socket
sudo systemctl stop docker.service

编辑 /etc/docker/daemon.json

1
vi /etc/docker/daemon.json

添加以下内容

1
2
3
4
5
6
7
8
9
10
11
{
"data-root": "/data/tools/docker",
"registry-mirrors": [
"https://docker.xuanyuan.me",
"https://docker.1ms.run/",
"https://docker.m.daocloud.io",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com"
],
"dns": ["223.5.5.5", "114.114.114.114"]
}

重启Docker

1
2
systemctl daemon-reload
systemctl restart docker.service

查看安装版本

1
2
3
docker -v
docker compose version
docker buildx version

验证

确认版本、资源与基本拉取运行是否正常,可顺序执行:

1
2
3
4
5
docker version
docker info
docker ps -a
docker pull hello-world
docker run --rm hello-world

旧镜像无法启动

报错

Error response from daemon: unknown or invalid runtime name: docker-runc

在旧版本的 Docker 中,默认的容器运行时名称是 docker-runc。而在新版本中,这个名称被简化为了 runc

当你升级 Docker 后,守护进程已经无法识别旧的 docker-runc 运行时。但是,之前创建的容器配置文件(位于 /var/lib/docker/containers/ 目录下)中仍然记录着旧的运行时名称 docker-runc。因此,当你尝试启动这些旧容器时,Docker 就会报错,因为它找不到名为 docker-runc 的运行时。

解决方案

批量替换运行时名称

1
sudo grep -rl 'docker-runc' /data/tools/docker/containers/ | xargs sudo sed -i 's/docker-runc/runc/g'

命令解释

  • grep -rl 'docker-runc' ...: 递归搜索包含 docker-runc 的文件,并列出文件路径。
  • xargs sudo sed -i 's/docker-runc/runc/g': 将上一步找到的所有文件作为输入,执行 sed 命令进行原地替换。

重启

1
sudo systemctl restart docker