一、简介
Docker是PASS【Platform As A Service】提供商dotCloud开源的一个基于LXC【Linux Container】的高级容器引擎,源代码托管在Github上。基于go语言并遵从Apache2.0协议开源
Docker的主要目标是“Build and Run Any App, Anywhere“,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP及其运行环境能够做到**“一次封装,到处运行”**。
传统的开发部署协作方式

Docker的开发部署协作方式

二、虚拟化技术
虚拟机技术

虚拟机 (VM) 是一个物理硬件层抽象,用于将一台服务器变成多台服务器。管理程序允许多个 VM 在一台机器上运行。每个 VM 都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此占用大量空间。而且 VM 启动也十分缓慢。
容器虚拟化技术

容器是一个应用层抽象,用于将代码和依赖资源打包在一起。多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行。与虚拟机相比,容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动。
三、Docker三要素
镜像(Image)
镜像就是一个只读模板。镜像可以用来创建Docker容器,一个镜像可以创建多个容器。
容器(Container)
Docker利用容器独立运行一个或一组应用。容器是镜像创建的运行示例。它可以被启动、停止、删除。每个容器都是相互隔离的、保证安全的平台。
仓库(Repository)
仓库是集中存放镜像文件的场所。仓库和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库又包含了多个镜像,每个镜像又不同的标签(tag)。
注:Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包形成一个可交付的运行环境,这个打包好的运行环境就是镜像文件。只有通过这个镜像文件才能生成Docker容器。镜像文件可以看作是容器的模板。Docker根据镜像文件生成容器的实例。同一个镜像文件,可以生成多个同时运行的容器实例。
四、YUM安装Docker
第一步:卸载原Docker组件,确认安装了gcc、gcc-c++
| |
第二步:安装Docker仓库
| |
第三步:更新、安装、开启Docker服务
| |
第四步:配置镜像加速器
| |
第五步:运行hello-world镜像验证是否安装成功
| |
五、命令
帮助命令
- 查看版本信息 docker version
- 查看详细信息 docker info
- 查看命令帮助 docker –help
镜像命令
列出镜像 docker images
参数 描述 -a 列出本地主机上的镜像(包括中间层镜像) -q 列出本地主机上的镜像ID 搜索镜像
docker search [镜像名]
参数 描述 –filter=stars=3 列出点赞数不小于指定值的镜像 –no-trunc 显示完整镜像描述 拉取/删除镜像
docker pull/rmi [镜像名]:[Tag]
小技巧:docker rmi -f $(docker images -qa) 删除所有镜像
提交容器作为镜像
docker -a=“作者名” -m=“描述信息” commit [容器ID] 名称:Tag标签
保存【导出】镜像
docker save [镜像名]:[Tag] -o /path/[name].tar
加载镜像
docker load -i [name].tar
容器命令
运行容器命令 docker run [镜像名]:[Tag]
参数 描述 -i 以交互模式运行容器,通常与-t同时使用 -t 为容器重新分配一个伪输入终端,通常与-i同时使用 -p 指定映射端口,形式hostPort:ContainerPort -P 随机端口映射 -d 后台运行容器 –name 为容器指定名称 –restart=always docker服务启动容器就启动 -h name 设置主机名 –add-host name:ip 注入hostname的IP解析 –rm 容器停止时自动删除 –link cname:hostName 向容器的/etc/hosts添加另一个IP地址的映射形式 退出容器方法
- exit 容器停止退出
- ctrl+p+q 容器不停止退出
查看容器进程 docker ps
参数 描述 -l 上次运行的容器 -a 所有运行过的容器 -q 静默只显示容器编号 启动/重启/停止容器
docker start/restart/stop [容器ID]
强制停止容器
docker kill [容器ID]
删除关闭的容器
docker rm [容器ID]
参数 描述 -f 强制删除 小技巧:docker rm -f $(docker ps -qa) 删除所有容器
查看容器日志 docker logs [容器ID]
参数 描述 -f 一直追加,显示最新日志 -t 显示每条日志时间戳 查看容器运行进程信息
docker top [容器ID]
查看容器内部细节
docker inspect [容器ID]
查看容器占用的系统资源
docker stats [容器ID]
不加容器ID则查看所有容器的系统资源
重新进入容器
docker attach [容器ID]
进入容器执行Shell命令
docker exec -it [容器id Shell命令]
拷贝容器内文件
docker cp [容器ID]:容器路径 本机路径
容器运行机制
Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是会挂起的命令(比如top),会自动退出。最佳的解决方案是,将要运行的程序以前台进程的形式运行
六、Docker Compose
Docker Compose是容器编排工具,允许用户在一个模板(YAML格式)中定义一组相关联的容器,对启动的优先级进行排序。
| 命令 | 解释 |
|---|---|
| -f | 指定YAML文件位置 |
| ps | 显示容器所有信息 |
| start/stop/restart | 启动/停止/重启容器【已加载成为容器】 |
| logs | 查看日志信息 |
| config -q | 验证YAML是否正确 |
| up -d | 启动容器项目【未加载成为容器】 |
| pause | 暂停容器 |
| unpause | 恢复暂停 |
| rm | 删除容器 |
简单示例:
| |
七、镜像加载原理
UnionFS 联合文件系统
联合文件系统是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层一层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分成来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特征:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成即联合文件系统。

bootfs(boot file system)主要包含bootloader和kernel, bootloader 主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在 Docker镜像的最底层是bootfs.这一层与我们典型的Linux/Unix系统是一一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权己由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system),在bootfs之 上.包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是 各种不同的操作系统发行版,比如Ubuntu, Centos等等 。
对于一个精简的OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用宿主机的kernel,自己只需要提供rootfs就行了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs 。

注意:docker在bootfs自检完毕之后并不会把rootfs的read-only改为read-write。而是利用union mount(UnionFS的一种挂载机制)将一个或多个read-only的rootfs加载到之前的read-only的rootfs层之上。在加载了这么多层的rootfs之后,仍然让它看起来只像是一个文件系统,在Docker的体系里把union mount的这些read-only的rootfs叫做Docker的镜像。但是,此时的每一层rootfs都是read-only的,我们此时还不能对其进行操作。当我们创建一个容器,也就是将Docker镜像进行实例化,系统会在一层或是多层read-only的rootfs之上分配一层空的read-write的rootfs。
八、容器数据卷
简介
容器数据卷的作用是数据共享和数据持久化。卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过联合文件系统,提供一些用于持续存储或共享数据的功能。
卷的设计目的就是持久化,完全独立于容器的生命周期,因此docker不会在容器删除时删除其挂载的数据卷。如果没有指定映射卷位置(容器数据卷)将会在/var/lib/docker/volumes下创建默认容器管理数据卷
容器卷具有以下特点:
- 容器卷可在容器之间共享或重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新当中
- 数据卷的生命周期一直持续到没有容器使用它为止
使用容器数据卷
挂载完成可以使用docker inspect命令查看相关数据卷挂载信息
使用命令
docker run [options] -v [宿主机绝对路径]:[docker容器绝对路径] 镜像ID 挂载容器数据卷
docker run [options] -v [宿主机绝对路径]:[docker容器绝对路径]:[ro] 镜像ID 只读模式挂载
指定宿主机路径,目的时为了读写数据
若不指定宿主机路径,则docker自动创建一个目录,这样使用是为了共享数据
注意:当宿主机删除与容器挂载的目录时,容器的挂载目录变为只读。即使宿主机恢复容器的挂载目录也无效
使用DockerFile文件的VOLUME命令创建容器管理数据卷
VOLUME [“docker容器绝对路径”,“docker容器绝对路径”]
只会在容器内创建,宿主机目录由docker自行创建,目的时为了数据共享
数据卷容器
命名的容器挂载数据卷,其它容器通过挂在这个父容器实现数据共享,挂载的容器被称为数据卷容器
docker run [options] –volumes-from 数据卷容器名称 镜像名称
九、DockerFile
基础知识
- 每条保留字指令都必须为大写字母且后面至少跟随一个参数
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
- 最大不能超过128层
保留关键字
| 关键字 | 描述 |
|---|---|
| FROM | 基础镜像,当前新镜像时基于哪个镜像 |
| LABEL | 镜像维护者的信息 |
| RUN | 执行的SHELL命令 |
| EXPOSE | 暴露服务的端口,只起显示作用 |
| WORKDIR | 终端登陆之后的工作目录 |
| ENV | 设置环境变量 |
| ADD | 把文件拷贝到镜像并解压【必须和Dockerfile在同一级目录下,不用加绝对路径】 |
| COPY | 把文件拷贝到镜像【必须和Dockerfile在同一级目录下,不用加绝对路径】 |
| VOLUME | 创建数据容器卷 |
| CMD | 指定容器启动时要运行的命令,可以有多个CMD命令,但只有最后一个生效,CMD会被docker run 之后的参数替换 |
| ENTRYPOINT | 指定容器启动时要运行的命令,不会覆盖只会追加 |
| ONBUILD | 当构建一个被继承的Dockerfile时运行的命令,父镜像在被子镜像继承时触发 |
示例
- 简单的使用
| |
- CMD和ENTRYPOINT
| |
- ONBUILD
| |
- 自定义tomcat
| |
十、镜像仓库搭建
官方仓库搭建方式
仓库端
- 启动仓库
| |
- 修改【
/etc/docker/deamon.json】文件
| |
- 重启docker服务
| |
客户端
- 修改【
/etc/docker/deamon.json】文件
| |
- 重启docker服务
| |
- 查看仓库镜像
| |
- 打包上传镜像
| |
Harbor仓库搭建
Harbor构建需要先安装python、compose。harborGithub地址
- 构建SSL证书
| |
- 修改
harbor.yml
| |
- 执行安装脚本
| |
- 访问harbor
https://ip/harbor/projects,默认账户:admin,密码:Harbor12345
客户端配置(非进行公网认证过的SSL证书)
- 修改【
/etc/docker/deamon.json】文件
| |
- 重启docker服务
| |
打包示例
docker tag hello-world:latest www.kun.com/library/hello-world:v1.0推送示例
先登录:
docker login www.kun.com
docker push www.kun.com/library/hello-world:v1.0
十一、网络设置
网络通讯

容器与容器之间通讯使用docker的网桥(类似交换机作用)进行相互之间铜须
容器访问外部网络使用SNAT转换
外部网络访问容器使用DNAT转换
网络模式修改
进程网络修改【不常用】
-b,–bridge=”“:指定Docker使用的网桥设备,默认情况下Docker会自动创建和使用docker0网桥设备,通过此参数可以设置已经存在的设备
–bip:指定Docker0的IP和掩码,使用标准的CIDR格式如10.10.10.10/24
–dns:配置容器的DNS,在启动Docker进程时添加,所有容器全部生效
容器网络修改
- –dns:配置容器的DNS
- –net:指定容器的网络通讯方式
- bridge:Docker默认方式,网桥模式
- none:容器没有网络栈
- container:使用其它容器的网络栈,容器会加入其它容器的network namespace
- host:表示容器使用Host的网络,没有自己独立的网络栈,容器可以完全访问Host的网络,不安全
端口暴露方式
p/P 选项的使用格式
- -p :
将制定的容器端口映射至主机所有地址的一个动态端口 - -p
: 映射至指定的主机端口 - -p
:: 映射至指定的主机的IP的动态端口 - -p
: : 映射至指定的主机IP的主机端口 - -P(大写) 暴露所需要的所有端口(expose端口)到随机端口
docker port [ontainerName] 可以查看容器当前的映射关系
容器间网络隔离
第一步:创建独立network namespace
| |
第二步:运行镜像是指定network
| |
查看namespace:
docker network ls
十二、内存&CPU限制
默认情况下Docker创建的容器会尽可能是用完操作系统内存,当服务异常时可能会导致崩溃,所以生产环境下CPU和内存必须加以限制。Dockers底层使用CGroup进行资源限制。
Linux内核有OOME机制【Out Of Memory Exception】
一旦发生OOME,任何进程都有可能被杀死,包括docker daemon在内,为此docker调整了docker daemon的OOM优先级,以免被内核关闭。
内存相关设置
-m,–memory 容器能使用的最大内存大小,单位M
–memory-swap 容器可使用的swap大小
- –memory为正数M,–memory-swap为正数S,swap空间为(S-M)
- –memory为正数M,–memory-swap为0或者unset,容器可用swap为2*M
- –memory为正数M,–memory-swap为-1,使用主机的swap限制
容器内使用free看到的swap空间不具有真实含义
–memory-swappiness swap出内存的比例。取值0-100,0代表不使用swap
–memory-resercation 内存软限制
–oom-kill-disable 发生OOME时是否杀死容器,只有配置-m时使用才安全,否则会造成内存耗尽
CPU相关设置
Docker提供的CPU资源限制选项可以在多核系统上限制容器能利用哪些vCPU,而对容器最多能使用的CPU时间 有两种限制方式:①设置各个容器能使用的CPU时间相对比例。②以绝对的方式设置容器在每个调度周期内最多能使用的时间
- –cpuset-cpus="" 使用的CPU集,例如:“0,1,1-3"分别表示使用第一块、第二和第一、第二、第三块CPU
- -c,–cpu-shares=1024 CPU使用权重,默认1024
- –cpu-period=0 一个调度周期时间单位微秒(1000~1000000),和
cpu-quota联用 - –cpu-quota=0 一个调度周期使用的CPU时间单位微妙,和
cpu-period联用
docker run -it –cpu-period=10000 –cpu-quota=20000 centos /bin/bash #代表使用两块CPU
十三、Docker安装MySQL、Redis
- 安装MySQL
| |
- 安装Redis
| |
附名词解释&容器状态转换图
IASS&PASS&SASS

LXC
Linux的container技术在内核层面由两个独立的机制保证,一个保证资源的隔离性,名为namespace,一个进行资源的控制,名为cgroup。
namespace
namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。
Linux现有的namespace有6种: uts[主机名], pid, ipc[进程通信], mnt[挂载点], net和user
cgroup
cgroup是Linux下的一种将进程按组进行管理的机制,在用户层看来,cgroup技术就是把系统中的所有进程组织成一颗一颗独立的树,每棵树都包含系统的所有进程,树的每个节点是一个进程组,而每颗树又和一个或者多个subsystem关联,树的作用是将进程分组,而subsystem的作用就是对这些组进行操作。
subsystem
一个subsystem就是一个内核模块,他被关联到一颗cgroup树之后,就会在树的每个节点(进程组)上做具体的操作。subsystem经常被称作"resource controller”,因为它主要被用来调度或者限制每个进程组的资源【比如限制CPU的使用时间,限制使用的内存,统计CPU的使用情况,冻结和恢复一组进程等】
hierarchy
一个hierarchy可以理解为一棵cgroup树,树的每个节点就是一个进程组,每棵树都会与零到多个subsystem关联。在一颗树里面,会包含Linux系统中的所有进程,但每个进程只能属于一个节点(进程组)。系统中可以有很多颗cgroup树,每棵树都和不同的subsystem关联,一个进程可以属于多颗树,即一个进程可以属于多个进程组,只是这些进程组和不同的subsystem关联。
容器状态转换图
