【docker基础知识】docker基础概念

1. docker 分层概念

【docker基础知识】docker基础概念

    linux 操作系统由内核空间和用户空间组成。
      

  • 内核空间:kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载
  • 用户空间:文件系统是 rootfs,包含 /dev, /proc, /bin 等

       对与基础镜像,底层直接使用 Host 的 kernel,而自己只需要提供 rootfs 。

     容器只能共用 Host kernel,不能修改。容器共用 host kernel,容器不能 kernel 升级。如果容器 kernel 版本有要求,这种更适合虚拟机。


1.1 为什么镜像采用分层结构

     好处就是共享资源

【docker基础知识】docker基础概念

      新镜像从 base 镜像一层一层叠加生成的。每RUN一次,就在现有镜像的基础上增加一层。

      只需在磁盘上保存一份 base 镜像;内存中也只需一份 base 镜像,就可以为所有容器使用。而且镜像的每一层都可以被共享

       当需要修改时才拷贝数据,这种称作 Copy-on-Write。


2 Dockerfile 指令

COPY
     将文件从 build context 复制到镜像。支持两种形式:

  • COPY src dest
  • COPY ["src", "dest"]

     注意:src 只能指定 build context 中的文件或目录

ADD
     从 build context 复制文件到镜像。不同的是,如果 src 是归档文件,文件会被自动解压到 dest。

ENV
     设置环境变量,环境变量可被后面的指令使用。

WORKDIR
     为后面指令设置镜像中的当前工作目录。

CMD
      容器启动时运行指定的命令。
      Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 可以被 docker run 之后的参数替换

ENTRYPOINT
      设置容器启动时运行的命令。
      Dockerfile 中可以有多个 ENTRYPOINT,只有最后一个生效。CMD 或 docker run 之后的参数会被当做参数传递给 ENTRYPOINT。


3 Docker 命令

【docker基础知识】docker基础概念

attach vs exec

  • attach 直接进入容器启动命令的终端,不会启动新的进程
  • exec 是在容器中打开新的终端,并且可以启动新的进程

      如果想直接在终端中查看启动命令的输出,用 attach;其他情况使用 exec。

stop start restart

       stop 命令向该进程发送一个 SIGTERM 信号。如果想快速停止容器,用 docker kill 命令,向容器进程发送 SIGKILL 信号,docker pause命令则不一样,它利用了cgroups的特性将运行中的进程空间暂停。

      容器可能会因某种错误而停止运行。对于服务类容器能够自动重启。启动容器时设置 --restart = always 就可以

rm

     批量删除所有已经退出的容器,可以执行如下命令:      

     docker rm $(docker ps -aq)

     docker rm -v $(docker ps -aq -f status=exited)


    build 命令根据 Dockerfile 文件中的 FROM 指令获取到镜像,然后重复地(create和start),修改,commit。在循环中的每一步都会生成一个新的层,因此许多新的层会被创建。

    docker exec 命令会在运行中的容器执行一个新进程。

    docker inspect命令会提取出容器或者镜像最顶层的元数据。 

     在 Docker 容器中的初始化进程(PID1 进程)在容器进程管理上具有特殊意义。它可以被 Dockerfile 中的 ENTRYPOINT 或 CMD 指令所指明;也可以被docker run 命令的启动参数所覆盖。

       

4 Docker 内存限额

      容器使用的内存包括两部分:物理内存和 swap。 Docker 两组参数来控制容器内存:

  • -m 或 --memory:内存的使用限额,例如 100M, 2G。
  • --memory-swap内存+swap 的使用限额。

      例如运行命令如下:

      $ docker run --memory=100M --memory-swap=200M progrium/stress --vm 1 --vm-bytes 90M

      如果在启动容器时只指定 -m 而不指定 --memory-swap,那么 --memory-swap 默认为 -m 的两倍


5 Docker CPU 限额  

        通过 -c 或 --cpu-shares 设置容器使用 CPU 的权重。如果不指定,默认值为 1024。

        容器能分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。换句话说:通过 cpu share 可以设置容器使用 CPU 的优先级

  

6 Docker Block IO 限额  

        通过设置 --blkio-weight 参数来改变容器 block IO 的优先级。

  • --device-read-bps,限制读设备的 bps
  • --device-write-bps,限制写设备的 bps
  • --device-read-iops,限制读设备的 iops
  • --device-write-iops,限制写某设备的 iops


7 Docker 网络

       Docker 安装会在 host 上创建三个网络,docker network ls 命令查看:

【docker基础知识】docker基础概念    none

       这个网络下的容器除了 lo,没有其他任何网卡。容器创建时,--network=none 使用 none 网络  

host

       容器共享 host 的网络栈,容器的网络配置与 host 完全一样。--network=host 使用 host 网络。

        最大的好处就是性能,适用的情况容器对网络传输效率有较高要求


7.1 创建网络

       网络驱动:bridge, overlay 和 macvlan。overlay 和 macvlan 用于创建跨主机的网络
       docker network create --driver bridge --subnet 172.200.200.0/24 --gateway 172.200.200.1 bridge_net
【docker基础知识】docker基础概念

       可以使用新创建的网络如下所示:
       docker run --network bridge_net
       静态IP 分配 --ip 

       容器添加网卡:
       docker network connect $network $docker_id


7.2 网络基础
  1. 网络命名空间
  2. veth 设备对
  3. Iptables / Netfilter
  4. 网桥
  5. 路由
Docker 容器中的各类网络栈设备都是 Docker Daemon 在启动时自动创建和配置的

网络命名空间代表的是一个堵路的协议栈,彼此之间相互隔离,无法通信:Veth 设备对就是打通互相看不到的协议栈 (不同命名空间进行通信)

【docker基础知识】docker基础概念



8 Docker 信号处理


     执行 docker stop 命令,docker 首先向容器的 PID1 进程发送一个SIGTERM信号,用于容器内程序的退出。如果容器在收到 SIGTERM 后没有结束, 那么 Docker Daemon 会在等待一段时间(默认是10s)后,再向容器发送 SIGKILL 信号,将容器杀死变为退出状态。这种方式给 Docker 应用提供了退出(graceful stop)机制,允许应用在收到 stop 命令时清理和释放使用中的资源。而 docker kill 可以向容器内 PID1 进程发送任何信号,缺省是发送 SIGKILL 信号来强制退出应用。

    
    由于 PID1 进程的特殊性,Linux 内核做了特殊处理。如果它没有提供某个信号的处理逻辑,那么与其在同一个PID 名空间下的进程发送给它的该信号都会被屏蔽。主要是防止 init 进程被误杀。


8.1 孤儿进程

     当一个子进程终止后,首先会变成一个失效(defunct)的进程,也称为僵尸 zombie 进程,等待父进程或系统收回。在 Linux 内核中维护了关于僵尸进程的信息(PID,终止状态,资源使用信息),从而允许父进程能够获取子进程的信息。如果不能正确回收僵尸进程,那么他们的进程描述符仍然保存在系统中,系统资源会缓慢泄露。
    

执行 docker stop 命令,docker 首先向容器的 PID1 进程发送一个SIGTERM信号,用于容器内程序的退出。如果容器在收到 SIGTERM 后没有结束, 那么 Docker Daemon 会在等待一段时间(默认是10s)后,再向容器发送 SIGKILL 信号,将容器杀死变为退出状态。这种方式给 Docker 应用提供了退出(graceful stop)机制,允许应用在收到 stop 命令时清理和释放使用中的资源。而 docker kill 可以向容器内 PID1 进程发送任何信号,缺省是发送 SIGKILL 信号来强制退出应用。