安装

  1. 卸载旧版本
    Docker的旧版本被称为docker,docker.io或docker-engine。如果安装了这些,请卸载它们:

    1
    for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

    apt-get可能会报告您没有安装这些软件包。当您卸载 Docker 时,存储在其中的图像、容器、卷和
    网络/var/lib/docker/不会自动删除。如果您想从全新安装开始,并且更愿意清理任何现有数据,
    请阅读 卸载 Docker 引擎部分。

  2. 更新apt包索引并安装包以允许apt通过 HTTPS 使用存储库

    1
    2
    sudo apt-get update
    sudo apt-get install ca-certificates curl gnupg
  3. 添加Docker官方的GPG密钥

    1
    2
    3
    4
    5
    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
    # curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
    curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    sudo chmod a+r /etc/apt/keyrings/docker.gpg
  4. 使用以下命令设置稳定存储库。

    1
    echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  5. 更新apt包索引,安装最新版本的Docker Engine和containerd

    1
    2
    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    要安装特定版本的 Docker Engine,列出您的存储库中可用的版本,然后选择一个并安装。

    1
    2
    3
    apt-cache madison docker-ce | awk '{ print $3 }'
    VERSION_STRING=5:24.0.0-1~ubuntu.22.04~jammy
    sudo apt-get install docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io docker-buildx-plugin docker-compose-plugin
  6. 修改/etc/bash.bashrc
    添加alias docker-compose='docker compose'到文件中后执行命令source /etc/bash.bashrc

  7. 通过运行hello-world 映像验证 Docker Engine 是否已正确安装

    1
    sudo docker run hello-world
  8. 测试docker-compose安装是否成功。

    1
    docker-compose --version

以非 root 用户身份管理 Docker

Docker 守护进程绑定到 Unix 套接字,而不是 TCP 端口。默认情况下,它是 root拥有 Unix 套接字的用户,
其他用户只能使用 sudo. Docker 守护进程始终以root用户身份运行。

如果您不想在docker命令前加上sudo,请创建一个名为 docker 的 Unix 组并将用户添加到其中。
当 Docker 守护进程启动时,它会创建一个可供组成员访问的 docker Unix 套接字。
在某些 Linux 发行版上,系统会在使用包管理器安装 Docker Engine 时自动创建此组。在这种情况下,您无需手动创建组。

  1. 创建docker组。

    1
    sudo groupadd docker
  2. 将您的用户添加到docker组中。

    1
    sudo usermod -aG docker $USER
  3. 注销并重新登录,以便重新评估您的组成员身份。
    如果您在虚拟机中运行 Linux,可能需要重新启动虚拟机才能使更改生效。您还可以运行以下命令来激活对组的更改。

    1
    newgrp docker
  4. 验证您是否可以在没有 sudo 下运行 docker.

    1
    docker run hello-world

配置 Docker 守护进程

可以通过修改 /etc/docker/daemon.json 配置 Docker 守护进程。下面的示例同时设置了容器默认 DNS、共享内存、
文件句柄上限、日志轮转和镜像加速地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"dns": [
"223.5.5.5",
"114.114.114.114"
],
"default-shm-size": "1GB",
"default-ulimits": {
"nofile": {
"Hard": 64000,
"Name": "nofile",
"Soft": 64000
}
},
"log-driver": "json-file",
"log-level": "",
"log-opts": {
"cache-disabled": "false",
"cache-max-file": "5",
"cache-max-size": "20m",
"cache-compress": "true",
"env": "os,customer",
"labels": "somelabel",
"max-file": "5",
"max-size": "10m"
},
"registry-mirrors": [
"https://docker.1panel.live/",
"https://docker.1ms.run",
"https://proxy.vvvv.ee",
"https://dockerproxy.link",
"https://docker.m.daocloud.io"
]
}
EOF
sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker

如果文件中已经存在其他配置,应在原 JSON 对象中新增或修改 dns 字段,不要直接覆盖整个文件。JSON 不允许注释,
字段之间也不要遗漏逗号。dockerd --validate 输出 configuration OK 后再重启服务,可避免格式或配置项错误导致
Docker 无法启动。只修改 daemon.json 时不需要执行 systemctl daemon-reload;该命令用于重新加载 systemd
单元文件。

Docker 守护进程配置参考

排查容器内 DNS 解析失败

容器中执行 curlpipapt 等命令时,可能遇到以下错误:

1
2
3
Could not resolve host
NameResolutionError
Temporary failure in name resolution

这些错误表示域名解析失败,但不能仅凭错误信息就断定 Docker 正在使用 Google DNS。应先区分宿主机 DNS、
容器 DNS 和镜像仓库访问问题。

Docker 的 DNS 解析机制

默认情况下,容器会继承宿主机 /etc/resolv.conf 中的 DNS 配置。Ubuntu 常使用 systemd-resolved
此时 /etc/resolv.conf 中可能只有 127.0.0.53。该地址是宿主机网络命名空间中的本地 DNS Stub,
容器有独立的网络命名空间,不能把它当作容器内可用的上游 DNS。

现代 Docker 能识别常见的 systemd-resolved 配置,并尝试从 /run/systemd/resolve/resolv.conf 获取实际
上游 DNS。其他本地回环地址也会被过滤;如果过滤后没有可用的非回环 DNS,Docker 才可能回退到默认外部 DNS,
常见的是 Google DNS 8.8.8.88.8.4.4。Docker 日志中通常会出现:

1
2
No non-localhost DNS nameservers are left in resolv.conf.
Using default external servers

因此,更准确的结论是:Docker 并非始终默认使用 Google DNS,而是在没有获得可供容器访问的上游 DNS 时,
可能回退到 Google DNS。
在中国大陆网络环境中,访问 8.8.8.8:53 可能出现丢包或超时,最终表现为容器
无法解析域名。

自定义 bridge 网络中的容器还可能看到 nameserver 127.0.0.11。这是 Docker 提供的内嵌 DNS,
用于解析 Compose 服务名并将外部域名请求转发给上游 DNS,属于正常现象,不要将它与宿主机的
127.0.0.53 混淆。

整个故障链条可以概括为:

1
2
3
4
5
6
7
8
9
10
11
宿主机仅暴露本地回环 DNS

该地址在容器网络命名空间中不可直接使用

Docker 未获得可用的非回环上游 DNS

Docker 回退到默认外部 DNS

当前网络无法稳定访问该 DNS

容器域名解析超时

先确认问题发生在哪一层

  1. 检查宿主机能否解析域名,并查看实际 DNS 配置。

    1
    2
    3
    getent hosts registry-1.docker.io
    cat /etc/resolv.conf
    resolvectl status
  2. 检查容器实际使用的 DNS。将 <容器名> 替换为正在报错的容器。

    1
    2
    docker exec <容器名> cat /etc/resolv.conf
    docker exec <容器名> getent hosts registry-1.docker.io

    如果镜像中没有 getent,也可以使用一个本地已有的 BusyBox 镜像测试:

    1
    docker run --rm busybox nslookup registry-1.docker.io
  3. 检查 Docker 是否触发了外部 DNS 回退。

    1
    2
    sudo journalctl -u docker --since today \
    | grep -E 'DNS|nameserver|resolv\.conf|default external servers'

如果宿主机可以解析,而容器不能解析,并且容器或 Docker 日志指向不可达的上游 DNS,才应继续调整容器 DNS。
如果 docker pull 在容器创建前就失败,应优先检查宿主机 DNS、代理、防火墙和镜像仓库连通性,不能把它直接
归因于容器的 /etc/resolv.conf

全局解决:为所有容器指定默认 DNS

如果这台主机上的容器都可以使用公共 DNS,可在 /etc/docker/daemon.json 中加入:

1
2
3
{
"dns": ["223.5.5.5", "114.114.114.114"]
}

如果文件中已有其他字段,应合并配置。例如:

1
2
3
4
{
"log-driver": "json-file",
"dns": ["223.5.5.5", "114.114.114.114"]
}

保存后先校验配置,再重启 Docker:

1
2
sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker

然后使用新容器验证:

1
2
docker run --rm busybox cat /etc/resolv.conf
docker run --rm busybox nslookup registry-1.docker.io

Docker 重启会影响正在运行的容器,应安排维护窗口。配置主要用于之后创建的容器;已有 Compose 服务仍然异常时,
可在确认业务允许后重新创建:

1
docker compose up -d --force-recreate

DNS 地址应根据实际网络选择。企业内网、VPN 或私有域名通常依赖内部 DNS,这时应优先配置可供容器访问的内部
DNS,并按需增加一个能解析公网域名的备用服务器。直接替换为公共 DNS 可能导致内部域名无法解析。

临时解决:只修改单个容器或 Compose 服务

不希望影响整台主机时,可以只为单个容器指定 DNS:

1
docker run --dns 223.5.5.5 --dns 114.114.114.114 <镜像名>

Docker Compose 可在对应服务下配置:

1
2
3
4
5
6
services:
app:
image: <镜像名>
dns:
- 223.5.5.5
- 114.114.114.114

这种方式适合临时排障或不同服务需要不同 DNS 的场景;全局配置适合网络环境固定、所有容器 DNS 策略一致的主机。

Docker 官方 DNS 排障说明

用systemd配置Docker在开机时启动

许多现代Linux发行版使用systemd来管理系统启动时的服务。在Debian和Ubuntu上,Docker服务默认在启动时启动。
在其他使用systemd的Linux发行版上,要在开机时自动启动Docker和containerd,请运行以下命令:

1
2
sudo systemctl enable docker.service
sudo systemctl enable containerd.service

要停止这种行为,请使用disable代替。

1
2
sudo systemctl disable docker.service
sudo systemctl disable containerd.service

卸载

  1. 卸载 Docker Engine、CLI 和 Containerd 包。

    1
    sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
  2. 主机上的映像、容器、卷或自定义配置文件不会自动删除。删除所有镜像、容器和卷。

    1
    2
    sudo rm -rf /var/lib/docker
    sudo rm -rf /var/lib/containerd