【Docker】
Docker是一个开放原始码的开放平台软体，用于开发应用、交付（shipping）应用和运行应用。Docker允许用户将基础设施（Infrastructure）中的应用单独分割出来，形成更小的颗粒（容器），从而提高交付软件的速度。
Docker容器与虚拟机类似，但二者在原理上不同。容器是将操作系统层虚拟化，虚拟机则是虚拟化硬件，因此容器更具有便携性、更能高效地利用服务器。 容器更多的用于表示软件的一个标准化单元。由于容器的标准化，因此它可以无视基础设施（Infrastructure）的差异，部署到任何一个地方。另外，Docker也为容器提供更强的业界的隔离兼容。
Docker 利用Linux核心中的资源分离机制，例如cgroups，以及Linux核心命名空间（namespaces），来建立独立的容器（containers）。这可以在单一Linux实体下运作，避免启动一个虚拟机器造成的额外负担。Linux核心对命名空间的支援完全隔离了工作环境中应用程式的视野，包括行程树、网路、用户ID与挂载档案系统，而核心的cgroup提供资源隔离，包括CPU、记忆体、block I/O与网路。从0.9版本起，Dockers在使用抽象虚拟是经由libvirt的LXC与systemd - nspawn提供界面的基础上，开始包括libcontainer函式库做为以自己的方式开始直接使用由Linux核心提供的虚拟化的设施。
== 基础架构 ==
专业名词Docker有两个意思：
* 代指整个Docker项目。
* 代指Docker引擎。
=== Docker引擎 ===
Docker引擎(Docker Engine)是一个服务端-客户端结构的应用，主要有这些部分：Docker守护进程、 Docker Engine APIdate=20200218205320 、Docker客户端。
*Docker守护进程(Docker daemons)，也叫 dockerd ，是一个持久化的进程，用户管理容器。守护进程会监听 Docker Engine APIdate=20200218205320  的请求。
* Docker Engine APIdate=20200218205320 是用于与Docker守护进程交互用的的API。它是一个RESTful API，因此它不仅可以被Docker客户端调用，也可以被wget 和 curl等命令调用。
*Docker客户端，也叫docker，是大部分用户与Docker交互的主要方式。用户通过客户端将命令发送给守护进程。命令会遵循 Docker Engine API date=20200218205320  date=20200218205320
=== Docker注册中心 ===
Docker注册中心(Docker registry)是用于存储Docker的镜像。Docker Hub 是一个公共的注册中心，任何人都可以使用，默认配置下，Docker将会在这里寻找镜像。
另外，用户可以自行构建私有注册中心。Docker Datacenter (DDC)的用户，可以直接使用 Docker Trusted Registry (DTR)。
=== 对象 ===
Docker的对象是指Images、Containers、Networks、Volumes、Plugins等等。
*容器（Containers）是镜像的可运行的实例。容器可通过API或CLI（命令行）进行操控。
*镜像（Images）是一个只读模板，用于指示创建容器。 镜像分层(layers)构建的，而定义这些层次的文件叫Dockerfile。
*服务（Services）允许使用者跨越不同的Docker守护进程（Docker daemons）的情况下增加容器，并将这些容器分为管理者（managers）和工作者（workers），让他们为swarm共同工作。
== 扩展架构 ==
=== Docker Compose ===
Compose可译为组合物。Compose 是用于定义和运行 多个容器Docker应用程序 的工具。通过Compose，你可以使用YAML文件来配置应用程序需要的所有服务，然后通过使用一个命令，就可以创建并启动所有服务。Compose对应的命令为docker-compose。
=== Swarm Mode ===
当说到 Docker Swarm 时，一般是指单独项目 Docker Swarm。而在Docker 1.12时，将swarm mode集成到Docker 引擎中，可用Docker引擎API 和 CLI 命令直接使用。官方推荐用户使用集成的 swarm mode 。
Swarm Mode 内置 kv 存储功能，提供了众多的新特性，比如：具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。使得 Docker 原生的 Swarm 集群具备与 Mesos、Kubernetes 竞争的实力。
cluster(中文：集群)，Docker将集群定义为：一群共同作业并提供高可用性的机器 。swarm(中文：群)，是指一个集群的Docker引擎以swarm mode形式运行。swarm mode是指Docker引擎内嵌的集群管理和编排功能。当你初始化了一个swarm(cluster)或者将节点加入一个swarm时，其Docker引擎就会以swarm mode的形式运行。
==== 原理 ====
swarm中的Docker机器中分为 managers（管理者） 和 workers（员工），管理者用于处理集群的关系和委派，员工则用于执行 swarm服务。 当你创建swarm服务时，你可以为其增加各种额外的状态（如：数量、网络、端口、存储资源等等）。Docker会去维持用户想要的状态。如：一个工作节点如果挂了，那么Docker会去把这个节点的任务给另外一个节点。此处的任务（task）是指：被swarm管理者管理的一个运行中的容器。
swarm服务比单独容器好在，修改swarm服务的配置之后不用重启。同时，Docker以swarm mode形式运行时，也可以选择直接启动单独的容器。另外，swarm mode下，你也可以通过 docker stack deploy 使用 Compose file 部署应用栈。 swarm服务分为两种，一种是replicated services ，可以指定节点任务的总数量；global services，则是每个节点都会运行一个指定任务。 swarm管理员使用 ingress  负载均衡使服务可被外部接触。 swarm管理员会自动地给服务分配PublishedPort（或者手动配置）。外部组件，如云负载均衡器能通过集群中任何节点上的PublishedPort去接入服务（不管该服务是否启动）。另外 swarm mode有内部DNS组件，它会为每个服务分配一个DNS条目。swarm管理员使用 internal load balancing 去分发请求时，就是依靠这个DNS组件。
swarm mode的功能是由swarmkit(一个独立项目)提供的，它实现了Docker的编排层。swarm可以直接被Docker使用。
== 文件格式 ==
Docker有两种文件格式，Dockerfile和Compose file。Dockerfile定义了单个容器的内容和启动时候的行为。Compose file定义了一个多容器应用。
=== Dockerfile ===
Docker 可以依照 Dockerfile 的内容，自动化地构建镜像。 Dockerfile 是包含着用户想要如何构建镜像的所有命令的文本。
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
关键词：
* RUN。RUN会在当前镜像的顶层上添加新的一层(layer)，并在该层上执行命令，执行结果将会被提交。提交后的结果将会用于Dockerfile的下一步。
* ENTRYPOINT，入口点。ENTRYPOINT允许你配置容器，使之成为可执行程序。即，ENTRYPOINT允许你为容器增加一个入口点。ENTRYPOINT和CMD类似，均在容器启动时执行，但是ENTRYPOINT为了提供稳定且不可被覆盖的操作。通过在命令行中指定--entrypoint 命令的方式，可在运行时将Dockerfile文件中的ENTRYPOINT覆盖。
* CMD，是command的缩写。CMD用于为已创建的镜像提供默认的操作，当不想要用默认操作时候，可用docker run  IMAGE@DIGEST COMMAND 进行替换 。但当Dockerfile拥有入口点时，CMD用于赋予入口点参数。
=== Compose文件 ===
Compose文件 是一个YAML文件，定义了服务（service）、网络、卷（volume）。
* 服务（service）定义 各容器的配置，定义内容将以命令行参数的方式 传给 docker run 命令。
* 网络（network），类似地，将定义内容传给 docker network create 命令 。
* 卷（volume），类似地，将定义内容传给 docker volume create 命令。
docker run 命令中有一些选项，和 Dockerfile文件中的指令效果一样（如：CMD, EXPOSE, VOLUME, ENV），如果Dockerfile文件中使用这些指令，那么这些指令就会被视为默认参数，所以开发者无需特意在 Compose文件中再指定一次。
Compose文件 可使用 Shell变量（Variable），如：
db:
image: "postgres:${POSTGRES_VERSION}"
Compose文件 可通过自身的ARGS变量，将参数传给Dockerfile的 ARGS 指令。
== 网络 ==
参考文档： Docker文档-网络概要date=20200415060005
=== bridge ===
在Docker里，网桥网络 使用的是 软件形式的网桥。使用相同的网桥的容器连接进入该网络，而非该网络的容器刷故无法接入。Docker网桥驱动会自动地在Docker主机上安装规则，这些规则让不同桥接网络之间不能直接通信。 桥接经常用于：在单独容器上运行应用时，可通过 网桥 进行通信。 网桥网络 适用于容器运行在相同地Docker守护进程的主机上。不同Docker守护进程主机上的容器，它们之间的通信需要依靠操作系统层次的路由，或者你应该使用 overlay网络 进行代替。
bridge 是网桥驱动，是Docker默认的网络驱动（接口名为 docker0），当你不为容器指定一个网络时候，Docker将会使用该驱动。  可通过  daemon.json 文件修改相关配置。
自定义网桥可通过 brctl 命令进行配置。
=== host ===
主机模式
host 用于单独容器，该网络下容器只能和Docker主机进行直接连接。host 只适用于 Docker 17.06或以上版本的swarm服务。
host网络和VirtualBox的 仅主机网络（Host-only Networking） 类似。
=== overlay ===
overlay （中文：覆盖网络）网络驱动将会创建分布式网络，该网络可以覆盖若干个 Docker守护进程主机。该网络是基于 主机特定网络（host-specific networks），允许 swarm服务 和 容器 进行安全通信（当加密功能开启时）。在该网络下，Docker能够清晰地掌握 数据包的路由 以及 发送接收容器。
overlay 有两种网络类型网络：
* ingress 网络，可掌控 swarm服务 的网络流量 。该网络是 overlay  的默认网络。
* docker_gwbridge 网络是 网桥网络。该网络会将 单独的Docker守护进程 连接至 swarm里的另外一个守护进程。
在 overlay 网络下，单独的容器 和 swarm服务 的行为和配置概念 是不一样的。
该策略不需要 容器们 具有操作系统级别的路由，因为Docker负责路由。
=== macvlan ===
Macvlan 网络允许你赋予容器 MAC地址 ，在该网络里，容器会被认为是物理设备。Docker守护进程会路由
=== none ===
该策略下，容器不使用任何网络。none 常常用于连接自定义网络驱动的情况下。
=== 其他 ===
其他第三方插件。
== 数据管理 ==
Docker默认下，所有文件将会存储在容器里的可写的容器层（container layer）。
* 数据与容器为一体。随着容器消失，数据将消失；难以与其他程序（容器）共享。
* 由于容器的写入层是与宿主机器紧紧耦合。所以你难以移动数据到其他机器。
* 容器的写入层的是通过  存储驱动date=20200218205357 （storage driver） 管理文件系统。 存储驱动date=20200218205357  会使用Linux内核的 链合文件系统（union filesystem）进行挂载。相比起直接操作于宿主机器文件系统的 数据卷，这额外的抽象层将会降低性能。
容器有两种永久化存储方式：卷（volumes）和 绑定挂载（bind mounts）。另外，Linux用户还可使用 tmpfs 进行挂载；Window用户还可以使用 命名管道（named pipe）。在容器中，不管是哪种永久化存储，表现形式都是一样的。
=== 卷 ===
卷（volumes）是宿主机器的文件系统的一部分，由Docker进行管理（ 在Linux，存储于/var/lib/docker/volumes/）。非Docker程序不应该去修改这些文件。Docker推荐使用 卷 进行持久化数据。 卷 可支持 卷驱动（volume drivers），该驱动允许用户将数据存储到 远程主机 或 云服务商（cloud provider）或 其他。
没有名字的卷叫匿名卷（anonymous volume），有名字的卷叫命名卷（named volume）。匿名卷没有明确的名字，当被初始化时，会被赋予一个随机名字。
=== 绑定挂载 ===
绑定挂载（bind mounts）通过将宿主机器的路径挂载到容器里的这种方式，从而数据持续化，因此绑定挂载可将数据存储在宿主机器的文件系统的任何地方。非Docker程序可修改这些文件。 绑定挂载是Docker早期就存在的，相比起卷，绑定挂载十分简单明了。 在开发Docker应用时，应使用命名卷（named volume）代替绑定挂载，因为用户不能对绑定挂载进行 Docker CLI 命令操作。
绑定挂载常用于：
* 同步配置文件，如： 将 宿主主机的DNS配置文件（/etc/resolv.conf）同步至容器中
* 在开发程序时，将 源代码 或 Artifact 同步至容器中。 这种用法与 Vagrant 类似。
=== tmpfs ===
tmpfs 挂载（tmpfs mounts），仅仅存储于内存中，并不操作 宿主机器的文件系统（不持久化于磁盘）。它可用于存储一些 非持久化状态、敏感数据。 举例，swarm服务 通过tmpfs 将  secretsdate=20200321112911 （密码、密钥、证书等）存储到swarm服务。
=== 命名管道 ===
命名管道（named pipes），通过 npipe 挂载的形式，使 Docker主机 和 容器 之间能互相通讯。常见用例是在容器内运行第三方工具，并使用命名管道连接到Docker Engine API。
=== 覆盖问题 ===
当挂载 空的卷 至一个目录中，目录中的内容会被复制于卷中（不会覆盖）。如果挂载 非空的卷 或 绑定挂载 至一个目录中，那么该目录的内容将会被隐藏（obscured ），当卸载后内容将会恢复显示。
== 日志 ==
在UNIX和类Unix系统中，常见的 I/O流（I/O streams） 分为三种：STDIN（输入 ）、 STDOUT（正常输出）、STDERR（错误输出）。
默认配置下，Docker的日志（如：docker logs、docker service log）所记载的是命令行的输出结果（STDOUT和STDERR）。而STDOUT 和 STDERR 对应的文件路径分别是 /dev/stderr和/dev/stdout。 另外，也可以在宿主主机上查看容器的日志，使用以下命令可以查看到容器的日志位置。
$ docker inspect --format= $INSTANCE_ID
== Kubernetes in docker ==
kind（全称：Kubernetes IN Docker）是部署本地Kubernetes集群的工具，而集群的节点是由Docker生成的。
== 操作细节 ==
在安装完kind之后，通过kind create cluster命令生成集群。 生成Kubernetes集群后，可以通过Docker命令进行查看节点概览：
$ docker container ls
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                       NAMES
99c96c1f21ab        kindest/node:v1.17.0   "/usr/local/bin/entr…"   4 minutes ago       Up 4 minutes        127.0.0.1:32769->6443/tcp   kind-control-plane
== 历史 ==
Docker命令在过去的发展中诞生了40种以上的命令，过多的命令导致混乱以及难以使用tab自动补充，因此在docker 1.13版本（2017.1.19）中，命令行被重构，根据逻辑对象进行划分。官方建议用户使用新的语法进行操作。
== 已过时 ==
=== Docker Swarm ===
参考Swarm Mode章节。
=== Docker Machine ===
Docker Machine 是一个工具，它允许你在虚拟宿主机上安装 Docker引擎，并使用 docker-machine 命令管理这些宿主机。你可以使用 Machine 在你本地的 Mac 或 Windows box、公司网络、数据中心、或像 AWS 或 Digital Ocean 这样的云提供商上创建 Docker 宿主机。
Docker Machine 最后更新时间是在0.16.0 (2018-11-08)版本。官方建议在1.12以及之后版本使用Docker Desktop for Mac和Docker Desktop for Windows进行代替。
=== Docker Toolbox ===
Docker Toolbox是用于帮 Windows系统和Mac系统 安装Docker环境。新版本建议使用Docker Desktop for Mac和Docker Desktop for Windows进行安装。最后更新版本是 19.03.1(2019-08-01)。
==安全性争议==
2021年，安全公司Palo Alto Networks研究人员Aviv Sasson，在Docker Hub上发现的恶意容器映像档，分别来自10个不同帐号，总下载次数超过2000万次，其中内含的挖矿软体。
== 参考文献 ==
== 外部连结 ==
*  Source code repositorydate=20190201052505
*  Multi-tenancy using Dockerdate=20141110083528
*  Docker 101 Tutorialdate=20141012120005
*  libcontainer git repodate=20140816072508
*  如何在Linux下安装Dockerdate=20170102080531
*  Windows 容器date=20180305063147  - 在 Windows 10 部署 Docker