深入浅出Docker学习笔记
Docker引擎
-
Docker引擎
:用来运行和管理容器的核心文件- 模块化(基于开放容器计划
OCI
相关标准要求) - 主要组件:
Docker Client
、Docker daemon
(Docker
守护进程)、containerd
以及runc
- 模块化(基于开放容器计划
-
runc
-
OCI
容器运行时规范的参考实现 - 实质上是一个轻量级的、针对
Libcontainer
进行了包装的命令行交互工具-
Libcontainer
是Docker公司
开发用于替代LXC
的工具 -
LXC
提供了对诸如命令空间(Namespace)
和控制组(CGroup)
等基础工具的操作能力,它们是基于Linux内核
的容器虚拟化技术 -
LXC
基于Linux
,对跨平台有阻碍
-
- 作用:创建容器
- 是一个
CLI包装器
,实质上就是一个独立的容器运行时工具 -
runc
所在的层有时也称为“OCI层
”
- 是一个
-
runc
与操作系统内核接口进行通信,基于所有必要的工具(Namespace
、CGroup
等)来创建容器,容器进程以runc
的子进程启动,启动完毕后,runc
将会退出
-
-
containerd
- 作用:负责容器的生命周期管理——
start
|stop
|pause
|rm
... - 后来也负责镜像管理,额外功能都是模块化可选的
- 以
daemon
(守护进程)方式运行 - 不负责创建容器,而是指挥
runc
去做,containerd
将Docker镜像
转换成OCI bundle
,并让runc
基于此创建一个新的容器
- 作用:负责容器的生命周期管理——
-
daemon
- 提供功能丰富、基于版本的
REST API
- 使用
CRUD风格
的API
,通过gRPC
与containerd
进行通信 - 将所有的用于启动、管理容器的逻辑和代码从
daemon
中移除,意味着容器运行时
与Docker daemon
是解耦的,有时称为“无守护进程的容器”- 好处:对
Docker daemon
的维护和升级工作不会影响到运行中的容器
- 好处:对
- 将越来越多的功能从
daemon
中拆解出来并模块化之后,daemon
还剩什么?- 暂时还包括的主要功能:镜像管理、镜像构建、
REST API
、身份验证、安全、核心网络以及编排
- 暂时还包括的主要功能:镜像管理、镜像构建、
- 提供功能丰富、基于版本的
-
shim
- 是实现无
daemon
的容器不可或缺的工具 -
containerd
指挥runc
来创建容器。实际上,每次创建容器时,shim
都会fork
一个新的runc
实例,一旦容器创建完毕,对应的runc
进程就会退出 - 一旦容器进程的父进程
runc
退出,相关联的containerd-shim
进程就会成为容器的父进程。 - 作为容器的父进程,
shim
的部分职责如下:- 保持所有的
STD_IN
和STD_OUT
流是开启状态,从而当daemon
重启的时候,容器不会因为管道(pipe
)的关闭而终止 - 将容器的退出状态反馈给
daemon
- 保持所有的
- 是实现无
Docker镜像
- 镜像由多个层组成,每个层叠加后,从外部看就像一个独立的对象。
- 镜像内部是一个精简的操作系统(
OS
),同时还包含应用运行所必须的文件和依赖包- 通常镜像中只包含一个
精简的shell
,甚至没有。 - 镜像中不包含内核——容器都是共享所在
Docker主机
的内核
- 通常镜像中只包含一个
- 镜像可以理解为一种
构建时(build-tiem)结构
,而容器可以理解为一种运行时(run-time)结构
- 一个镜像可以有多个标签
-
悬虚镜像
- 没有标签的镜像
- 出现原因:构建了一个新镜像,然后为新镜像打了一个已经存在的标签,接着
Docker
会移除旧镜像上的标签,旧镜像就变成了一个悬虚镜像
-
Docker
通过存储引擎(新版本采用快照机制)的方式实现镜像层堆栈,并保证多镜像层对外展示位同一的文件系统。-
Linux
上可用的存储引擎有AUFS
、Overlay2
、Device Mapper
、Btrfs
以及ZFS
-
Windows
上仅支持windowsfilter
-
- 多个镜像之间可以并且确实会共享镜像层。节省空间并提升性能
- 镜像本身就是一个配置对象,其中包含了镜像层的列表和一些元数据信息
- 镜像层才是实际数据存储的地方
- 内容散列
- 镜像的唯一标识是一个
加密ID
,即配置对象本身的散列值 - 每个镜像层也由一个
加密ID
区分,其值为镜像层本身内容的散列值 - 修改镜像的内容或其中任一的镜像层,都会导致散列值的变化。镜像和镜像层都是不可变的,任何改动都能很轻松地辨别
- 推送和拉取镜像的时候,都会对镜像进行压缩来节省网络带宽以及仓库的二进制存储空间,但是压缩会改变镜像内容,这导致镜像内容的散列值在推送或者拉取之后,会与镜像内容不相符。为了避免该问题,每个镜像层同时会包含一个分发散列值,这是一个压缩版镜像的散列值。
- 镜像的唯一标识是一个
- 如果某镜像中有一个
Bug
,拉取下来并修改之后,重新推送回仓库。此时使用了问题镜像相同的标签,原镜像被覆盖,但是生产环境使用的大量运行中的容器无法区分正在使用的镜像版本是修复前还是修复之后的-
Docker1.10
中引入了新的内容寻址存储模型。 - 作为模型的一部分,每一个镜像现在都有一个基于其内容的密码散列值,镜像内容变更一定会导致散列值变更
-
-
多架构镜像,配置
Menifest列表
- 删除镜像时,必须确保与该镜像相关的全部容器停止并被删除
- 如果镜像的某个层被多个镜像共享,那么只有依赖该镜像层的所有镜像被删除后,该镜像层才会删除
- 常用命令
docker container run
docker service create
-
docker image pull <repository>:<tag>
:拉取镜像,如果没有指定tag标签
,默认latest
;-a
拉取全部镜像 -
docker image ls
-
--filter dangling=true/false
:仅返回悬虚镜像(true
) -
--filter before id/name
:返回在id
或者镜像名之前创建的全部镜像 -
--filter since id/name
:返回在id
或者镜像名之后创建的全部镜像 -
--filter label
::根据标注(label
)的名称或值,对镜像进行过滤 -
--format
:通过go模版
对输出内容进行格式化 -
--digests
:查看镜像摘要(内容散列值)
-
-
docker search
-
NAME
:搜索仓库名为NAME
中包含的所有镜像 -
label
:返回所有仓库中包含label
的镜像 -
--filter is-official=true
:过滤非官方镜像 -
--filter is-automated=true
:只显示自动创建的镜像 -
--limit
:增加返回内容的行数,最大100行,默认25行
-
-
docker image inspect name
:显示镜像分层信息 docker image rm id
Docker容器
- 虚拟机与容器的最大区别:容器更快并且更轻量级——容器会共享其所在主机的操作系统/内核
- 容器只有一份
OS
损耗,也只要一份授权,占用更少的资源,启动更快
- 容器只有一份
-
Hypervisor
是硬件虚拟化,容器时操作系统虚拟化 - 常用命令
-
docker container run <image> <app>
:启动容器-
docker container run -it ubuntu /bin/bash
:-it
参数表示将当前终端(terminal
)以交互方式连接到容器的shell
上。启动ubuntu镜像
的bash程序
-
-d
:后台模式 -
sleep time
:运行指定time时间
关闭容器 -
--restart
always
unless-stopped
on-failed
-
-
docker container exec -it id bash
:将终端重新连接到docker docker container stop
docker container start
docker container rm
-
Crtl+PQ
:断开shell
与容器终端的链接,并在退出后保持容器在后台处于运行(UP
)状态 -
docker container exec
:允许用户在运行状态的容器中,启动一个新进程 -
docker container inspect
:显示容器的配置细节和运行时信息
-
应用的容器化
- 项目源码
- 编写
Dockerfile
- 对当前应用的描述
- 指导
Docker
完成应用容器化 -
FROM
:指定基础镜像层 -
LABEL
:设置一个键值对 -
RUN
:会在FROM
指定的基础镜像层上,新建一个镜像层,并执行指令,例如安装程序 -
COPY
:将应用相关文件从构建上下文中复制到当前镜像中,并新建一个镜像层来存储 -
WORKDIR
:为Dockerfile
中尚未执行的指令设置工作目录,该目录与镜像相关,并且会作为元数据记录到镜像的配置中,但不会创建新的镜像层 -
EXPOSE 8080
:暴露指定端口,作为元数据保存,不会产生新的镜像层 -
ENTERPOINT
:指定镜像以容器方式启动后默认运行的程序 -
Docker
指令不区分大小写,通常采取大写,便于区分;部分指令会创建新的镜像层(通常是添加新的文件或程序),其他指令只会增加或修改镜像的元数据信息
-
docker image build -t web:latest .
:在当前目录(.
)构建一个名为web:latest
的镜像 - 推送镜像到仓库
docker image push
- 先使用
Docker ID
登录Docker Hub
Docker login
- 推送之前,为镜像打上标签
-
Registry
(镜像仓库服务,默认docker.io
) -
Repository
(镜像仓库) -
Tag
(镜像标签,默认latest
) -
docker image tag web:latest you_can_access/web:latest
:为镜像添加一个额外的标签,并且不需要覆盖已经存在的标签
-
docker image push you_can_access/web:latest
- 先使用
- 运行应用程序
docker container run -d --name ...
-
APP
测试 - 查看构建历史:
docker image history web:latest
- 生产环境的多阶段构建
- 在一个
Dockerfile
中添加多个FROM
指令,构成几个单独的构建阶段(一般前面几个阶段构建运行环境,一般镜像都很大,最后一个阶段构建应用生产环境,用一个比较小的包作为基础) - 最后一个阶段使用
COPY --from
指令从前面几个阶段构建的镜像中仅复制生产环境相关的应用代码,而不会复制生产环境不需要的构造 - 完成之后,前几个阶段生成的镜像会变成悬虚镜像
- 在一个
- 建造者模式构建
- 至少需要两个
Dockerfile
- 一个用于开发环境
Dockerfile.dev
,一个用于生产环境Dockerfile.prod
(基于较小的基础镜像开始构建) - 生产环境的
Dockerfile
将开发环境中的与应用程序相关的部分复制过来,整个过程需要额外的脚本才能串联起来
- 至少需要两个
- 最佳实践
- 利用构建缓存
- 合并镜像:
docker image build --squash
- 使用
no-install-recommends
:确保Linux
的APT包管理器
仅安装核心依赖 - 不要使用
MSI包
(Windows
)
使用Docker Compose部署应用
- 负责将多个比较小的服务互相协同起来组成一个完整可用的应用
- 使用一个声明式的配置文件描述整个应用,从而使用一条命令完成部署,部署成功后,还可以通过一系列简单的命令实现对其完整生命周期的管理,甚至,配置文件还可以置于版本控制系统中进行存储和管理
-
Compose文件
:可以使用JSON
文件,也可以使用JSON
的子集YAML文件
-
version
必须指定,且总是位于文件的第一行。它定义了Compose文件的格式
(主要是API
)的版本,version
并非是Docker Compose
的版本号 -
services
用于定义不同的应用服务- 下面的
key
定义服务名-
build .
:指定Docker
基于当前目录(.
)下的Dockerfile
构建镜像,此镜像用于启动该服务的容器 -
command
:指定Docker
在容器中运行的程序 -
ports
:容器内的(-target
)端口映射到主机(published
)的端口 -
networks
:将服务连接到指定的网络上。这个网络应该是已经存在的,或者在networks
一级key
中定义的网络 -
volumes
:指定Docker
将source
挂载到target
上,source
指定的卷应该是已存在的,或者在volumes
一级key
中定义
-
- 下面的
-
networks
用于指引Docker
创建新的网络,默认情况下,会创建bridge
网络。- 这是一个单主机网络,只能实现同一主机上容器的连接
- 可以使用
driver
属性指定不同的网络类型
-
-
Docker Compose
部署命令-
docker-compose up
-
&
:将终端窗口返回,日志输出到终端 -
-d
:后台运行 -
docker-compose -f you_configure.yaml up
:指定Compose文件
,默认使用的是docker-compose.yml
或者docker-compose.yaml
-
Docker Compose
会将项目名称和Compose文件
中定义的资源名称连起来,作为新构建的镜像名称;每个容器的名称都以项目名称(所在目录名称)为前缀,此外,还都以一个数字为后缀用于标识容器的实例序号 - 第一次部署,
Docker Compose
会检查是否有同名的卷存在,如果不存在,就会创建它 -
Docker主机
对卷中文件的修改,会立即反应到应用中
-
-
docker-compose down
:停止和关闭应用,应用被删除,仅留下镜像、卷和源码 -
docker-compose top
:列出各个服务(容器)内运行的进程 -
docker-compose stop
:停止应用,但不会删除资源 -
docker-compose rm
:对于已停止应用,用rm
删除 -
docker-compose ps
:列出Compose应用
中的各个容器 -
docker-compose restart
:重启已停止的Compose应用
-
Docker Swarm
-
Docker Swarm
主要包含两方面:- 企业级的
Docker
安全集群 - 微服务应用编排引擎
- 企业级的
- 集群方面
-
Swarm
将一个或多个Docker
节点组织起来,可以用集群的方式管理它们 - 默认内置有加密的分布式集群存储、加密网络、公用
TLS
、安全集群接入令牌以及一套简化数字证书管理的PKI
(public key infrastructure
) - 可以自如地添加删除节点
-
- 编排方面
-
Swarm
提供一套丰富的API
使得部署和管理复杂的微服务应用变得易如反掌 - 通过将应用定义在声明式配置文件中,就可以使用原生的
Docker命令
完成部署 - 可以执行滚动升级、回滚以及扩缩容操作
-
-
Swarm
集群- 唯一前提:所有节点通过可靠的网络相连
- 节点属性
- 管理节点(
Manager
) - 工作节点(
Worker
)
- 管理节点(
-
Swarm
的配置和状态信息- 保存在一套位于所有管理节点上的分布式
etcd
数据库中 -
Swarm
内置etcd
数据库,无需管理 -
etcd
数据库运行于内存中,并保持数据的最新状态
- 保存在一套位于所有管理节点上的分布式
-
Swarm
安全性-
Swarm
集成TLS
保证集群安全性 - 使用
TLS
进行通信加密、节点认证和角色授权 - 自动密钥轮换(
Automatic Key Rotation
)在后台默默运行
-
-
Swarm
应用编排-
Swarm
最小调度单元是服务- 服务在
API
中是一个新的对象元素,它基于容器封装了一些高级特性,是一个更高层次的概念 - 当容器被封装在一个服务中时,我们称之为一个任务或一个副本
- 服务中增加了诸如扩缩容、滚动升级以及简单回滚等特性
- 服务在
-
- 搭建安全
Swarm
集群- 要求
- 每个节点都需要安装
Docker
,并且能够与Swarm
的其他节点通信 - 网络方面,需要在路由器和防火墙中开放如下端口
-
2377/tcp
:用于客户端与Swarm
进行安全通信(2377端口
可配置,但是这是一个约定成俗的端口配置,最好不要改) -
7946/tcp
与7946/udp
:用于控制gossip分发
-
4789/udp
:用于基于VXLAN
的覆盖网络
-
- 每个节点都需要安装
- 大体流程
- 初始化第一个管理节点
- 加入额外的管理节点
- 加入工作节点
- 完成
- 初始化一个全新的
Swarm
- 不包含在任何
Swarm
中的Docker节点
,称为运行于单引擎(Single-Engine)模式
。- 一旦被加入
Swarm集群
,则切换为Swarm模式
- 单引擎模式下,运行
docker swarm init
会将其切换到Swarm模式
,并创建一个新的Swarm
,将自身设置为Swarm
的第一个管理节点
- 一旦被加入
-
docker swarm init --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377
-
docker swarm init
:通知Docker
来初始化一个新的Swarm
,并将自身设置为第一个管理节点,开启Swarm模式
-
--advertise-addr
:指定其他节点用来连接到当前管理节点的IP
和端口 -
--listen-addr
:指定用于承载Swarm流量
的IP
和端口。建议总是和--advertise-addr
一起使用
-
-
docker node ls
:列出Swarm
中的所有节点 - 添加工作节点与管理节点
- 在第一个管理节点上执行
-
docker swarm join-token worker
:获取工作节点接入命令中的Token
-
docker swarm join-token manager
:获取管理节点接入命令中的Token
- 一个节点是作为工作节点加入还是管理节点加入完全依赖于使用的
Token
-
- 登录到要加入的节点
docker swarm join --token 工作节点/管理节点Token 10.0.0.1:2377 --advertise-addr 10.0.0.4:2377 --listen-addr 10.0.0.4:2377
- 在第一个管理节点上执行
-
docker node ls
:在管理节点上执行,列出Swarm节点
-
MANAGER STATUS
无任何显示的是工作节点,显示Leader
的是主节点
-
- 不包含在任何
-
Swarm
管理器高可用性(HA
)-
HA支持
:一个或多个节点发生故障,剩余管理节点也会继续保证Swarm
的运转 -
Swarm
实现了一种主从方式的多管理节点HA
(有多个管理节点,但也总是仅有一个节点处于活动状态,通常处于活动状态的管理节点被称为“主节点”) - 主节点是唯一一个会对
Swarm
发送控制命令的节点,只有主节点才会变更配置,或发送任务到工作节点- 命令从一个远程
Docker
客户端发送给一个管理节点 - 如果接收到命令的管理节点非节点,则将命令转发给主节点
- 主节点对
Swarm
执行命令
- 命令从一个远程
- 管理节点或是
Leader
或是Follower
Raft术语
-
Swarm
使用了Raft共识算法
- 最佳实践原则
- 部署奇数个管理节点
- 有利于减少脑裂(这里解释有点奇怪)
- 不要部署太多的管理节点
-
对于共识算法来说,更多的参与节点就意味着需要花费更多的时间来达成共识。也就是我要在更多个管理节点上同步状态信息,保证主节点宕机后,
Follower
能够接替主节点的工作 - 管理节点之间一定要确保高速可靠的网络连接
-
对于共识算法来说,更多的参与节点就意味着需要花费更多的时间来达成共识。也就是我要在更多个管理节点上同步状态信息,保证主节点宕机后,
- 部署奇数个管理节点
- 内置的
Swarm
安全机制- 提供了开箱即用的合理的默认配置
-
CA
设置、接入Token
、公用TLS
、加密集群存储、加密网络、加密节点ID
- 锁定
Swarm
- 重启一个旧的管理节点或进行备份恢复仍有可能对集群造成影响
- 一个旧的管理节点重新接入
Swarm
会自动解密Raft数据库中长时间序列的访问权,这会带来安全隐患 - 进行备份恢复可能会抹掉最新的
Swarm
配置 -
Swarm
提供了自动锁机制来锁定Swarm
,这会强制要求重启的管理节点在提供一个集群解锁码之后才有权重新接入集群 docker swarm init --autolock=true
docker swarm update --autolock=true
- 上面两条命令可以开启自动锁,并得到解锁钥匙,解锁钥匙必须妥善保存在安全的地方
-
service docker restart
:重启一个管理节点 -
docker swarm unlock
:为重启的管理节点解锁Swarm
,提供解锁码
-
-
Swarm
服务docker service create --name web-fe -p 8080:8080 --replicas 5 yuq/docker-ci
-
docker service create
:声明一个新服务 -
--name web-fe
:命名为web-fe
-
-p 8080:8080
:将每个节点的8080端口
映射到服务副本内部的8080端口
-
--replicas 5
:告知Docker
应该总是有5个此服务的副本(容器) -
yuq/docker-ci
:告知Docker
镜像yuq/docker-ci
用于副本 - 所有的服务都会被
Swarm
持续监控——Swarm
在后台进行轮询检查- 如果某个副本宕机了,
Docker
会启动一个新的副本来是实际状态能够满足期望
- 如果某个副本宕机了,
-
docker service ps web-fe
:产看web-fe
服务副本列表及状态 -
docker service inspect --pretty web-fe
:查看更详细的信息,--pretty
限制输出仅包含最感兴趣的内容 - 副本服务vs全局服务
- 服务的默认复制模式是副本模式
- 部署期望数量的服务副本,并尽可能均匀地将各个副本分布在整个集群中
- 全局模式
docker service create --mode global
- 每个节点上仅运行一个副本
- 服务的默认复制模式是副本模式
- 服务的扩缩容
-
docker service scale web-fe=10
:服务器副本数量从5个加到10个 -
Swarm
实现一个调度算法,默认将副本尽可能均衡分配给Swarm
中的所有节点
-
- 删除服务
docker service rm web-fe
- 谨慎使用删除,删除所有副本时并不会进行确认
docker service ls
- 滚动升级
- 先创建一个覆盖网络给服务使用:
docker network create -d overlay uber-net
- 覆盖网络是一个二层网络,容器可以接入该网络,并且所有接入的容器均可互相通信
- 覆盖网络是创建于底层异构网络之上的一个新的二层容器网络
- 创建一个新的服务接入
uber-net
网络docker service create --name uber-svc --network uber-net -p 80:80 --replicas 12 yuq/tu-demo:v1
-
-p 80:80
:会建立Swarm集群范围的网络流量映射,到达Swarm任何节点80端口的流量,都会映射到任何服务副本的内部80端口 - 默认的模式是在
Swarm
中的所有节点开放端口——即使节点上没有服务的副本——称为入站模式 - 主机模式:仅在运行有容器副本的节点上开放端口
- 打开主机模式:
docker service create --name uber-svc --network uber-net --publish published=80,target=80,mode=host --replicas 12 yuq/tu-demo:v1
- 升级服务
-
docker service update --image yuq/tu-demo:v2 --update-parallelism 2 --update-delay 20s uber-svc
-
--update-parallelism
:每次使用新镜像更新几个副本 -
--update-delay
:每次更新与上一次之间的延迟时间
-
-
- 先创建一个覆盖网络给服务使用:
- 故障排除
-
docker service logs
:查看log
- 默认使用
json-file
日志驱动 - 其他还有
journald
、syslog
、splunk
、gelf
- 默认使用
- 可在
daemon.json
中配置日志驱动"log-driver":"syslog"
-
docker service create
命令时传入--logdriver
和--log-opts
参数可以强制某服务使用一个不同的日志驱动,这会覆盖daemon.json
中的配置
-
- 要求
Docker网络
-
CNM
- 容器网络模型(Container Network Model)(设计标准,规定
Docker
网络架构的基础组成要素) - 定义3个基本要素:沙盒(
Sandbox
)、终端(Endpoint
)、网络(Network
) - 沙盒(独立的网络栈)被放置在容器内部,容器中的接口(终端,虚拟网络接口)连接到网络(
802.1d网桥
)上,同一网络上的容器相互之间可以通信 - 同一份容器可以有多个终端,分别可以连接到不同的网络(一个终端只能接入某一个网络),同一个容器中的多个终端需要三层路由器的支持才能通信
- 如果容器需要接入到多个网络,就需要多个终端
- 容器网络模型(Container Network Model)(设计标准,规定
-
Libnetwork
-
CNM
的具体实现(Go语言
编写) - 实现了
CNM
定义的三个基本组件,还实现了本地服务发现、基于Ingress
的容器负载均衡,以及网络控制层和管理层功能
-
- 驱动
- 通过实现特定网络拓扑的方式来拓展该模型的能力
- 如果说
Libnetwork
实现了控制层和管理层的功能,那么驱动就负责实现数据层 - 网络的连通性和隔离性是由驱动来处理的
-
Docker
封装的内置驱动(原生驱动或者本地驱动)-
Linux
:Bridge
、Overlay
、Macvlan
-
Windows
:NAT
、Overlay
、Transport
、L2Bridge
-
-
Docker
也可以使用第三方网络驱动(远程驱动) -
Libnetwork
支持同时激活多个网络驱动。Docker
环境支持一个庞大的异构网络
- 单机桥接网络
- 单机:只能在单个
Docker主机
上运行,并只能与所在的Docker主机
上的容器进行连接 - 桥接:
802.1d
桥接的一种实现(二层交换机) - 每一个
Docker主机
都有一个默认的单机桥接网络,Linux
上网络名称为bridge
,windows
上为nat
- 可以使用标准
Linux
工具来查看bridge
网络ip link show docker0
- 接在相同网络中的容器之间可以通过容器名(新容器都注册了指定的
Docker DNS服务
)ping
通(默认的Bridge
网络不支持,自定义桥接网络可以) - 可以使用端口映射来绕开“桥接网络中的容器只能与位于相同网络中的容器进行通信”的限制
- 端口数有限制,所以单机桥接网络只适合本地开发环境以及非常小的应用
- 单机:只能在单个
- 多机覆盖网络
- 允许单个网络包含多个主机,不同主机上的容器间就可以在链路层实现通信
- 只要在
docker network create
命令中加入-d overlay
参数
- 接入现有网络
- 例如应用中已经容器化的部分需要与那些运行在物理网络和
VLAN
上未容器化部分进行通信 -
Docker
内置的Macvlan
驱动(windows
中为Transparent
) - 通过为容器提供
MAC和IP地址
- 优点:
Macvlan
性能优异,因为无需端口映射或者额外桥接,可以直接通过主机接口(或者子接口)访问容器接口 - 缺点:需要将主机网卡(
NIC
)设置为混杂模式,这在大部分公有云平台上是不允许的
- 例如应用中已经容器化的部分需要与那些运行在物理网络和
- 服务发现
- 允许容器和
Swarm服务
通过名称相互定位,唯一的要求是需要位于同一个网络中 - 底层实现利用
Docker
内置的DNS服务器
,为每个容器提供DNS解析
功能 - 可以自定义
DNS配置
(Linux
上,自定义操作会在容器内部的/etc/resolve.conf
中增加条目)-
--dns
:指定自定义的DNS列表
-
--dns-search
:指定自定义查询时所使用的域名
-
- 允许容器和
-
Ingress
网络-
Swarm
支持两种服务发布模式,均保证服务从集群外可以访问-
Ingress
模式(默认)- 保证集群内的任一节点都能访问该服务
- 采用
Service Mesh
或者Swarm Mode Service Mesh
的四层路由网络来实现
-
Host
模式- 只能通过运行服务副本的节点来访问
--publish published=5000,target=80,mode=host
-
-
- 基本命令
docker network ls
-
docker network inspect bridge
:查看bridge网络
的详细信息 -
docker port name
:查看端口映射 -
docker network prune
:删除Docker
主机上全部未使用的网络 -
docker network rm
:删除Docker
主机上指定网络 docker network create
Docker覆盖网络
-
Swarm模式
下构建及测试Docker
覆盖网络- 构建
Swarm
,初始化管理节点,以及加入工作节点 - 创建一个新的覆盖网络
uber-net
:docker network create -d overlay uber-net
- 能连接
Swarm
所有主机 - 包括了一个
TLS
加密控制层 - 如果相对数据层加密,添加
-o encrypted
- 只有当运行中的容器连接到覆盖网络的时候,该网络才变为可用状态。这种延迟生效策略通过减少网络梳理,提升了网络的扩展性(这句看不太明白~)
- 能连接
- 将服务连接到覆盖网络
docker service create --name test --network uber-net --replicas 2 ubuntu sleep infinity
- 创建一个名为
test
的服务,连接到了uber-net
这个覆盖网络,并且指定ubuntu镜像
创建两个副本(容器),采用sleep命令
保持容器运行
- 测试覆盖网络
docker network inspect uber-net
docker container inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' your_container_id
- 查看被分配给覆盖网络的
Subnet
(两个需要ping
的容器上分别运行,得到容器ID
和IP地址
) - 安装
ubuntu
上的ping
工具包:iputils-ping
- 跟踪路由:
traceroute
- 构建
- 工作原理
-
VXLAN
入门-
VXLAN隧道技术
:创建虚拟二层覆盖网络 - 优点:是一种封装技术,能使现存的路由器和网络架构看起来就像普通的
IP/UDP
包一样 - 为了创建二层网络,
VXLAN
基于现有的三层IP
网络创建了隧道。基础网络:三层之下的基础部分 -
VXLAN隧道
两端都是VXLAN
隧道终端(VXLAN Tunnel Endpoint
,VTEP
)。VTEP
完成了封装和解压的步骤
-
- 两个容器示例
- 每台主机上都有一个
Sandbox
(网络命名空间):当前主机上独立的网络栈-
Sandbox
内部创建了一个名为Br0
的虚拟交换机(虚拟网桥),同时还创建了一个VTEP
,VTEP
的一端接入到Br0
,另一端接入主机网络栈
-
- 在主机网络栈中的
VTEP
(终端)从主机所连的基础网络中获取到IP地址,并以UDP Socket的方式绑定到4789端口 - 不同主机上的两个
VTEP
通过VXLAN隧道
创建了一个覆盖网络 - 每个容器都有自己的虚拟以太网(
veth
)适配器,并接入本地Br0
虚拟交换机
- 每台主机上都有一个
- 通信示例——
node1
上的C1
到连接node2
上的C2
-
C1
发起ping请求
,目标IP
为C2
的地址10.0.0.4
(非实际网络ip
)。 - 请求的流量通过连接到
Br0虚拟交换机
的veth接口
发出- 虚拟交换机并不知道要将包发送到哪里,所以
Br0
将包发送到其上的全部端口 - 连接到
Br0
的VETP接口
知道如何转发这个数据帧,所以将自己的MAC地址
返回(代理ARP响应
) -
Br0
更新自己的ARP映射表
,将10.0.0.4
映射到本地VTEP
的MAC地址
上
- 虚拟交换机并不知道要将包发送到哪里,所以
-
Br0
将目标为C2
的流量转发到VTEP接口
-
VTEP
知道C2
,因为所有新启动的容器都会将自己的网络详情采用网络内置的Gossip协议
发送给相同Swarm集群
内的其他节点
-
-
VTEP
完成数据帧的封装,也就是把VXLAN Header
信息添加到以太网帧当中-
VXLAN Header
信息包含VXLAN
网络ID
(VNID
),其作用是记录VLAN
(这个VLAN
具体是啥?)到VXLAN
的映射关系 - 将数据帧放到
UDP包
中,并设置UDP
的目的IP字段
为node2
节点的VTE
P的IP地址
,同时设置UDP Socket
端口为4789
-
- 当包到达
node2
,内核将包发给合适的VTEP
,有VTEP
读取VNID
,解压包信息 - 根据
VNID
将包发送到本地名为Br0
并且连接到VLAN
的交换机 - 在交换机上,包被发送给
C2
-
-
Docker
支持使用同样的覆盖网络实现三层路由- 可以创建包含两个子网的覆盖网络,
Docker
会负责子网间的路由 docker network create --subnet=10.1.1.0/24 --subnet=11.1.1.0/24 -d overlay prod-net
- 该命令会在
sandbox
中创建两个虚拟交换机,默认支持路由
- 可以创建包含两个子网的覆盖网络,
-
卷与持久化数据
- 非持久化数据
- 自动创建,从属于容器,生命周期与容器相同。——容器擅长无状态和非持久化事务
- 删除容器也会删除全部非持久化数据
- 持久化数据
- 将数据存储在卷上,删除一个关联卷的容器,卷并不会删除
- 卷与容器是解耦的,从而可以独立的创建和管理卷,并且卷并未与任意容器生命周期绑定
- 容器与持久化数据
- 用户创建卷,然后创建容器,接着将卷挂载到容器上。卷会挂载载容器的某个目录之下,任何写到该目录下的内容都会写到卷中。即使容器被删除,卷与其上面的数据仍然存在
-
docker volumn create myvol
:创建名为myvol
的卷- 默认情况下,新卷采用内置的
local驱动
,本地卷只能被所在节点的容器使用 - 第三方驱动可以通过插件的方式,为
Docker
集成外部存储系统- 块存储:相对性能更高,适用于对小块数据的随机访问负载
- 文件存储:包括NFS和SMB协议的系统,在高性能场景下表现优异
- 对象存储:适用于较大且长期存储的、很少变更的二进制数据存储。通常对象存储是根据内容寻址,并且性能较低
- 也可以使用
Dockfile
部署卷,VOLUMN
- 默认情况下,新卷采用内置的
-
docker container run -dit --name voltainer --mount source=bizvol,target=/vol alpine
- 挂载了一个名为
bizvol
的卷,如果系统中没有这个卷,则Docker
会自动创建一个卷 docker service create --name hellcat --mount source=bizvol,target=/vol alpine sleep 1d
- 挂载了一个名为
- 在集群节点间共享存储
-
Docker
能够集成外部存储系统,使得集群间节点共享外部存储数据变得简单 - 独立存储
LUN
或者NFS
共享可以应用到多个Docker
主机,无论容器或者服务副本运行在那个节点上,都可以共享该存储 - 共享存储需要注意数据损坏(Data Corruption)
- 也就是多个容器同时写入,或者某个容器写入到缓存中,还没更新到共享存储,另一个容器在这期间更新的文件,那么当将缓存中的内容更新到文件中时,另一个容器对此一无所知
-
- 常用命令
docker volumn ls
docker volumn inspect myvol(卷名)
-
docker volumn prune
:会删除未装入到某个容器或者服务的所有卷 -
docker volumn rm
:删除指定卷(不能删除正在被容器或服务使用的卷)
使用Docker Stack部署应用
-
Stack
能够在单个声明文件中定义复杂的多服务应用 - 提供简单的方式来部署应用并管理其完整的生命周期
- 初始化部署、健康检查、扩容、更新、回滚
- 在
Compose文件
中定义应用,然后通过docker stack deploy
命令完成部署和管理 -
Stack
基于Docker Swarm
之上来完成应用的部署 -
Docker
适用于开发和测试,Docker Stack
适用于大规模场景和生产 -
Stack
部署文件(例如docker-stack.yml
)-
version
:Compose
文件格式的版本号,Stack
需要3.0或者更高版本
-
services
:定义组成当前应用的服务-
image
:指定用于构建服务的镜像,与Docker Compose
的一个区别是,Stack不支持构建,在部署之前,所有镜像必须提前构建完成 -
ports
:定义端口映射- 默认采用
Ingress
模式,Swarm集群
中的每个节点对应的端口都会映射并且是可访问的 - 也可以手动设置为
Host模式
- 默认采用
-
secret
:定义服务需要用到的密钥,密钥必须被顶级关键字secrets
定义,并且必须在系统上已经存在- 密钥以普通文件的形式挂载到服务副本中
-
networks
:确保服务所有副本连接到指定网络上(如果网络不存在,自动创建) -
environment
:允许在服务副本中注入环境变量 -
deploy
:部署-
placemnet:contraints
: 约束- 节点
ID
,如node.id==o2p4kw2uuw2a(id)
- 节点名称,如
node.hostname==wrk-12
- 节点角色,如
node.role!=manager
- 节点引擎标签,如
engine.labels.operatingsystem==ubuntu16.04
- 节点自定义标签,如
node.labels.zone==prod1
- 节点
- 副本数量:
replicas=2
-
update_config
:定义Docker
滚动升级的时候具体如何操作-
parallelisem:2
:每次更新两个副本
-
-
failure_action
:升级失败后的策略-
pause
:(默认)阻止其他副本升级 -
continue
:继续 -
rollback
:自动回滚
-
-
restart-policy
:定义Swarm
针对容器异常退出的重启策略-
condition:onfailure
:某副本以非零返回值退出,立即重启该副本 -
max_attempts
:最多重试次数 -
window
:每次检测是否启动成功最长等待时间 -
delay
:每次重启间隔时间
-
-
-
stop_grace_period
:设置优雅停止(发送停止信号后,有一段时间处理后事)时间 -
volumns
:挂在提前创建的卷或者主机目录到某个服务副本当中-
/var/run/docker.sock
是Docker
提供的IPC套接字
,Docker daemon
通过该套接字对其他进程暴露其API
终端,可以通过该文件管理Docker daemon
-
-
-
networks
:列出必须的网络- 部署时,首先检查并创建networks:关键字对应的网络
- 默认网络采用
overlay驱动
,控制层加密 - 如果需要加密数字层(需要额外的开销)
-
docker network create
命令中指定-o encrypted
参数 - 在
Stack
文件中的driver_opts
之下指定encrypted:'yes'
-
-
secrets
:定义用到的密钥- 如果密钥被定义为
external
,则在Stack
部署之前,这些密钥必须存在
- 如果密钥被定义为
- 所有变更都应该通过Stack文件进行声明,然后通过
docker stack deploy
进行部署 - 常用命令
docker stack deploy
docker stack ls
docker stack ps
docker stack rm
-
Docker安全
-
Linux
安全技术-
Namespace
- 该技术将操作系统进行拆分,是一个操作系统看起来像多个互相独立的操作系统一样
- 用于隔离不同容器
-
Docker
容器是由各种命名空间组成的,Docker容器本质就是命名空间的有组织集合- 进程
ID
(PID
):为每个容器提供互相独立的容器进程树 - 网络(
NET
):提供互相隔离的网络栈 - 文件系统/挂载(
MNT
):每个容器都有互相隔离的根目录/
- 进程内通信(
IPC
):在容器内提供共享内存,共享内存载不同容器间也是互相独立的 - 用户(
USER
):将容器内用户映射到Linux
主机的不同用户上(Docker
新生事物,非必选项) -
UTS
:为每个容器提供自己的主机名称
- 进程
-
Control Group
- 控制组用于限额
-
CGroup
允许用户设置限制,防止单个容器占用全部主机资源
-
Capability
- 选择容器运行所需的
root用户
权限(只取容器需要的权限,限制不需要的权限) -
Linux root
用户常见能力-
CAP_CHOWN
:允许用户修改文件所有权 -
CAP_NET_BIND_SERVICE
:允许用户将socket
绑定到系统的端口号 -
CAP_SETUID
:允许用户提升进程优先级 -
CAP_SYS_BOOT
:允许用户重启系统
-
-
capability
机制用来实现用户以root身份
运行容器的同时,还能移除非必须的root
能力
- 选择容器运行所需的
- 强制访问控制(
MAC
) - 安全计算(
Seccomp
)- 使用过滤模式下的
Secomp
来限制容器对宿主机内核发起的系统调用
- 使用过滤模式下的
-
-
Docker
平台安全技术-
Swarm模式
- 加密
节点ID
- 基于
TLS
的认证机制- 每个加入
Swarm
的节点都需要发布自己的客户端证书,证书用于双向认证 - 证书定义节点相关信息,包括从属的
Swarm集群
以及该节点载集群中的身份、证书更新周期 - 内容保存在
docker
内部的swarm-node.crt
文件中 - 使用
docker system info
查看信息
- 每个加入
- 安全准入令牌:向
Swarm
中加入管理者和工作者所需的唯一凭证(join-token
)- 管理者所需准入令牌
- 工作者所需准入令牌
- 令牌格式:
PREFIX - VERSION - SWARM ID - TOKEN
-
PREFIX
永远是“SWMTKN”
,所以允许通过正则表达式匹配该令牌 -
VERSION
展示了Swarm
的版本信息 -
SWARM ID
是Swarm
认证信息的一个哈希值 -
TOKEN
内容决定该令牌是管理者还是工作者的准入令牌
-
- 重设准入令牌:
docker swarm join-token --rotate manager
- 支持周期性证书自动更新的
CA配置
- 被配置为
Swarm集群
的第一个管理节点,也是根CA节点
-
docker swarm update --cert-expiry 720h
:更改证书更新周期 -
docker swarm ca
:可以用于管理CA配置
,--help
查看帮助
- 被配置为
- 加密集群存储(配置
DB
)-
Swarm
大脑,保存了集群配置和状态数据,默认加密 - 目前基于
etcd
的某种实现,并且会在Swarm
内所有管理者之间自动复制
-
- 加密网络
- 加密
-
Docker
安全扫描-
Docker
安全扫描对Docker镜像
进行二进制代码级别的扫描,对其中的软件根据已知缺陷数据库(CVE数据库
)进行检查
-
-
Docker
内容信任机制-
Docker Content Trust
,DCT
允许开发者对发布到Docker Hub
或者Docker可信服务
的镜像进行签名 - 当镜像被拉取时,会自动确认签名状态
-
DCT
一旦开启,将无法获取并使用未经签名的镜像
-
-
Docker
密钥-
docker secret
命令管理密钥 - 密钥使用总体流程
- 创建密钥,并发送到
Swarm
- 将密钥存放在集群存储当中,并且加密(管理节点可以访问集群存储)
-
B服务
创建,并且使用该密钥 - 密钥加密传输到B服务任务节点(容器)
-
B服务
的容器将密钥解密并挂在到路径/run/secrets
下,这是一个临时内存文件系统 - 一旦容器(服务任务)完成,内存文件系统关闭,密钥也随之删除
-
A服务
中的容器不能访问该密钥
- 创建密钥,并发送到
-
-
企业版工具及特性
-
Docker EE
企业版能够实现私有化部署 -
Docker EE
引擎 -
Docker
通用控制平面(UCP
)- 基于角色的权限控制(
RBAC
):UCP
通过一中称为授权(Grant
)的东西实现- 主体(
Subject
):一个或多个用户,或一个团队 - 角色(
Role
):一系列权限的组合 - 集合(
Collection
):权限作用的资源 - 授权:配置谁,对那些资源,拥有什么样的权限
- 主体(
- 集成活动目录
-
UCP
能够与活动目录及其他LDAP
目录服务进行集成,从而利用组织中现有的单点登录系统中的用户和组
-
- 基于角色的权限控制(
-
Docker
可信镜像仓库服务(DTR
)- 可配置为使用自签名证书或来自可信第三方
CA证书
- 可设置
DTR
来执行二进制级别的镜像扫描,检查镜像中的缺陷 - 基于构建流水线来配置自动化的镜像提升策略
- 可配置为使用自签名证书或来自可信第三方
-
HTTP路由网格
(HRM
)
Docker面试题
- 什么是虚拟化?
- 虚拟化允许您在相同的硬件上运行两个完全不同的操作系统。每个客户操作系统都经历了引导,加载内核等所有过程。
- 可以基于虚拟化方法如何模仿客户操作系统的硬件并模拟客户操作环境来对虚拟化方法进行分类。主要有三种类型的虚拟化:
- 仿真
- 半虚拟化
- 基于容器的虚拟化
- 什么是
Docker
?-
Docker
是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以确保您的应用程序在开发,测试或生产的任何环境中无缝运行。 -
Docker容器
,将一个软件包装在一个完整的文件系统中,该文件系统包含运行所需的一切:代码,运行时,系统工具,系统库等可以安装在服务器上的任何东西。 - 这可以保证软件始终运行相同,无论其环境如何。
-
- 什么是
-
Docker
与虚拟机有何不同?-
Docker
不是虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具。为此,Docker
最初使用LXC驱动程序
,然后移动到libcontainer
现在重命名为runc
。 -
Docker
主要专注于在应用程序容器内自动部署应用程序。应用程序容器旨在打包和运行单个服务,而系统容器则设计为运行多个进程,如虚拟机。因此,Docker
被视为容器化系统上的容器管理或应用程序部署工具。 - 与虚拟机不同,容器不需要引导操作系统内核,因此可以在不到一秒的时间内创建容器。
- 由于基于容器的虚拟化为主机增加了很少或没有开销,因此基于容器的虚拟化具有接近本机的性能
- 主机上的所有容器共享主机的调度程序,从而节省了额外资源的需求。
- 与虚拟机映像相比,容器状态(
Docker
或LXC映像
)的大小很小,因此容器映像很容易分发。 - 容器中的资源管理是通过
cgroup
实现的。CGroups
不允许容器消耗比分配给它们更多的资源。虽然主机的所有资源都在虚拟机中可见,但无法使用。
-
- 容器内部机制?
- 大约在2006年,包括Google的一些员工在内的人们实现了名为
命名空间
的新的Linux
内核级功能(不过这个想法早在FreeBSD
中就已存在)。操作系统的一个功能是允许将全局资源(如网络和磁盘)共享到进程。如果将这些全局资源包装在命名空间中,以使它们仅对在同一命名空间中运行的那些进程可见,该怎么办?比如说,你可以获得一大块磁盘并将其放在命名空间X
中,然后在命名空间Y
中运行的进程无法查看或访问它。类似地,名称空间X
中的进程无法访问分配给名称空间Y
的内存中的任何内容。当然,X
中的进程无法查看或与名称空间Y
中的进程通信。这为全局资源提供了一种虚拟化和隔离。 - 这就是
Docker
的工作原理:每个容器都在自己的命名空间中运行,但使用与所有其他容器完全相同的内核。发生隔离是因为内核知道分配给进程的命名空间,并且在API
调用期间确保进程只能访问其自己的命名空间中的资源。
- 大约在2006年,包括Google的一些员工在内的人们实现了名为
-
CI
(持续集成)服务器的功能是什么?-
CI
服务器功能是不断地集成所有正在进行的更改并由不同的开发人员提交到存储库,并检查编译错误。它需要每天多次构建代码,最好是在每次提交之后,以便它可以检测在问题发生时是哪个提交Bug
了。
-
- 如何使用
Docker
构建与环境无关的系统?- 有三个主要功能有助于实现这一目标:
Volumes
- 环境变量注入
- 只读文件系统
- 有三个主要功能有助于实现这一目标:
- 什么是
Docker镜像
?-
Docker镜像
用于创建容器。使用build
命令创建映像,并且在使用run
启动时它们将生成容器。 - 镜像存储在
Docker注册表``http://registry.hub.docker.com
中,因为它们可能变得非常大,镜像被设计为由其他镜像层组成,允许在通过网络传输镜像时发送最少量的数据。
-
- 什么是
Docker容器
?-
Docker容器
包括应用程序及其所有依赖项,但与其他容器共享内核,作为主机操作系统上用户空间中的独立进程运行。Docker容器
不依赖于任何特定的基础架构:它们可以在任何计算机,任何基础架构和任何云中运行。
-
- 什么是
Docker Hub
?-
Docker hub
是一个基于云的注册表服务,允许您链接到代码存储库,构建镜像并测试它们,存储手动推送的镜像以及指向Docker
云的链接,以便您可以将镜像部署到主机。它为整个开发流程中的容器镜像发现,分发和变更管理,用户和团队协作以及工作流自动化提供了集中资源。
-
-
Docker容器
有几种状态?-
Docker容器
可以有四种状态:- 运行
- 已暂停
- 重新启动
- 已退出
- 我们可以通过运行命令来识别
Docker容器
的状态:docker ps –a
- 这将依次列出所有可用的
docker容器
及其在主机上的相应状态。从那里我们可以很容易地识别感兴趣的容器,以相应地检查其状态。
- 这将依次列出所有可用的
-
-
Docker
适合什么类型的应用程序 - 无状态或有状态更适合Docker容器
?- 最好为
Docker Container
创建无状态应用程序。我们可以从应用程序中创建一个容器,并从应用程序中取出可配置的状态参数。现在我们可以在生产和具有不同参数的QA环境中运行相同的容器。这有助于在不同场景中重用相同的image。使用Docker Containers
比使用有状态应用程序更容易扩展无状态应用程序。
- 最好为
- 解释基本的
Docker
使用流程- 一切都从
Dockerfile
开始。Dockerfile
是镜像的源代码(这解释合理吗?我觉得更像是Makefile或者CMake脚本)。 - 创建
Dockerfile
后,您可以构建它以创建容器的镜像。镜像只是“源代码”的“编译版本”,即Dockerfile
。 - 获得容器的镜像后,应使用注册表重新分发容器。注册表就像一个
git
存储库 - 你可以推送和拉取镜像。 - 接下来,您可以使用该镜像来运行容器。在许多方面,正在运行的容器与虚拟机(但没有管理程序)非常相似。
- 一切都从
-
Dockerfile
中最常见的指令是什么?-
Dockerfile
中的一些常用指令如下:-
FROM
:我们使用FROM
为后续指令设置基本镜像。在每个有效的Dockerfile
中,FROM
是第一条指令。 -
LABEL
:我们使用LABEL
按照项目,模块,许可等组织我们的镜像。我们也可以使用LABEL
来帮助实现自动化。在LABEL
中,我们指定一个键值对,以后可用于以编程方式处理Dockerfile
。 -
RUN
:我们使用RUN
命令在当前镜像之上的新图层中执行任何指令。使用每个RUN
命令,我们在镜像顶部添加一些内容,并在Dockerfile
的后续步骤中使用它。 -
CMD
:我们使用CMD
命令提供执行容器的默认值。在Dockerfile
中,如果我们包含多个CMD
命令,则只使用最后一条指令。
-
-
-
Dockerfile
中的命令COPY
和ADD
命令有什么区别?- 一般而言,虽然
ADD
并且COPY
在功能上类似,但是COPY
是优选的。 - 那是因为它比
ADD
更透明。COPY
仅支持将本地文件基本复制到容器中,而ADD
具有一些功能(如仅限本地的tar提取
和远程URL
支持),这些功能并不是很明显。因此,ADD
的最佳用途是将本地tar
文件自动提取到镜像中,如ADD rootfs.tar.xz /
中所示。
- 一般而言,虽然
- 解释一下
dockerfile
的ONBUILD
指令?- 当镜像用作另一个镜像构建的基础时,
ONBUILD指令
向镜像添加将在稍后执行的触发指令。如果要构建将用作构建其他镜像的基础的镜像(例如,可以使用特定于用户的配置自定义的应用程序构建环境或守护程序),这将非常有用。
- 当镜像用作另一个镜像构建的基础时,
-
Docker镜像
和层有什么区别?我觉得应该是:镜像是一个配置信息,内部是一个使用的层的列表以及一些元信息,而层存储实际的内容
-
镜像:
Docker镜像
是由一系列只读层构建的- 层:每个层代表镜像
Dockerfile
中的一条指令(不对吧,有些指令不会创建层,只会加入元信息)。
- 层:每个层代表镜像
-
下面的Dockerfile包含四个命令,每个命令都创建一个层。
FROM ubuntu:15.04 COPY . /app RUN make /app CMD python /app/app.py
重要的是,每个层只是与之前一层的一组差异层(相同的就不再放到新层中)。
- 什么是
Docker Swarm
?-
Docker Swarm
是Docker
的本机群集。它将Docker
主机池转变为单个虚拟Docker
主机。Docker Swarm
提供标准的Docker API
,任何已经与Docker
守护进程通信的工具都可以使用Swarm
透明地扩展到多个主机。
-
- 如何在生产中监控
Docker
?-
Docker
提供docker stats
和docker事件
等工具来监控生产中的Docker
。我们可以使用这些命令获取重要统计数据的报告。 -
Docker
统计数据:当我们使用容器ID
调用docker stats
时,我们获得容器的CPU
,内存使用情况等。它类似于Linux
中的top
命令。 -
Docker事件
:Docker事件
是一个命令,用于查看Docker
守护程序中正在进行的活动流。- 一些常见的
Docker事件
是:attach
,commit
,die
,detach
,rename
,destroy
等。我们还可以使用各种选项来限制或过滤我们感兴趣的事件。
- 一些常见的
-
-
Docker
如何在非Linux系统
中运行容器?- 通过添加到
Linux内核版本2.6.24
的名称空间功能,可以实现容器的概念。容器将其ID添加到每个进程,并向每个系统调用添加新的访问控制检查。它由clone()
系统调用访问,该调用允许创建先前全局命名空间的单独实例。 - 如果由于
Linux内核
中可用的功能而可以使用容器,那么显而易见的问题是非Linux系统
如何运行容器。Docker for Mac
和Windows
都使用Linux VM
来运行容器(window好像默认不是linux了吧)。Docker Toolbox
用于在Virtual Box VM
中运行容器。但是,最新的Docker
在Windows
中使用Hyper-V
,在Mac
中使用Hypervisor.framework
。
- 通过添加到
- 如何在多个环境中使用
Docker
?- 可以进行以下更改:
- 删除应用程序代码的任何卷绑定,以便代码保留在容器内,不能从外部更改
- 绑定到主机上的不同端口
- 以不同方式设置环境变量(例如,减少日志记录的详细程度,或启用电子邮件发送)
- 指定重启策略(例如,重启:始终)以避免停机
- 添加额外服务(例如,日志聚合器)
- 因此,您可能希望定义一个额外的
Compose
文件,例如production.yml
,它指定适合生产的配置。此配置文件只需要包含您要从原始Compose
文件中进行的更改。
- 为什么
Docker Compose
不会等待容器准备就绪,然后继续以依赖顺序启动下一个服务?-
Compose
按照依赖顺服启动和停止容器,决定依赖关系语句有depends_on
,links
,volumes_from
, 和network_mode: "service:..."
. - 但是,对于启动,
Compose
不会等到容器“准备好它运行“。这里有一个很好的理由:- 等待数据库(例如)准备就绪的问题实际上只是分布式系统更大问题的一个子集。在生产中,您的数据库可能随时变得不可用或移动主机。您的应用程序需要能够适应这些类型的故障。
- 要处理此问题,请将应用程序设计为在发生故障后尝试重新建立与数据库的连接。如果应用程序重试连接,它最终可以连接到数据库。
- 最佳解决方案是在启动时以及出于任何原因丢失连接时,在应用程序代码中执行此检查
-