Linux 安装 Docker

摘要

Docker 简介

  • Docker 是一个开源的容器化平台,用于打包、分发和运行应用程序。它通过将应用程序及其依赖打包到一个“容器”中,确保应用在不同环境中始终能够一致运行。与传统的虚拟机相比,Docker 容器更轻量、启动更快、资源占用更少。

  • Docker 采用客户端-服务器架构,核心组件包括 Docker Engine(负责构建和运行容器)、Dockerfile(定义构建镜像的指令)、镜像(应用和依赖的只读模板)和容器(基于镜像运行的实例)。开发者可以通过 Docker Hub 共享或下载镜像,极大简化了部署流程。

  • 总结来说,Docker 提高了开发效率,支持持续集成与部署(CI/CD),在微服务架构中尤为常用,是现代 DevOps 流程的重要工具。

  • Docker是什么?

名称 描述
Docker 仓库(Registry) Docker仓库用于存储Docker镜像。Docker Hub是一个任何人都可以使用的公共仓库,默认情况下,Docker在Docker Hub上查找图像。你也可以配置自己的私人仓库。
当您使用docker pull或docker run命令时,Docker会从您配置的仓库中提取所需的镜像。当您使用docker push命令时,Docker会将您的镜像推送到已配置的仓库中。
Docker 守护进程(Daemon) 监听Docker API请求,并管理Docker对象,如镜像、容器、网络和卷。守护程序还可以与其他守护程序通信来管理Docker服务。
Docker 客户端(Client) Docker 客户端(docker)是许多用户与 Docker 交互的主要方式。当你使用如 docker run 这样的命令时,客户端会将这些命令发送给 dockerd(Docker 守护进程),由它来执行这些操作。
docker 命令是通过 Docker API 进行通信的。Docker 客户端可以与多个守护进程进行通信。
Docker 主机(Host) 运行 Docker 守护进程和容器的物理或虚拟机器。
Docker 镜像(Images) 创建容器的只读模板,包含运行应用所需的所有文件和配置。
Docker 容器(Container) 基于镜像运行的实例,是一个或多个应用的独立运行环境。

Docker 安装

  • 全新安装前需要先卸载旧版本,卸载docker也可以按照如下方式操作

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
# 删除Docker相关源
sudo rm -f /etc/yum.repos.d/docker*.repo
# 删除Docker相关软件包,dnf可能会报告您没有安装这些软件包。
# 卸载docker旧版本
sudo dnf -y remove \
docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 卸载docker新版本
sudo dnf -y remove \
docker-ce \
containerd.io \
docker-ce-rootless-extras \
docker-buildx-plugin \
docker-ce-cli \
docker-compose-plugin

# 删除Docker数据,镜像、容器、卷和网络
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
# 删除Docker配置
sudo rm -rf /etc/docker/
  • 设置docker存储库

1
2
3
4
5
sudo dnf -y install dnf-plugins-core
# 海外,添加Docker的官方存储库
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 国内,添加阿里云的存储库
sudo dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  • 安装 Docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 安装最新版本,升级 docker 时也是执行如下命令
sudo dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 安装指定版本
# 先查看所有版本
sudo dnf list docker-ce --showduplicates | sort -r
## 输出
docker-ce.x86_64 3:26.1.3-1.el8 docker-ce-stable
docker-ce.x86_64 3:26.1.3-1.el8 @docker-ce-stable
docker-ce.x86_64 3:26.1.2-1.el8 docker-ce-stable
docker-ce.x86_64 3:26.1.1-1.el8 docker-ce-stable
docker-ce.x86_64 3:26.1.0-1.el8 docker-ce-stable
…………………………

# 安装指定版本,这里 VERSION_STRING 为版本号,例如 3:26.1.3-1.el8
sudo dnf install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io docker-buildx-plugin docker-compose-plugin
## 比如
sudo dnf install docker-ce-3:26.1.3-1.el8 docker-ce-cli-3:26.1.3-1.el8 containerd.io docker-buildx-plugin docker-compose-plugin
  • 启动 Docker

1
2
3
4
# 设置Docker守护进程在系统启动时自动启动
sudo systemctl enable docker
# 启动Docker
sudo systemctl start docker
  • 验证 Docker 安装

1
2
3
4
5
docker -v # Docker version 26.1.3, build b72abbb
# 显示 Docker 基本信息,包括版本信息,插件信息,镜像加速信息等等。
docker info
# 拉取hello-world镜像,此时国内会提示访问失败,需要添加国内镜像源
sudo docker pull hello-world
  • 添加国内镜像源

目前国内大部分的Docker镜像源都关闭了,另外阿里云的Docker镜像源只允许在阿里云的机器上使用。
参考:Docker/DockerHub 国内镜像源/加速列表
注意:国内镜像源的更新会比官网滞后,但只要不是获取最新版本基本上是够用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
]
}
EOF

# 重启Docker
sudo systemctl daemon-reload
sudo systemctl restart docker

# 可以通过如下命令查看是否配置生效,查看 Registry Mirrors 中的配置
docker info
# 验证国内镜像源
sudo docker pull hello-world
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用的bash

# 安装bash-completion
sudo dnf install bash-completion -y

# 添加自动补全到当前登录用户
cat <<EOT >> ~/.bashrc
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
EOT
# 刷新bash
source ~/.bashrc

# 创建自动补全文件
mkdir -p ~/.local/share/bash-completion/completions
docker completion bash > ~/.local/share/bash-completion/completions/docker

# 启动一个新的bash
exec bash
  • /var/lib/docker 用于存储 Docker 运行时生成的数据,如镜像、容器、网络、卷、配置文件、日志等,其目录结构说明如下:

目录名 作用说明
buildkit/ 存放 Docker BuildKit 构建缓存和状态信息;构建镜像时的中间文件和上下文会存于此,空间占用可能较大。
containers/ 每个容器一个子目录,包含配置文件和运行日志(如 container.log),用于容器的运行状态记录和管理。
engine-id 存储 Docker 引擎的唯一 ID,Docker 安装时生成,常用于 swarm 节点识别。
image/ 镜像的元数据(不含实际 layer 数据),组织镜像的结构、标签、驱动等信息。
network/ 网络配置及状态信息,如默认 bridge 网络、自定义网络配置等。
overlay2/ 镜像和容器实际的数据层(overlay2 是存储驱动),包含所有联合文件系统层,是 Docker 中最大的空间使用者。
plugins/ 存放 Docker 插件(如网络、卷插件)的配置和数据,一般为空,除非使用了扩展插件。
runtimes/ 支持的 OCI runtime 配置目录,如默认的 runc,也可能包含其他 runtime(如 kata, gvisor)。
swarm/ Docker swarm 模式下的集群元数据与节点状态,仅在初始化 swarm 后存在实际数据。
tmp/ Docker 的临时文件目录,如镜像下载缓存、挂载操作中的临时文件,通常可以清理但需小心。
volumes/ Docker 卷的数据目录,每个卷一个子目录,卷中的持久化数据实际存放于此。
  • /var/lib/containerd 是 Containerd 守护进程的默认数据存储目录。Containerd 是 Docker 和其他容器平台(如 Kubernetes)底层的 容器运行时(Container Runtime),负责拉取镜像、管理容器生命周期、挂载文件系统等操作。其目录结构说明如下:

目录名 作用说明
io.containerd.content.v1.content/ 存储镜像 layer 的实际二进制内容(blob),遵循 OCI 镜像规范,是镜像和容器文件系统的数据来源。
io.containerd.metadata.v1.bolt/ 使用 BoltDB 存储 containerd 的元数据(如镜像信息、容器状态、快照引用等),是 containerd 的核心元数据数据库。
io.containerd.runtime.v1.linux/ 存储旧版(v1 API)运行时容器信息,目前已逐步被 v2 接口取代,仅在向后兼容场景中存在。
io.containerd.runtime.v2.task/ 存储 v2 运行时接口下容器的运行时状态,如容器进程的 shim、PID、日志路径等,是容器实际运行时所依赖的。
io.containerd.snapshotter.v1.native/ 使用 native 模式存储的容器快照(文件系统层),直接复制底层文件;性能较差,占用空间较大,主要用于测试或特定用途。
io.containerd.snapshotter.v1.overlayfs/ 使用 overlayfs 模式存储容器的文件系统快照(镜像层和容器层);这是生产环境默认的高效存储驱动。
tmpmounts/ 临时挂载点目录,containerd 用于镜像解包、中间构建过程中的挂载操作,通常是构建或运行过程的临时数据。

MacOS/Windows下无法查看/var/lib/docker的解决方法

  • 在 MacOS/Windows 上使用Docker时,是启动了一个虚拟机来运行docker的,由于其运行在虚拟机内部,直接查找/var/lib/docker路径是无效的。
  • 解决方法如下:
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
# 启动一个临时容器,并进入其内部
docker run --rm -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
## 说明
--it
交互式地运行容器,并分配一个伪终端

--rm
退出容器时,自动删除容器

--privileged
给容器特权权限,这意味着容器几乎拥有宿主机的所有能力,能访问 /dev、修改内核参数等。非常强大但也很危险。

--pid=host
容器共享宿主机的进程命名空间(PID Namespace)。
这使得容器可以看到并访问宿主机的所有进程(包括 PID 1,即系统 init 进程)。

debian
使用的基础镜像是 Debian,容器里运行的是这个系统。

nsenter -t 1 -m -u -n -i sh
这是容器内部运行的命令,用来进入宿主机的命名空间:
nsenter:Linux 工具,用于进入其他进程的命名空间。
-t 1:指定目标进程的 PID 是 1(宿主机的 init 或 systemd)。
-m:进入目标进程的 Mount Namespace(文件系统挂载)。
-u:进入目标的 UTS Namespace(主机名等)。
-n:进入目标的 Network Namespace(网络)。
-i:进入目标的 IPC Namespace(进程间通信)。
sh:在这些命名空间中执行一个 shell。
  • 这个命令启动一个基于 Debian 的容器,给它所有特权,让它能看到宿主机的进程,然后使用 nsenter 进入 PID 为 1 的所有命名空间(相当于进入宿主机的视角),最后启动一个 sh,你就在容器里 “变成了宿主机”。
  • 这样,你就可以在这个容器中查看/var/lib/docker目录了。