Docker

Docker入门

容器技术的发展

  1. chroot

  2. Namespace
    2002年其Linux2.4.19开始引入的特性。可以通过三个系统调用直接操作Namespace

    1. clone 传递不同的namespace的标志为新的(子)进程指定其所属的namespace
    2. unshare 允许一个进程(或线程)取消当前与其他进程(或线程)共享的执行上下文
    3. setns 进入文件描述符指定的namespace
  3. cgroups 和LXC
  • Docker允许用户将容器环境打包成为一个Docker镜像进行分发,这也大大降低了用户使用的门槛

Docker的基本使用

  1. Docker安装:
  2. Docker 的生命周期

    1. created
    2. running : a. running b .paused c. restarting
    3. removing
    4. dead
    5. exited
  3. 容器资源管理:

    1. CPU
    2. 内存
    3. 网络
    4. IO
    5. GPU
  • cgroups:
    cgroups,其名称来源自控制组群(control group的简写,是Linux内核的一个功能,来用限制,控制与分离一个进程组的资源(如CPU,内存,磁盘输入输出等).

  • 容器的核心 namespace

  • /proc目录

    /proc文件系统下的多种文件提供的系统信息不是针对某个特定进程的,而是能够在整个系统范围的上下文中使用。可以使用的文件随系统配置的变化而变化。命令procinfo能够显示基于其中某些文件的多种系统信息。以下详细描述/proc下的文件。

/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过 proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是 动态从系统内核读出所需信息并提交的。


/proc下有关于每个进程的文件夹
cgroup文件

  • namespace

    • namespace 管理的资源(可用的namespace)
      Mount
      PID
      Network
      IPC
      UTS
      User
      Cgroups

    • 如何使用namespace:

      1. clone(),创建一个新的进程;但如果传递一个或多个CLONE_NEW8标志给clone,则会根据每个标志创建新的namespace 并且将紫禁城添加为其成员
      2. setns(),允许进程加入一个已存在的namespace中
      3. unshare(),允许进程(或线程)取消其执行上下文中,与其他进程(或线程)共享部分的关联。简单来说,就是可以利用此系统调用来让当前的进程(或线程)移动至一个新的namespace中。

编写容器

  1. 容器的基本属性

    1. 容器一定具有隔离性,具备了隔离性才能被成为容器
    2. 容器的资源可以被管理
    3. 容器可以从“镜像”启动
    4. 启动后的容器,可以具备网络连接
    5. 可以进入到容器中执行指令
  2. namespace 和cgroups是实现资源的隔离和管理的关键技术。其他的问题就是镜像以及网络相关的内容

1. 创建隔离环境

使用unshare 来创建隔离环境

2. 隔离主机的根目录系统

chroot可以改变进程可见的根目录。

3. 使用cgroups进行资源管理

  • 安装cgroups工具

  • 创建cgroups,容器的资源管理和限制是通过cgroup完成的,为了让我们的隔离环境更完善,创建一个可用于限制内存和CPU的cgroups作为演示。

  • 使用cgcreate来创建一个新戴尔cgroups

镜像生命周期管理

  • docker run下载镜像行为解析

    1. 查找镜像
    2. 下载镜像
  • 镜像操作:增

    • 通过docker pull 或docker image pull命令来自动下载镜像 —platform参数可以执行下载的镜像的平台

    • 加载 docker image save -o xxx.tar xxx
      docker image load -i xxx.tar

    • 导入 (import)
      docker export -o xxx.tar containerID
      docker image import xxx.tar

    • commit 从正在运行的容器创建一个镜像
      docker commit -a “xxx” containerID image:tag

    • build

      1. 写一个Dockerfile
      2. 使用docker build 构建镜像,通过-t 指定其名称和Tag
      3. docker build -t xxx:xxx
  • 镜像操作:查
    1. # 查询具体名称和Tag的镜像
    2. docker image ls xxx:tag
    3. # 查询具有相同名称的镜像
    4. docker image ls xxx
  • 镜像操作:改 ```

    只修改镜像名称或Tag

    docker image ls xxx docker image tag xxx:tag xxx-new:tag-new

基于原对象对内容做修改

启动一个容器,为它新增一个文件

docker run —rm -it alpine:latest

在该容器中进行文件操作

使用commit命令将容器保存新的tag镜像

运行该tag下的镜像,文件被保存

不保留原镜像信息做修改

将容器导出为一个tar包

docker export -o xxx.tar containerID

导入该包

docker import xxx.tar alpine:some-tag

使用新的镜像启动容器

docker run alpine:some-tag sh

使用dockerfile

  1. -
  2. 镜像操作:删

一个个删除

docker image rm xxx xxxx1 xxxx2

批量删除

docker image rm $(docker image ls alpine -q) ```

构建镜像和分发

  • 本地镜像存储

Dockerfile基本介绍

  1. Dockerfile基本格式

    • 以# 开头的是注释,除了# escape =# syntax =
    • 指令不区分大小写,但约定使用大写
  2. Docker常用指令

    • FROM 指定构镜像所用的基础镜像,通常情况下使用Docker官方镜像,可以在Docker Hub上找到。每个Dockerfile必须有FROM指令,如果没有指定FROM,则会在解析DOCKERFILE时报错

    • RUN 指定构建过程中需要执行的操作。Docker是层级结构的,每个RUN指令都会在一个新层中执行,并将其执行结果提交为一个新的层,并用于后续Dockerfile的操作。常用的RUN指令SHELL形式的,也可以使用exec形式的,不过需要用[]括起来。
      `RUN [“/usr/bin/echo”,”using exec form”]

    • EXPOSE 标识容器运行时要监听的端口,例如EXPOSE 6379则标识暴露6379端口,也可以在docker run时通过-p 参数指定

  3. Dockerfile 重要指令

    • COPY / ADD

      1. ADD 除可用于正常拷贝文件外,还可添加URL形式的远程内容

      2. ADD 可添加本地的tar归档文件或压缩文件,并且会被解压。如果是来自远程的内容,则不会解压

      3. COPY 还可用于多阶段构建中,通过—from=参数传递,可以从之前阶段中拷贝内容到新的构建阶段。

      4. 在满足要求的情况下,优先使用COPY

        1. 构建缓存
        2. 减少镜像体积
    • ARG和ENV

      1. 均可用于在构建镜像过程中预定义变量
      2. 生命周期: ARG定义的变量只影响镜像的构建阶段,但是ENV定义的变量会存在于镜像的整个生命周期,包括使用镜像创建容器,该变量仍然可用
      3. ARG在构建时,可通过—build-arg进行修改和指定,但是ENV指定的变量在构建时不可修改
      4. 优先级: 如果ARG和ENV定义的变量相似,且ARG在ENV之前,则ENV定义的变量会覆盖ARG定义的变量
      5. 使用范围: ARG可优先与FROM使用,但是ENV不可以。
      6. 如果在构建过程中修改变量的值,则使用ARG指令,如果是想要将值保留在镜像中,甚至是之后的容器中使用的话,使用ENV更加合适。应该避免ARG和ENV指向相同的变量
    • ENTRYPOINT 和 CMD

      1. 均定义了当容器运行时,需要执行的命令
      2. ENTRYPOINT定义的行为,在启动容器时,需要指定—entrypoint 才能覆盖。
      3. CMD定义的行为,在docker run [OPTIONS] image [COMMAND] [ARG …]的[COMMAN]和[ARG…]处进行覆盖
      4. 当定义ENTRYPOINT后,如果CMD使用的是exec格式,即CMD[“AA”,”BB”]形式的话,则其内容会直接作为ENTRYPOINT的参数。如果CMD使用的时shell格式,即CMD AA BB的话,最终的连接形式为ENTRYPOINT sh -c aa bb。
      5. 建议ENTRYPOINT和CMD使用exec格式。如果是工具类镜像,直接将执行该工具的命令设为ENTRYPOINT
  4. 多阶段构建
  • 为了能让最终产生只保留我们所需的内容,可以使用多阶段构建的方式。
  • Dockerfile中存在多个FROM指令,表示不同的阶段,后阶段可以使用前阶段的产物,或镜像的内容

Docker核心特性

Docker网络基础

  1. none网络
    使用null驱动,没有网络的意思

  2. host网络
    容器与主机共享网络堆栈,其hosts内容也和主机一直

  3. bridge网络
    默认模式,容器在启动时,由Docker为其分配一个IP地址,并且在访问外部网络时,会通过Docker默认提供的docker0接口出去。

  4. container网络
    容器共享指定容器的网络堆栈。

定制bridge网络

  1. 使用默认配置创建网络
    docker network create 自定义网络名 即可创建新的bridge网络

生态扩展