跳转至

01 Docker 安装:入门案例带你了解容器技术原理

第一课时我们先来了解 Docker 的基础内容:Docker 能做什么、怎么安装 Docker,以及容器技术的原理。

Docker 能做什么?

众所周知,Docker 是一个用于开发、发布和运行应用程序的开放平台。通俗地讲,Docker 类似于集装箱。在一艘大船上,各种货物要想被整齐摆放并且相互不受到影响,我们需要把各种货物进行标准化包装。有了集装箱,我们就不需要专门运输水果或化学用品的船了。我们可以把各种货品通过集装箱打包,然后统一放到一艘船上运输。Docker 要做的就是把各种软件打包成一个集装箱(镜像),然后分发,且在运行的时候可以相互隔离。

下面就让我们来安装 Docker。

CentOS 下安装 Docker

Docker 是跨平台的解决方案,它支持在当前主流的各大平台安装,包括 Ubuntu、RHEL、CentOS、Debian 等 Linux 发行版,同时也可以在 macOS、Windows 等非 Linux 平台下安装使用。

因为 Linux 是 Docker 的原生支持平台,所以推荐在 Linux 上使用 Docker。由于生产环境中我们使用 CentOS 较多,下面主要针对在 CentOS 平台下安装和使用 Docker 展开介绍。

1. 操作系统要求

要安装 Docker,我们需要 CentOS 7 及以上的发行版本,建议使用 overlay2 存储驱动程序。

2. 卸载已有 Docker

如果你已经安装过旧版的 Docker,可以先执行以下命令卸载旧版 Docker:

sudo yum remove docker                   docker-client                   docker-client-latest                   docker-common                   docker-latest                   docker-latest-logrotate                   docker-logrotate                   docker-engine

3. 安装 Docker

首次安装 Docker 之前,需要添加 Docker 安装源。添加之后,就可以从配置好的源中安装和更新 Docker:

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

正常情况下,直接安装最新版本的 Docker 即可:

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

如果想要安装指定版本的 Docker,可以使用以下命令列出可用版本:

sudo yum list docker-ce --showduplicates | sort -r

输出示例:

docker-ce.x86_64            18.06.1.ce-3.el7                   docker-ce-stable
docker-ce.x86_64            18.06.0.ce-3.el7                   docker-ce-stable
docker-ce.x86_64            18.03.1.ce-1.el7.centos            docker-ce-stable
docker-ce.x86_64            18.03.0.ce-1.el7.centos            docker-ce-stable
docker-ce.x86_64            17.12.1.ce-1.el7.centos            docker-ce-stable
docker-ce.x86_64            17.12.0.ce-1.el7.centos            docker-ce-stable
docker-ce.x86_64            17.09.1.ce-1.el7.centos            docker-ce-stable

然后选取想要的版本执行安装:

sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

安装完成后,启动 Docker 服务:

sudo systemctl start docker

安装完成后,按照惯例启动一个 hello-world 容器进行测试:

sudo docker run hello-world

运行输出:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:7f0a9f93b4aa3022c3a4c147a449bf11e0941a1fd0bf4a8e6c9408b2600777c5
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

运行上述命令,Docker 首先会检查本地是否有 hello-world 镜像,发现本地没有时就会自动从 Docker Hub 官方镜像仓库下载,然后运行它。最后输出 "Hello from Docker!" 并退出。

提示:安装完成后默认 docker 命令只能以 root 用户执行。如果想允许普通用户执行 docker 命令,可以将其加入 docker 用户组:

sudo groupadd docker && sudo gpasswd -a ${USER} docker && sudo systemctl restart docker

执行完毕后重新打开新的终端窗口即可生效。

容器技术原理

提起容器就不得不说 chroot,因为 chroot 是最早的容器雏形。chroot 意为切换根目录(Change Root),有了 chroot 就意味着我们可以把任何目录更改为当前进程的根目录。

1. chroot 体验

维基百科中对 chroot 的定义如下:

chroot 是 Unix 和 Linux 系统下的一个操作,针对正在运行的进程及其子进程改变其外显的根目录。一个在经由 chroot 设置根目录环境下运行的程序,不能够对指定根目录之外的文件进行访问或修改。

通俗地说,chroot 就是改变某进程的根目录,使其无法访问目录之外的其他文件。下面通过一个实例演示:

首先创建一个 rootfs 目录:

mkdir rootfs

这里使用现成的 busybox 容器提取文件系统:

cd rootfs
docker export $(docker create busybox) -o busybox.tar
tar -xf busybox.tar

解压完成后在 rootfs 目录下查看目录结构:

ls -l

输出示例:

bin  busybox.tar  dev  etc  home  proc  root  sys  tmp  usr  var

可以看到在 rootfs 目录下初始化了一套完整的 Linux 根目录结构。接着使用 chroot 命令启动一个 /bin/sh 进程,并将 /home/centos/rootfs 作为该进程的根目录:

chroot /home/centos/rootfs /bin/sh

在弹出的 sh 窗口中查看当前根目录:

/ # /bin/ls /

输出:

bin  busybox.tar  dev  etc  home  proc  root  sys  tmp  usr  var

可以看到当前进程的根目录已经变成了主机上的 /home/centos/rootfs 目录,实现了目录级别的隔离。

但在 sh 窗口中查看路由信息:

/etc # /bin/ip route

输出:

default via 172.20.1.1 dev eth0
172.17.0.0/16 dev docker0 scope link  src 172.17.0.1
172.20.1.0/24 dev eth0 scope link  src 172.20.1.3

可以看到网络信息与宿主机依然共享,进程与资源也并未隔离。要想实现一个完整的容器,还需要 Linux 的另外三项核心技术:NamespaceCgroups联合文件系统(UnionFS)

2. 容器三大核心支撑技术对比

核心支撑技术 核心作用与定义 解决的根本问题 具体隔离与限定机制
Namespace (命名空间) 内核级资源隔离,为每个容器提供独立的运行空间视图 运行视图隔离:防止容器间及容器与宿主机相互影响 隔离 PID(进程)、NET(网络端口/IP)、MNT(挂载点)、IPC(进程间通信)、UTS(主机名)
Cgroups (控制组) 限制和监控进程组对宿主机硬件资源的使用 资源配额控制:防止单个容器暴涨挤垮宿主机 限制 CPU 时间片分配、Memory 内存上限、Disk I/O 读写带宽
UnionFS (联合文件系统) 分层挂载与 Copy-on-Write (写时复制) 的轻量级文件系统 存储与构建高效:实现镜像极速下载与按层共享 Overlay2、AUFS、Devicemapper

Namespace

Namespace 是 Linux 内核提供的功能,对内核资源进行隔离,使得容器中的进程都在独立的命名空间中运行:

  • PID Namespace:隔离进程 ID;
  • NET Namespace:隔离网络接口(独立的 IP、路由、端口等);
  • MNT Namespace:隔离文件系统挂载点;
  • IPC Namespace:隔离信号量、消息队列和共享内存;
  • UTS Namespace:隔离主机名和域名。

Cgroups

Cgroups(Control Groups)用于限制和隔离进程的资源使用情况(CPU、内存、磁盘 I/O、网络带宽等),防止某个容器消耗过多宿主机资源。

联合文件系统(UnionFS)

联合文件系统通过创建文件层进行操作,极其轻快。Docker 使用联合文件系统为容器提供构建层,实现写时复制(Copy-on-Write)以及镜像的分层构建与存储。常用的联合文件系统有 Overlay2、AUFS、Devicemapper 等。

结语

容器技术从 1979 年 chroot 的问世便已崭露头角,到了 2013 年 Docker 的横空出世才使得容器技术迅速爆发。

Docker 提供了完整的工具和平台来管理容器的生命周期:

  1. 使用容器开发应用程序及其支持组件;
  2. 容器成为分发和测试应用程序的标准单元;
  3. 可以将应用程序作为容器部署到任何生产环境中(本地数据中心、公有云等)。

思考:为什么容器技术在 Docker 出现之前一直没有爆发?欢迎在留言区讨论。

下一课时我们将讲解 Docker 的架构设计以及三大核心概念。