简介

​ docker是一个用Go语言实现的开源项目,可以让我们方便的创建和使用容器,docker将程序以及程序所有的依赖都打包到docker container,这样你的程序可以在任何环境都会有一致的表现,这里程序运行的依赖也就是容器就好比集装箱,容器所处的操作系统环境就好比货船或港口,程序的表现只和集装箱有关系(容器),和集装箱放在哪个货船或者哪个港口(操作系统)没有关系

​ 因此我们可以看到docker可以屏蔽环境差异,也就是说,只要你的程序打包到了docker中,那么无论运行在什么环境下程序的行为都是一致的,程序员再也无法施展表演才华了,不会再有“在我的环境上可以运行”,真正实现“build once, run everywhere”。

概念

​ docker 中的几个概念:

  1. dockerfile
  2. image
  3. container

dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。感觉就像makefile一样。

image

​ Docker镜像(Docker Image)就是一个只读的模板。比如,一个镜像可以包含一个完整的Ubuntu操作系统环境。镜像可以用来创建Docker容器。

container

​ 容器是镜像的运行时实例,容器是独立运行的一个或一组应用,以及它们的运行态环境。

安装方式:

包管理器安装

添加官方仓库源

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

更新源

1
2
sudo dnf clean all
sudo dnf makecache

安装docker及其组件

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

二进制包安装(tgz)

解压二进制包

1
tar -zxvf docker-28.3.0.tgz 

转移到用户库

1
sudo cp docker/* /usr/bin/

配置 systemd 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo tee /etc/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Service
After=network.target

[Service]
ExecStart=/usr/bin/dockerd
Restart=always
LimitNOFILE=1048576
LimitNPROC=1048576

[Install]
WantedBy=multi-user.target
EOF

启动

1
2
3
sudo systemctl daemon-reload
sudo systemctl start docker
sudo systemctl enable docker

改变 Docker 默认存储位置

  1. 停止 Docker 服务:
1
sudo systemctl stop docker
  1. 创建新目录:
1
sudo mkdir -p /data/docker
  1. 修改 Docker 配置文件(/etc/docker/daemon.json):
1
2
3
{
"data-root": "/data/docker"
}
  1. 把旧数据迁移(可选,如果想保留):
1
sudo rsync -aP /var/lib/docker/ /data/docker
  1. 启动 Docker:
1
sudo systemctl start docker
  1. 验证:
1
docker info | grep "Docker Root Dir"

应该显示:

1
Docker Root Dir: /data/docker

技术分析

Docker 容器的实现基于 Linux 内核的核心技术,通过资源隔离和虚拟化技术模拟独立的运行环境。以下是其核心实现原理:

1. 核心技术(Linux 内核支持)

Docker 容器本质上是 隔离的进程,依赖以下 Linux 特性实现:

  • Namespaces(命名空间)

    • PID Namespace:隔离进程树,容器内只能看到自己的进程(如 ps aux)。
    • Network Namespace:独立网络栈(IP、端口、路由表等)。
    • Mount Namespace:隔离文件系统挂载点(容器内目录独立)。
    • UTS Namespace:隔离主机名和域名。
    • IPC Namespace:隔离进程间通信(如信号量、消息队列)。
    • User Namespace:隔离用户和用户组(可映射宿主机UID/GID)。
  • Cgroups(控制组)

    • 限制资源使用(CPU、内存、磁盘I/O等),避免单个容器耗尽宿主机资源。
  • Union File System(联合文件系统)

    • OverlayFSAUFS,实现镜像分层存储和容器读写层的高效复用。

2. 容器运行流程

  1. 镜像加载
    • 基于镜像(只读层)创建容器时,添加一个可写层(Copy-on-Write)。
  2. 资源隔离
    • 通过 Namespaces 创建隔离的进程、网络、文件系统等环境。
  3. 资源限制
    • 通过 Cgroups 分配 CPU、内存等配额。
  4. 网络配置
    • 默认使用 bridge 模式,创建 veth pair 虚拟网卡对连接容器与宿主机。

3. 与虚拟机的区别

特性 Docker 容器 虚拟机
隔离级别 进程级(共享宿主机内核) 硬件级(完整操作系统)
启动速度 秒级(直接调用宿主机内核) 分钟级(需启动Guest OS)
性能损耗 <5%(接近原生进程) 15%~30%(虚拟化开销)
镜像大小 MB 级(仅应用层) GB 级(含完整OS)

4. 关键组件

  • containerd:负责容器生命周期管理(创建/启动/停止)。
  • runc:底层运行时工具,根据 OCI 标准调用内核功能创建容器。
  • Docker Engine:封装上层 API 和工具链(如 docker build/docker run)。

5. 简单示例:容器如何启动?

1
2
3
4
5
# 当执行 `docker run -it ubuntu bash` 时:
1. 检查本地是否存在 `ubuntu` 镜像,若无则从仓库拉取。
2. 创建可写层(容器层)叠加到镜像的只读层上。
3. 调用 `runc` 创建 Namespaces 和 Cgroups。
4. 在隔离环境中启动 `/bin/bash` 进程。

总结

Docker 容器本质是 通过 Linux 内核的 Namespaces 和 Cgroups 实现的隔离进程,配合联合文件系统提供轻量级、高性能的虚拟化环境。其效率远高于传统虚拟机,但隔离性较弱(共享内核)。