每天5分钟玩转Docker容器技术 笔记

400 阅读25分钟

image.png

作者博客:blog.51cto.com/cloudman/19…

第1章 鸟瞰容器生态系统

容器核心技术

包括容器规范、容器runtime、容器管理工具、容器定义工具、Registry以及容器OS

  1. 容器规范:OpenContainer Initiative(OCI)是制定开放的容器规范的组织。目前OCI发布了两个规范:runtime spec和image format spec,保证了容器的可移植性和互操作性。
  2. 容器runtime:runtime是容器真正运行的地方,需要跟操作系统kernel紧密协作,为容器提供运行环境。目前主流的三种容器runtime:lxc、runc和rkt。lxc是Linux上老牌的容器runtime;runc是Docker自己开发的容器runtime;rkt是CoreOS开发的容器runtime。
  3. 容器管理工具:对内与runtime交互,对外为用户提供interface。lxc的管理工具是lxd;runc的管理工具是docker engine;kt的管理工具是rkt cli。我们通常提到Docker,一般就是指的docker engine。
  4. 容器定义工具:docker image,dockerfile,ACI(App Container Image)。允许用户定义容器的内容和属性,使容器能够被保存、共享和重建。
  5. Registry:存放image的仓库,比如Docker Hub。
  6. 容器OS:专门运行容器的操作系统。比如CoreOS、Atomic和Ubuntu Core。

容器平台技术

容器平台技术包括容器编排引擎、容器管理平台和基于容器的PaaS。容器核心技术使得容器能够在单个host上运行,而容器平台技术能够让容器作为集群在分布式环境中运行。

容器支持技术

  1. 容器网络:管理容器与容器、容器与其他实体之间的连通性和隔离性。docker network是Docker原生的网络解决方案。
  2. 服务发现:容器会根据host的资源使用情况在不同host中迁移,容器的IP和端口也会随之发生变化。当负载增加时,集群会自动创建新的容器;负载减小,多余的容器会被销毁。
  3. 监控:Docker命令行监控工具docker ps/top/stats
  4. 数据管理:在不同的host上,保证持久化数据和动态迁移。
  5. 日志管理:Docker日志工具docker logs
  6. 安全性:容器安全工具OpenSCAP,能够对容器镜像进行扫描,发现潜在的漏洞。

安装Docker:阿里云部署并使用Docker

安装Docker的依赖库
yum install -y yum-utils device-mapper-persistent-data lvm2
添加Docker CE的软件源信息。
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装Docker CE。
yum -y install docker-ce
启动Docker服务。
systemctl start docker

配置镜像加速器
sudo mkdir -p /etc/docker 
sudo tee /etc/docker/daemon.json <<-'EOF' 
{ 
    "registry-mirrors": ["https://rr1l27vx.mirror.aliyuncs.com"] 
    } 
EOF 
重新加载服务配置文件。
sudo systemctl daemon-reload 
重启Docker服务。
sudo systemctl restart docker

运行容器:docker run

  • -d:  后台运行容器,并返回容器ID;
  • -p:  指定端口映射,格式为:主机(宿主)端口:容器端口
  • -i:  以交互模式运行容器,通常与 -t 同时使用;
  • --name="nginx-lb":  为容器指定一个名称;
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run -d -p 80:80 httpd    //Docker客户端执行docker run命令
Unable to find image 'httpd:latest' locally    //Docker daemon发现本地没有httpd镜像
latest: Pulling from library/httpd 
7d63c13d9b9b: Already exists    //daemon从Docker Hub下载镜像
ca52f3eeea66: Already exists 
448256567156: Already exists 
21d69ac90caf: Already exists 
462e88bc3074: Already exists 
Digest: sha256:f70876d78442771406d7245b8d3425e8b0a86891c79811af94fb2e12af0fadeb
Status: Downloaded newer image for httpd:latest  //下载完成,镜像httpd被保存到本地
e321c2c27cd7108e3eedf1a16307e38178323fa7d648209bf211f2166c0e46c5  //Docker daemon启动容器

其过程可以简单地描述为:

1. 从Docker Hub下载httpd镜像。镜像中已经安装好了Apache HTTP Server。
2. 启动httpd容器,并将容器的80端口映射到host的80端口。

第2章 容器核心知识概述

Docker的核心组件包括:

  • Docker客户端:Client,最常用的Docker客户端是docker命令。
  • Docker服务器:Docker daemon,以Linux后台服务的方式运行,负责创建、运行、监控容器,构建、存储镜像。
  • Docker镜像:Image,只读模板,通过它可以创建Docker容器。
  • Registry:Registry是存放Docker镜像的仓库,Registry分私有和公有两种。
  • Docker容器:Container,是Docker镜像的运行实例。

对于应用软件,镜像是软件生命周期的构建和打包阶段,而容器则是启动和运行阶段。

架构如图: image.png Docker采用的是Client/Server架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。

docker info    用于查看服务器的信息
docker build <docker-file>  构建出Docker镜像
docker pull  从Registry下载镜像
docker run ...  先下载镜像(如果本地没有),然后再启动容器
docker images 查看镜像
docker ps或者docker container ls显示容器正在运行
docker history ... 显示镜像的构建历史,也就是Dockerfile的执行过程。

第3章 Docker镜像

镜像的内部结构:

base镜像:

  1. 不依赖其他镜像,从scratch构建;scratch是一个空的镜像,可以用于构建busybox(一种嵌入式Linux)等超小镜像。
  2. 其他镜像可以以之为基础进行扩展。 linux操作系统由内核空间和用户空间组成。 内核空间是kernel, Linux刚启动时会加载bootfs文件系统,之后bootfs会被卸载掉。 用户空间的文件系统是rootfs,包含我们熟悉的 /dev、/proc、/bin等目录。 对于base镜像来说,底层直接用Host的kernel,自己只需要提供rootfs就行了。 image.png 镜像的分层结构:Docker通过从base镜像一层一层叠加扩展现有镜像,生成的新的镜像。每安装一个软件,就在现有镜像的基础上增加一层。分层结构最大的一个好处就是:共享资源。

当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。只有容器层是可写的,记录对镜像的修改,容器层下面的所有镜像层都是只读的,所以镜像可以被多个容器共享。

添加文件:在容器中创建文件时,新文件被添加到容器层中。
读取文件:在容器中读取某个文件时,Docker会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
修改文件:在容器中修改已存在的文件时,Docker会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。这种特性被称作Copy-on-Write。
删除文件:在容器中删除文件时,Docker也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作

构建镜像的方法: docker commit命令与Dockerfile构建文件。 docker commit包含三个步骤:

  • 运行容器。
  • 修改容器。
  • 将容器保存为新的镜像。
运行容器 ubuntu
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete 
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest

执行vim,命令找不到
root@11846efaf6b0:/# vim
bash: vim: command not found

安装vim,失败
root@11846efaf6b0:/# apt-get install -y vim
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package vim

查看版本
root@20856f23257f:/etc/apt# cat /etc/issue 
Ubuntu 20.04.3 LTS \n \l

新建配置文件
root@20856f23257f:/etc/apt# touch  /etc/apt/sources.list
修改源
echo deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse >> /etc/apt/sources.list
echo deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse >> /etc/apt/sources.list
echo deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse >> /etc/apt/sources.list
echo deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse >> /etc/apt/sources.list
echo deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse >> /etc/apt/sources.list
echo deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse >> /etc/apt/sources.list
echo deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse >> /etc/apt/sources.list
echo deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse >> /etc/apt/sources.list
echo deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse >> /etc/apt/sources.list
echo deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse >> /etc/apt/sources.list

激活和更新源
apt-get update 

安装vim
apt-get install -y vim

查看vim版本
root@20856f23257f:/etc/apt# vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Sep 20 2021 11:42:42)

不要退出容器

新开一个窗口,查看镜像名称,great_beaver是Docker为容器随机分配的名字
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker ps -a
CONTAINER ID   IMAGE                                    COMMAND              CREATED          STATUS                      PORTS                                     NAMES
84803a53edd9   ubuntu                                   "bash"               34 seconds ago   Exited (0) 33 seconds ago                                             great_beaver

执行docker commit命令将容器保存为镜像,新镜像命名为ubuntu-with-vi
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker commit great_beaver ubuntu-with-vi
sha256:41eb93c761bf6b3bbf0a78d8372b04bd1fb07e142d23437d777159cec6ff8df1

查看本地镜像
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED         SIZE
ubuntu-with-vi                      latest    a6f66dc34962   6 seconds ago   230MB
ubuntu                              latest    ba6acccedd29   3 weeks ago     72.8MB

从size上看到镜像因为安装了软件而变大了,从新镜像启动容器vim已经可以使用
root@97f3cc723809:/# which vi
/usr/bin/vi

用Dockerfile创建上节的ubuntu-with-vi-dockerfile

当前文件夹为root
[root@iZwz9f1ba8y91wed647jhlZ ~]# pwd
/root

[root@iZwz9f1ba8y91wed647jhlZ ~]# vim Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y vim
:wq保存退出

运行docker build命令,-t将新镜像命名为ubuntu-with-vi-dockerfile
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker build -t ubuntu-with-vim-dockerfile .
Sending build context to Docker daemon  13.82MB
Step 1/2 : FROM ubuntu                                    --执行FROM,将Ubuntu作为base镜像。Ubuntu镜像ID为f753707788c5。
 ---> ba6acccedd29
Step 2/2 : RUN apt-get update && apt-get install -y vim   --执行RUN,安装vim,具体步骤为 
 ---> Running in 28b2570fc24f

... ...

Setting up vim (2:8.1.2269-1ubuntu5.3) ...                --启动临时容器,在容器中通过apt-get安装vim

... ...

Removing intermediate container 28b2570fc24f               --删除临时容器9f4d4166f7e3
 ---> 203e55414406
Successfully built 203e55414406                            -- 安装成功后,将容器保存为镜像,其ID为203e55414406
Successfully tagged ubuntu-with-vim-dockerfile:latest

查看镜像,ubuntu-with-vim-dockerfile 
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED          SIZE
ubuntu-with-vim-dockerfile          latest    203e55414406   3 minutes ago    172MB

Docker会在启动的临时容器中执行操作,并通过commit保存为新的镜像。

Dockerfile中最常用的指令:

FROM:指定base镜像
MAINTAINER:设置镜像的作者,可以是任意字符串。
COPY:将文件从build context复制到镜像
ADD:与COPY类似,从build context复制文件到镜像
ENV:设置环境变量
EXPOSE:指定容器中的进程会监听某个端口
VOLUME:将文件或目录声明为volume
WORKDIR:设置镜像中的当前工作目录
RUN:执行命令并创建新的镜像层,RUN经常用于安装软件包。
CMD:设置容器启动后默认执行的命令及其参数,多个CMD指令,但只有最后一个生效。CMD可以被docker run之后的参数替换。
ENTRYPOINT:配置容器启动时运行的命令,有多个ENTRYPOINT指令,但只有最后一个生效。CMD或docker run之后的参数会被当作参数传递给ENTRYPOINT。

Dockerfile支持以“#”开头的注释。

分发镜像

将镜像上传到公共Registry,Docker Hub。 一个特定镜像的名字由两部分组成:repository和tag,如果执行docker build时没有指定tag,会使用默认值latest。通过docker tag命令方便地给镜像打tag。

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED        SIZE
httpd                               latest    1132a4fc88fa   2 weeks ago    143MB

保存和分发镜像的最直接方法就是使用Docker Hub。 注册账户,docker login登录 镜像命名格式为:[username]/xxx:tag docker push将镜像上传到Docker Hub

docker commit ... 从容器创建新镜像
docker build ... 从Dockerfile构建镜像
docker tag ... 给镜像打tag
docker login -u ... -p ... 登录Docker Hub账户
docker push ... 上传镜像到Docker Hub
docker pull ... 从Docker Hub拉取镜像
docker rmi ... 删除Docker host中的镜像,不会删除registry的镜像。如果一个镜像对应了多个tag,只有当最后一个tag被删除时,镜像才被真正删除。
docker search ... 搜索Docker Hub中的镜像

第4章 Docker容器

后台运行容器:docker run -d 有两种方法进入容器:attach和exec,主要区别如下:

1)attach直接进入容器启动命令的终端,不会启动新的进程。
(2)exec则是在容器中打开新的终端,并且可以启动新的进程。
(3)如果想直接在终端中查看启动命令的输出,用attach;其他情况使用exec。

容器各种状态之间的转换 image.png

docker logs 查看启动命令的输出
docker stop 可以停止运行的容器,通过docker start重新启动,会保留容器的第一次启动时的所有参数
docker restart 可以重启容器,其作用就是依次执行docker stop和docker start。只有当容器的启动进程退出时,--restart才生效
docker pause 让容器暂停工作一段时间,通过docker unpause恢复运行
docker rm 一次可以指定多个容器
docker rmi 删除镜像
docker create 创建的容器处于Created状态
docker run 实际上是docker create和docker start的组合。

资源限制

与操作系统类似,容器可使用的内存包括两部分:物理内存和swap。

内存限额

Docker通过下面两组参数来控制容器内存的使用量。如果在启动容器时只指定-m,而不指定--memory-swap,那么--memory-swap默认为 -m的两倍。

-m或--memory:设置内存的使用限额,例如100MB,2GB。
--memory-swap:设置内存+swap的使用限额。
-vm 1:启动1个内存工作线程。
--vm-bytes 280M:每个线程分配280MB内存。

下面使用progrium/stress镜像来学习如何为容器分配内存。该镜像可用于对容器执行压力测试。执行如下命令:

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run -it -m 300M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
stress: dbug: [7] allocating 293601280 bytes ...

... ...

因为280MB在可分配的范围(300MB)内,所以工作线程能够正常工作,
其过程是:
(1)分配280MB内存。
(2)释放280MB内存。
(3)再分配280MB内存。
(4)再释放280MB内存。
(5)一直循环……

如果让工作线程分配的内存超过300MB
[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run -it -m 300M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [6] forked
stress: dbug: [6] allocating 325058560 bytes ...
stress: dbug: [6] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 6 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 0s

分配的内存超过限额,stress线程报错,容器退出。

CPU限额

默认设置下,所有容器可以平等地使用host CPU资源并且没有限制。 Docker可以通过 -c或 --cpu-shares设置容器使用CPU的权重。如果不指定,默认值为1024。 最终能分配到的CPU资源取决于它的cpu share占所有容器cpu share总和的比例。按权重分配CPU只会发生在CPU资源紧张的情况下。如果A处于空闲状态,这时,为了充分利用CPU资源,B也可以分配到全部可用的CPU。

-c或--cpu  设置工作线程的数量。
--cpu-shares  设置容器使用CPU的权重

下面继续用progrium/stress做实验

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run --name container_A -it -c 1024 progrium/stress --cpu 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [7] forked

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run --name container_B -it -c 512 progrium/stress --cpu 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [7] forked

执行top,查看容器对CPU的使用情况,containerA消耗的CPU是containerB的两倍。 image.png

暂停container_A

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker pause container_A
container_A

top显示containerB在containerA空闲的情况下能够用满整颗CPU

docker top 查看容器对CPU的使用情况
ps axf 查看容器进程
docker pause ...  暂停容器

Block IO带宽限额

Block IO即磁盘的读写,docker可通过设置权重、限制bps和iops的方式控制容器读写磁盘的带宽。默认情况下,所有容器能平等地读写磁盘,可以通过设置 --blkio-weight参数来改变容器block IO的优先级。--blkio-weight与 --cpu-shares类似,设置的是相对权重值,默认为500。

bps是byte per second,每秒读写的数据量
iops是io per second,每秒IO的次数

--blkio-weight参数来改变容器block IO的优先级
--device-read-bps:限制读某个设备的bps
--device-write-bps:限制写某个设备的bps
--device-read-iops:限制读某个设备的iops
--device-write-iops:限制写某个设备的iops

实现容器的底层技术

cgroup实现资源限额(Control Group),namespace实现资源隔离
cgroup:--cpu-shares、-m、--device-write-bps实际上就是在配置cgroup。在 /sys/fs/cgroup/cpu/docker目录中,Linux会为每个容器创建一个cgroup目录,以容器长ID命名。目录中包含所有与cpu相关的cgroup配置。/sys/fs/cgroup/memory/docker和 /sys/fs/cgroup/blkio/docker中保存的是内存以及Block IO的cgroup配置
namespace:namespace管理着host中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。namespace实现了容器间资源的隔离。Linux使用了6种namespace,分别对应6种资源:Mount、UTS、IPC、PID、Network和User Mount namespace让容器看上去拥有整个文件系统 UTS namespace让容器有自己的hostname IPC namespace让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与host和其他容器的IPC混在一起。 PID namespace容器拥有自己独立的一套PID Network namespace让容器拥有自己独立的网卡、IP、路由等资源 User namespace让容器能够管理自己的用户,host不能看到容器中创建的用户

ps axf 查看容器进程

第5章 Docker网络

Docker安装时会自动在host上创建三个网络,我们可用docker network ls命令查看

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
60f16f858b56   bridge            bridge    local
8bc829e974c5   host              host      local
4f4a4bb4d47e   none              null      local
  1. none网络,就是什么都没有的网络。挂在这个网络下的容器除了lo,没有其他任何网卡。容器创建时,可以通过 --network=none指定使用none网络。对安全性要求高并且不需要联网的应用可以使用none网络。
  2. host网络,连接到host网络的容器共享Docker host的网络栈,容器的网络配置与host完全一样。可以通过 --network=host指定使用host网络。最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。
  3. bridge网络,Docker安装时会创建一个命名为docker0的Linux bridge。如果不指定--network,创建的容器默认都会挂到docker0上。通过dockernetwork inspect bridge看一下bridge网络的配置信息。

Docker提供三种user-defined网络驱动:bridge、overlay和macvlan。 指定IP网段,只需在创建网段时指定 --subnet--gateway参数。

容器间通信

容器之间可通过IP, Docker DNS Server或joined容器三种方式通信。 外部世界访问容器:端口映射。docker可将容器对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器。每一个映射的端口,host都会启动一个docker-proxy进程来处理访问容器的流量

ip -r 查看docker host的路由表
docker ps或者docker port查看host映射端口

第6章 Docker存储

Docker为容器提供了两种存放数据的资源:

(1)由storage driver管理的镜像层和容器层。
(2)Data Volume。

先来回顾一下Docker镜像的分层结构:

image.png

容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存放在这些层中。这样的分层结构最大的特性是Copy-on-Write。

  1. 新数据会直接存放在最上面的容器层。
  2. 修改现有数据会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,镜像层保持不变。
  3. 如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。

storage driver

分层结构使镜像和容器的创建、共享以及分发变得非常高效,而这些都要归功于Docker storagedriver。storage driver实现了多层数据的堆叠,并为用户提供一个单一的合并之后的统一视图。Docker支持多种storage driver,有AUFS、Device Mapper、Btrfs、OverlayFS、VFS和ZFS。
storage driver适用于无状态的应用。无状态意味着容器没有需要持久化的数据,不需要保存数据供以后使用,使用完直接退出,容器删除时存放在容器层中的工作数据也一起被删除。

Data Volume

Data Volume本质上是Docker Host文件系统中的目录或文件,能够直接被mount到容器的文件系统中。适用于有状态的容器,即有持久化数据的需求,容器启动时需要加载已有的数据,容器销毁时希望保留产生的新数据。

bind mount:通过-v 将文件mount到容器,格式为 <host path>:<container path>
docker managed volume:不需要指定mount源,指明mountpoint就行,docker会生成一个随机目录作为mount源
通过docker inspect查看volume,或者用docker volume命令

数据共享

容器与host共享数据:两种类型的data volume,它们均可实现在容器与host之间共享数据

bind mount:直接将要共享的目录mount到容器
docker managed volume:容器启动时将共享数据从host的目录复制到volume

容器之间共享数据:
第一种方法是将共享数据放在bind mount中,然后将其mount到多个容器。
另一种在容器之间共享数据的方式是使用volume container。

volume container是专门为其他容器提供volume的容器。它提供的卷可以是bind mount,也可以是docker managed volume。

执行docker create命令,创建一个volume container。只是提供数据,它本身不需要处于运行状态

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker create --name vc_data  -v ~/htdocs:/usr/local/apache2/htdocs  -v /other/useful/tools  busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
01c2cdc13739: Pull complete 
Digest: sha256:139abcf41943b8bcd4bc5c42ee71ddc9402c7ad69ad9e177b0a9bc4541f14924
Status: Downloaded newer image for busybox:latest
86d3ec5270b9c91d3a86c109e44edbe58904f81aa261a19a797b0e8321227585

通过docker inspect可以查看到这两个volume

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker inspect vc_data
[
    {
        ... ...
        
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/root/htdocs",
                "Destination": "/usr/local/apache2/htdocs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "2c77c1371f9adee9d9156387281c2f692df3aca2fd4d86362f18d6f1824920e0",
                "Source": "/var/lib/docker/volumes/2c77c1371f9adee9d9156387281c2f692df3aca2fd4d86362f18d6f1824920e0/_data",
                "Destination": "/other/useful/tools",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        
        ... ...
    }
]

其他容器可以通过--volumes-from使用vc_data这个volume container

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker run --name web1 -d -p 80 --volumes-from vc_data httpd
b173ab11e625dd889040d2c8aec21155da0e49c4f26bb3994f01605300ca8773

查看web1的volume

[root@iZwz9f1ba8y91wed647jhlZ ~]# docker inspect web1 | grep Mounts -A 20
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/root/htdocs",
                "Destination": "/usr/local/apache2/htdocs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "2c77c1371f9adee9d9156387281c2f692df3aca2fd4d86362f18d6f1824920e0",
                "Source": "/var/lib/docker/volumes/2c77c1371f9adee9d9156387281c2f692df3aca2fd4d86362f18d6f1824920e0/_data",
                "Destination": "/other/useful/tools",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {

web1容器使用的就是vc_data的volume,而且连mount point都是一样的

docker inspect ... 查看volume
grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5grep -B 5 foo file 显示foo及前5grep -A 5 foo file 显示foo及后5

data-packed volume container,将数据完全放到volumecontainer中,同时又能与其他容器共享。其原理是将数据打包到镜像中,然后通过docker managed volume共享。data-packed volume container是自包含的,不依赖host提供数据,具有很强的移植性,非常适合只使用静态数据的场景,比如应用的配置信息、Web server的静态文件等。

docker volume ls 查看容器使用的docker managed volume
docker volume rm删除孤儿volume

第7章 多主机管理

Docker Machine可以批量安装和配置docker host,这个host可以是本地的虚拟机、物理机,也可以是公有云中的云主机。

安装 Docker Machine

  base=https://github.com/docker/machine/releases/download/v0.16.0 &&
  curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
  sudo mv /tmp/docker-machine /usr/local/bin/docker-machine &&
  chmod +x /usr/local/bin/docker-machine

Docker Machine命令

docker-machine ls查看当前的machine
docker-machine create 创建机器
docker-machine ip ... 查看机器ip
docker-machine upgrade:更新machine的docker到最新版本
docker-machine config:查看machine的docker daemon配置
stop/start/restart:是对machine的操作系统操作
docker-machine scp:可以在不同machine之间复制文件

第8章 容器网络

单个Docker Host内容器通信:通过none、host、bridge和joined容器。 跨主机网络方案包括:

  1. docker原生的overlay和macvlan;
  2. 第三方方案:常用的包括flannel、weave和calico

第9章 容器监控

Docker自带的几个监控子命令:ps、top和stats。

docker container ps \docker container ls 查看当前运行的容器
docker container top[container] : 某个容器中运行了哪些进程docker container top sysdig -au
docker container stats用于显示每个容器各种资源的使用情况

Ps、top、stats这几个命令是Docker自带的,优点是运行方便,很适合想快速了解容器的运行状态的场景。其缺点是输出的数据有限,而且都是实时数据,无法反映历史变化和趋势。

开源监控工具sysdigWeave ScopecAdvisorPrometheus

sysdig:是一个轻量级的开源的系统监控、捕获、分析和排障的工具,同时它还原生支持容器。 优点:功能全面,全方面的系统参数:CPU、Memory、Disk IO、网络 IO,支持各种 IO 活动:进程、文件、网络连接等.能获取实时的系统数据,也能把信息保存到文件中以供后面分析.用户可以随意组合自己的过滤逻辑,还可以自己编写 Lua 脚本来自定义分析逻辑,基本上不受任何限制。
工作原理:sysdig容器是以privileged方式运行,而且会读取操作系统/dev、/proc等数据,这是为了获取足够的系统信息。Sysdig 通过在内核的 driver 模块注册系统调用的 hook,这样当有系统调用发生和完成的时候,它会把系统调用信息拷贝到特定的 buffer,然后用户模块的组件对数据信息处理(解压、解析、过滤等),并最终通过 Sysdig 命令行和用户进行交互。
缺点:sysdig显示的是实时数据,看不到变化和趋势,而且是命令行操作方式。

Weave Scope:最大特点是会自动生成一张Docker Host地图,让我们能够直观地理解、监控和控制容器。可以监控kubernetes集群中的一系列资源的状态、资源使用情况、应用拓扑、scale、还可以直接通过浏览器进入容器内部调试等,其提供的功能包括:交互式拓扑界面、图形模式和表格模式、过滤功能、搜索功能、实时度量、容器排错、插件扩展。可用于k8s监控。

cAdvisor:是google开发的容器监控工具,它被内嵌到k8s中作为k8s的监控组件。会显示当前host的资源使用情况,包括CPU、内存、网络、文件系统等。一个亮点是它可以将监控到的数据导出给第三方工具,由这些工具进一步加工处理。

Prometheus:提供了监控数据搜集、存储、处理、可视化和告警一套完整的解决方案,Prometheus广泛用于 Kubernetes 集群的监控系统中。
Prometheus具有以下特点:具有由指标名称和键/值对标识的时间序列数据的多维度数据模型。PromQL灵活的查询语言。不依赖分布式存储,单个服务器节点是自主的。通过基于HTTP的pull方式采集时序数据。可以通过中间网关(Pushgateway)进行时序列数据推送。通过服务发现或者静态配置来发现目标服务对象。支持多种多样的图表和界面展示,比如Grafana等。

功能比较: image.png

第10章 日志管理

Docker logs:Docker自带的logs子命令,logging driver
日志管理方案:ELK、Fluentd和Graylog

ELK是开源实时日志分析平台,Elasticsearch,logash,kibana的结合。 Elasticsearch的功能:

  1. 搜索
  2. 全文检索
  3. 分析数据
  4. 处理海量数据PB,对海量数据进行近实时的处理(ES可以自动将海量数据分散到多台服务器上去存储和检索)
  5. 高可用高性能分布式搜索引擎数据库 Elasticsearch的应用场景:
  6. 网页搜索
  7. 新闻搜索
  8. 商品标签
  9. 日志收集分析展示

Fluentd是一个完全免费且完全开源的日志收集器,可以连接各种数据源和数据输出组件。Fluentd将日志视为JSON。

Graylog是一个开源的日志聚合、分析、审计、展现和预警工具。功能上和ELK类似,但又比ELK更加简洁,高效,部署使用简单。

第11章 数据管理

从业务数据的角度看,容器可以分为两类:无状态(stateless)容器和有状态(stateful)容器。
如果Docker Host宕机了,如何恢复容器?一个办法就是定期备份数据,但这种方案还是会丢失上次备份到宕机这段时间的数据。更好的方案是由专门的storage provider提供volume, Docker从provider那里获取volume并挂载到容器。这样即使Host挂了,也可以立刻在其他可用Host上启动相同镜像的容器,同时直接挂载之前使用的volume,这样不会有数据丢失。
跨主机管理data volume,第三方driver:Rex-Ray driver。
REX-Ray 是一个 EMC {code} 团队领导的开源项目,为 Docker、Mesos 及其他容器运行环境提供持续的存储访问。其设计旨在囊括通用存储、虚拟化和云平台,提供高级的存储功能。