Docker:Docker基础知识

docker是什么

docker 是一个基于Go语言的开源应用容器引擎。

docker可以让开发者打包自己的应用到一个轻量级、可移植的容器中,实现容器化。

不同容器内的程序不会相互影响,想删除某个容器应用,通过直接删除掉容器,能够达到最小残留。

这比起直接安装应用,更加方便管理。

看到这些,感觉docker与虚拟机大同小异,那么他们的区别在哪儿?

docker与虚拟机的区别:

虚拟机运行程序时,如下图:

  • HardWare:计算机硬件资源
  • Kernel:操作系统内核(内核应该包含在操作系统中,为了虚拟机结构图和docker容器结构图区分,单独拿出来了)
  • Host OS:宿主机除内核的操作系统
  • Hypervisor:计算机管理程序,分配管理宿主机的资源,实现硬件资源虚拟化。Hypervisor能够直接管理调用硬件资源,甚至可以不需要底层操作系统。
  • Guest OS:客户机(虚拟机)操作系统
  • Dependencies:相关依赖等
  • APP:程序主体

docker容器的程序运行结构,如下图:

  • Docker daemon:docker守护进程

对比两张结构图:

1、管理

  • 虚拟机需要一层Hypervisor去管理虚拟机的运行情况,Hypervisor能够直接管理调用底层资源,所以它承载着虚拟机(VM)

  • 而docker则是运行一个进程(docker daemon)去管理容器,不属于父子关系。

    比如docker一个容器运行mysql,通过ps命令(或者pstree)查看进程,mysql-master容器进程的父进程是-bash,-bash的父级是sshd,sshd的父级是systemd,中间没有经过守护进程,如下图:

2、内核

  • 虚拟机中还有一个Kernel(操作系统内核),所以虚拟机是不依赖宿主机内核的,只要有Hypervisor,虚拟机就都能够运行。

  • docker的容器中没有内核,只有一层操作系统。因为docker容器的运行都依赖于宿主机内核,这意味着docker只能在linux上运行(其他系统都需要有linux虚拟机),且不能在低版本 Linux宿主机 运行 高版本Linux容器。

3、技术

  • 虚拟化,虚拟机的Hypervisor能够直接管理硬件资源,实现硬件隔离。

  • 容器化(容器虚拟化),docker daemon依赖宿主机内核的cGroups与namespace特性,实现对容器的资源限制隔离。

docker的三个基本概念

docker的三个基本概念:

  • 镜像(Image):用于docker容器的创建运行,方便移植。类似于代码,可以放到其他服务器上去运行。
  • 容器(Container):docker运行程序的载体。通过镜像创建容器,可以看成代码运行起来,在内存中开辟的空间,只要有代码都可以运行出同样的程序。此时删除镜像,容器不会发生改变。
  • 仓库(Repository):镜像的存储空间,可以看成代码仓库,比如github。

docekr的配置与使用

[Linux][阿里服务器]CentOS7联网安装docker-ce(yum)

[Linux][阿里服务器]CentOS7离线安装docker-ce

docker如何实现容器化

docker的容器化体现在资源限制与容器间隔离,主要依赖于内核的cgroups与namespace特性。

首先看一下这两个特性的作用

docker容器的资源限制,通过cGroups(control groups)实现,

它最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。以文件目录形式 挂载在 /sys/fs/cgroup。

docker容器间的隔离,是通过 namespace 命名空间进行的划分,在不同的 namespace 下 进程相互不可见。
namespace 也分为:

  • pid ns(管理进程id PID: Process ID)、
  • net ns(管理网络 NET: Networking)、
  • mnt ns(管理挂载点 MNT: Mount)、
  • ipc ns(管理进程间通信 IPC: InterProcess Communication)
  • uts ns(Unix时间系统隔离 UTS: Unix TimesharingSystem)

那么,这两个特性是对进程组的限制,和docker容器有什么关系?

docker容器 实际上就是一个个进程,可以通过 ps -ef 查看运行容器的进程,一个容器可能存在多个进程。

比如,现在我创建一个镜像,里边有一个java程序,一个mysql。

使用docker run运行容器后,该容器至少存在java进程与mysql进程。

这样看来,容器和其中的进程并不能画等号

有时会遇到这样的情况:

内存使用空间过高,导致OOM,

触发的OOM Killer,会杀死容器的某个或某些进程,导致容器存在,但是进程已死 容器无法使用。

解决方案一,

强制kill容器docker kill <容器别名或者容器id>
然后启动容器docker start <容器别名或者容器id>

解决方案二(此方法由于删除容器,容器数据若无挂载数据卷,将导致数据丢失),

强制移除容器docker rm -f <容器别名或者容器id>
然后清理网络占用docker network disconnect --force bridge <容器别名或者容器id>

docker的信号机制

docker stop 与 docker kill 均可以将容器停掉,但二者究竟有什么区别呢?首先,摘录一下官网对这两个功能的描述:

docker stop: Stop a running container (send SIGTERM, and then SIGKILL after grace period) [...] The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL. [emphasis mine]
docker kill: Kill a running container (send SIGKILL, or specified signal) [...] The main process inside the container will be sent SIGKILL, or any signal specified with option --signal. [emphasis mine]

docker stop,支持“优雅退出”。

先发送SIGTERM信号,在一段时间之后(10s)再发送SIGKILL信号。

Docker内部的应用程序可以接收SIGTERM信号,然后做一些“退出前工作”,比如保存状态、处理当前请求等。

docker kill,发送SIGKILL信号,应用程序直接退出。

两种停止容器的方式与 linux下的kill命令的-15(结束必要工作后退出)和-9(强制kill)效果相似。

线上应用优雅退出十分必要。docker stop也不是docker独有的设计,lxc和google borg系统都有类似设计,即在发送SIGKILL之前,发送SIGTERM信号通知任务。

之前有遇到一次因为强制kill导致docker hang死的经历:

当时是由于磁盘使用空间已满,导致一个k8s容器发生故障,清理磁盘后决定重启该容器。

发现无法停止该容器,docker stop后容器依然存在,判断此时容器内进程已停止,使用 docker kill强制停止容器。

重启后发现,容器仍旧没有正常工作,决定重启docker。

停止docker后,发现启动docker后 docker命令无法使用,docker ps 会卡死没有反应。

再次停止docker,检查docker状态,发现停止docker的信号是SIGNKILL,导致docker守护进程没有正常停止。kill 掉守护进程,启动docker之后 可以正常使用。

docker文件目录

不同版本的docker目录不一样,通用目录一般有:

  1. containers:存放容器基本信息。目录名称对应容器ID,
    • config.v2.json 存储环境变量、容器创建时间、容器路径、容器名称、容器网关,文件驱动、网桥等信息
    • hostconfig.json 存储容器数据映射、cpu限制、磁盘限制、内存限制、掩码、网关等信息
    • hostname 存储容器内部的主机名
    • hosts 存储容器内部的主机配置
  2. image:存放镜像基本信息
  3. network:存放容器网络连接信息
  4. swarm
  5. temp:临时数据
  6. trust:信任文件
  7. volumes:容器卷数据信息
  8. overlay/overlay2/aufs:存储镜像层、容器层文件。
    overlay/overlay2/aufs是三种不同的文件存储驱动,以前docker首选aufs驱动,但是有些linux发行版不支持aufs。目前常见overlay和overlay2。

docker的文件存储驱动

overlayFS是和aufs相似的联合文件系统。

docker的overlay存储驱动利用overlayFS的一些特征来构建管理镜像和容器的磁盘结构。

overlay

在这里插入图片描述

overlay应用两个目录,upperdir和lowerdir,分别是容器层和镜像层。
通过联合挂载技术将镜像层和容器层挂载到同一层,提供统一视图。

docker pull 拉取镜像后,在docker目录下的overlay目录中会增加对应的镜像目录,镜像目录的名称和镜像ID并不是对应的(
docker1.10开始,使用基于内容的寻址,因此目录名和镜像层的id不一致)。
镜像目录中的root目录为镜像层的所有目录文件。

docker 启动一个容器后,overlay目录下会生成两个目录,xxx....xx和xxx....xx-init。
xxx....xx为读写层,xxx....xx-init为初始层,初始层存储容器的相关环境信息,对容器的修改都是存在于读写层。

overlay2

overlay2 可以实现多层文件结构,镜像层和容器层都有diff和work两个目录,diff用于存储内容,work用于存储修改时的内容。
容器的读写层 多一个merged目录,该目录为联合挂载后的视图目录,容器内的目录文件就是此文件下的文件结构。

文件存储驱动详解 - doker的overlay文件系统

DOCKER存储驱动之AUFS简介

posted @ 2022-04-11 00:03  钢板意志  阅读(305)  评论(0编辑  收藏  举报