1. docker组成

image.png

2. 容器隔离

image.png

3. Control groups cgroup

Linux Cgroups的全称是Linux Control Groups,是Linux内核的一个功能.最早是由Google的工程师(主
要是Paul Menage和Rohit Seth)在2006年发起,最早的名称为进程容器(process containers)。在
2007年时,因为在Linux内核中,容器(container)这个名词有许多不同的意义,为避免混乱,被重命
名为cgroup,并且被合并到2.6.24版的内核中去。自那以后,又添加了很多功能。
如果不对一个容器做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug
程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资
源分配限制,比如CPU、内存等
Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带
宽等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等
操作)。

4. docker的进程关系

docker 相关的四个进程:

  • dockerd: 服务器程序,被client直接访问,其父进程为宿主机的systemd守护进程。
  • docker-proxy: 每个进程docker-proxy实现对应一个需要网络通信的容器,管理宿主机和容器的之间端口映射,其父进程为dockerd,如果容器不需要网络则无需启动
  • containerd: 被dockerd进程调用以实现与runc交互
  • containerd-shim: 真正运行容器的载体,每个容器对应一个containerd-shim进程,其父进程为containerd

docker-proxy
image.png

5. 容器的创建与管理过程

image.png

  1. dockerd通过grpc和 containerd模块通信,dockerd由libcontainerd负责和containerd进行交
    换,dockerd和containerd 通信socket文件: /run/containerd/containerd.sock
  2. containerd在dockerd启动时被启动,然后containerd启动grpc请求监听,containerd处理grpc
    请求,根据请求做相应动作
  3. 若是run, start或是exec 容器,containerd 拉起一个container-shim , 并进行相应的操作
  4. container-shim别拉起后,start/exec/create拉起runC进程,通过exit、control文件和
    containerd通信,通过父子进程关系和SIGCHLD监控容器中进程状态
  5. 在整个容器生命周期中,containerd通过 epoll 监控容器文件,监控容器事件

    6. docker0 网卡

    开启一个容器就会开启一个虚拟网卡
    虚拟网卡自动加入到docker0的网桥里面
    image.png
    关闭所有容器后,没有虚拟网卡了
    image.png

    7. docker服务添加标签

    ```bash [root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service

    修改下面行

    ExecStart=/usr/bin/dockerd -H fd:// —containerd=/run/containerd/containerd.sock —label=”name=docker1”

[root@ubuntu1804 ~]#systemctl daemon-reload [root@ubuntu1804 ~]#systemctl restart docker [root@ubuntu1804 ~]#docker info ID: LVU6:OXD3:TAPB:KDNQ:YRSN:XTAS:3V32:IERB:2DM6:4CDK:CRO6:ZKAW Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: name=docker1 #此处显示添加的标签 Experimental: false Insecure Registries: 127.0.0.0/8
Registry Mirrors: https://si7y70hh.mirror.aliyuncs.com/ Live Restore Enabled: false WARNING: No swap limit support

  1. <a name="x52i5"></a>
  2. # 8. 开启docker的远程访问

方法1

[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service

修改下面行

ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 —containerd=/run/containerd/containerd.sock —label=”name=docker1”

  1. ```
  2. #实现远程访问方式2
  3. [root@centos7 ~]#docker -H tcp://10.0.0.100:2375 info

9. 镜像结构和原理

image.pngimage.png

scratch 最底层镜像,所有镜像从这个镜像来

镜像即创建容器的模版,含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于方便和快
速的创建并启动容器
镜像含里面是一层层的文件系统,叫做 Union FS(联合文件系统),联合文件系统,可以将几层目录挂载
到一起(就像千层饼,洋葱头,俄罗斯套娃一样),形成一个虚拟文件系统,虚拟文件系统的目录结构就
像普通 linux 的目录结构一样,镜像通过这些文件再加上宿主机的内核共同提供了一个 linux 的虚拟环
境,每一层文件系统叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限,只读
(readonly)、读写(readwrite)和写出(whiteout-able),但是镜像中每一层文件系统都是只读的,
构建镜像的时候,从一个最基本的操作系统开始,每个构建提交的操作都相当于做一层的修改,增加了
一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层
把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层,实际上也不
需要知道里面有几层,结构如下:
image.png
一个典型的 Linux文件系统由 bootfs 和 rootfs 两部分组成
bootfs(boot file system) 主要包含bootloader和kernel,bootloader主要用于引导加载 kernel,Linux
刚启动时会加载bootfs文件系统,当boot加载完成后,kernel 被加载到内存中后接管系统的控制权,bootfs
会被 umount 掉

rootfs (root file system) 包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc 等标准目录和文
件,不同的 linux 发行版(如 ubuntu 和 CentOS ) 主要在 rootfs 这一层会有所区别。
一般的镜像通常都比较小,官方提供的Ubuntu镜像只有60MB多点,而 CentOS 基础镜像也只有
200MB左右,一些其他版本的镜像甚至只有几MB,比如: busybox 才1.22MB,alpine镜像也只有5M
左右。镜像直接调用宿主机的内核,镜像中只提供 rootfs,也就是只需要包括最基本的命令,配置文件和
程序库等相关文件就可以了。
下图就是有两个不同的镜像在一个宿主机内核上实现不同的rootfs。
image.png
容器、镜像和父镜像关系:
image.png

10. docker命令

查看镜像分层历史
docker image history nginx

打包
docker save nginx -o nginx.tar

搜索点赞100个以上的镜像
#旧语法
docker search -s 100 centos
#新语法
docker search —filter=stars=100 centos

11. dockerfile

请注意,每条指令都是独立运行的,并会导致创建新镜像,比如RUN cd /tmp 对下一条指令不会有任
何影响。
Docker将尽可能重用中间镜像层(缓存),以显著加速docker build 命令的执行过程,这由Using
cache 控制台输出中的消息指示

1、基础镜像、公有仓库拉取
2、安装常用软件、创建用户、yum源
3、安装基础服务:nginx、php、jdk、
image.png

Dockerfile 文件说明

  • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
  • 使用 # 开始作为注释
  • 每一行只支持一条指令,每条指令可以携带多个参数
  • 指令按文件的顺序从上至下进行执行
  • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令
  • 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面

    11.1. dockerfile参数

    LABEL: 指定镜像元数据
    MAINTAINER: 指定维护者信息
    此指令已过时,用LABEL代替
    MAINTAINER
    范例:
    MAINTAINER wangxiaochun root@wangxiaochun.com
    #用LABEL代替
    LABEL maintainer=”wangxiaochun root@wangxiaochun.com

RUN: 执行 shell命令
RUN 指令用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令。
通常各种基础镜像一般都支持丰富的shell命令
注意: RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多
个shell命令通过 && 连接一起成为在一条指令
每个RUN都是独立运行的,和前一个RUN无关

ENV: 设置环境变量
ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY或${KEY}进行引用,并在容器运行时保持

COPY: 复制文本
说明:
可以是多个,可以使用通配符,通配符规则满足Go的filepath.Match 规则filepath.Match 参考链接: https://golang.org/pkg/path/filepath/#Match
必须是build上下文中的路径(为 Dockerfile 所在目录的相对路径),不能是其父目录中的文件
如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制
如果指定了多个, 或在中使用了通配符,则必须是一个目 录,且必须以 / 结尾
可以是绝对路径或者是WORKDIR 指定的相对路径
使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等
如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录

ADD: 复制和解包文件
该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解缩。可以将复制指定的 到容器中的
说明:
可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压)
可以是绝对路径或者是WORKDIR 指定的相对路径
如果是目录,只复制目录中的内容,而非目录本身
如果是一个 URL ,下载后的文件权限自动设置为 600
如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>
如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于”tar -x”命令,但是通过URL获取到的tar文件将不会自动展开
如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到

CMD: 容器启动命令
一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运
行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令.
如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么开启容器时就会使用执行CMD指定的默认的命令
前面介绍过的 RUN 命令是在构建镜像进执行的命令,注意二者的不同之处
每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行
如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令

ENTRYPOINT: 入口点
功能类似于CMD,配置容器启动后执行的命令及参数
ENTRYPOINT 不能被 docker run 提供的参数覆盖,而是追加,即如果docker run 命令有参数,那么参数全部都会作为ENTRYPOINT的参数
如果docker run 后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINT的参数
如果docker run 后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数
可以通过docker run —entrypoint string 参数在运行时替换,注意string不要加空格
使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效

12. docker挂载

image.png