Docker容器虚拟化技术
2021-09-01 10:05:47 3 举报
AI智能生成
Docker容器虚拟化技术
作者其他创作
大纲/内容
Docker容器虚拟化技术
1. 概述
虚拟化
即在操作系统上多加一个虚拟化层(Hypervisor),可以将物理机的CPU、内存、硬盘、网络等资源进行虚拟化,再通过虚拟化出来的空间上安装操作系统,构建虚拟的应用程序执行环境
如:VMware、VirtualBox、KVM等
优点
提升IT效率
降低运维成本
更快地部署工作负责
提高应用性能
提高服务器可用性
消除服务器梳理剧增情况和复杂性
缺点
占用资源较多
性能较差
扩展能力较差
环境迁移能力较差
容器化
说明
借鉴集装箱的解决方案,封装应用以及它的运行环境,将应用和环境打包成一个轻量化、可移植、自包含的容器
容器是轻量级的,不需要虚拟机管理程序的额外负载,而是直接在主机的内核中运行
与使用虚拟机相比,可以在给定的硬件组合上运行更多的容器
特点
容器共享宿主主机内核
容器使用内核的功能对进程进行分组和资源限制
容器通过命名空间保证隔离
容器像是轻量级的VM(占用空间更少,速度更快)
Docker
简介
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows机器上,也可以实现虚拟化
背景
Docker是基于Go语言实现的开源容器项目,已加入Linux基金会,并遵循Apache2.0协议
构想是要实现“Build、Ship and Run Any App,Anywhere”
通过对应用的封装(Packaging)、分发(Distribution)、部署(Deployment)、运行(Runtime)生命周期进行管理,达到应用组件“一次封装、到处运行”的目的
应用组件可以是一个Web应用、一个编译环境,也可以是一套数据库平台服务、甚至是一个操作系统或集群
Docker首次为应用的开发、运行和部署提供了“一站式”的使用解决方案
Linux容器(LXC)
最早的Docker基于Linux容器技术
最早的容器技术为1982年Unix系统上的chroot工具
早期的容器实现技术
Sun Solaris OS的Solaris Containers(2004)
FreeBSD OS的FreeBSD jail(2000)
GNU/Linux的Linux-VServer和OpenVZ
从Linux容器到Docker
Docker在LXC基础上进一步优化了容器的使用体验
Docker提供了各种容器管理工具(分发、版本、移植),让用户无需关注底层的操作,可以更简单明了的管理和使用容器
Docker通过引入分层文件系统构建(aufs)和高效的镜像机制,降低了迁移难度,极大地提升了用户体验
v0.9后,Docker开发了libcontainer项目,作为更广泛的容器驱动实现,从而替换掉了LXC的实现
应用场景
快速,一致地交付应用程序、镜像打包环境,避免了环境不一致的问题
Docker可以为开发人员提供标准化的本地工作环境给应用程序和服务,从而简化了开发生命周期
容器非常适合持续集成和持续交付工作流程
响应式部署和扩展
Docker是基于容器的平台,允许高度可移植的工作负载
Docker容器可以在开发人员的本地笔记本电脑上,数据中的物理或虚拟机上,云提供商上或混合环境中运行
Docker的可移植性和轻量级的特性还使可以轻松地动态管理工作负载,并根据业务需求指示实时扩展或拆除应用程序和服务
在同一个硬件上运行更多工作负载
Docker轻巧快速,它为基于虚拟机管理程序的虚拟机提供了可行、经济高效的替代方案,因此可以利用更多的计算能力来实现业务目标
Docker非常适合于高密度环境以及中小型部署,而需要用更少的资源做更多的事情
优点
Docker提供了一种更为聪明的方式,通过容器来打包应用,解耦应用和运行平台
在迁移时,只需要在新的服务器上启动需要的容器即可,无论新旧服务器是否是同一类型的平台
优势
更快速的交付和部署
更高效的资源利用
更轻松的迁移和扩展
更简单的更新管理
提供完整的软件生态系统
镜像管理、资源隔离、文件系统、网络隔离、流程管理、服务发现
特性
启动速度:秒级
性能:接近原生
内存代价:很小
硬盘使用:一般为MB
运行密度:单机支持上千个容器
隔离性:安全隔离
迁移性:优秀
2. 快速实战
核心组件
Docker引擎
Docker使用客户端-服务器架构
客户端是用户与Docker交互的主要方式,与Docker守护进程(Docker引擎)进行通信,该进程完成了构建、运行和分发Docker容器的繁重工作
Docker客户端和守护程序可以在同一系统上运行,也可以将Docker客户端连接到远程Docker守护程序
Docker客户端和守护程序在UNIX套接字和网络接口上使用REST_API进行通信
Docker守护进程侦听Docker_API请求并管理Docker对象,如镜像、容器、网络和卷等
Docker守护程序还可以与其他守护程序通信,以管理Docker服务
Docker镜像
Docker镜像类似于虚拟机镜像,可以将其理解为一个只读的模板
镜像是基于联合(Union)文件的系统的一种层式的结构,由一系列指令一步步构建出来
镜像是构建Docker容器的基础,通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有镜像,客户可以下载一个已经做好的应用镜像,并直接使用
可以利用DockerFile来构建自己的镜像
Docker容器
类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用
容器是镜像的一个运行实例,可以将其启动、开始、停止、删除,而容器间是彼此相互隔离、互不可见的
可以把容器看作是一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子
容器基于镜像启动,容器中可以运行一个或多个进程
镜像是Docker生命周期中的构建或打包阶段,而容器时启动或执行阶段
镜像自身是只读的,容器从镜像启动时,会在镜像的最上层创建一个可写层
Docker仓库
Docker仓库类似于代码仓库,它是Docker集中存放镜像文件的场所
仓库注册服务器是存放仓库的地方,其上往往存放着多个仓库
每个仓库集中存放某一类镜像,往往包含多个镜像文件,通过不同的标签(tag)来进行区分
根据所存储的镜像公开分享与否,Docker仓库可分为公开仓库和私有仓库两种形式
安装
1、卸载历史版本
2、安装官方yum源
3、安装Docker引擎
4、启动
使用镜像
获取镜像
docker pull NAME[: TAG]
拉取最新的镜像,描述一个镜像需要包括“名称+标签”信息
镜像文件一般由若干层组成,层唯一id
如果不显式指定TAG,默认选择latest标签,下载仓库中最新版本的镜像
镜像的仓库名称中还应该添加仓库地址(即registry)作为前缀,默认使用DockerHub服务,可以忽略
如果从非官方仓库下载,则需要在仓库名称前指定完整的仓库地址
查看信息
docker images
可以通过max docker-images查看更多命令参数
添加标签
docker tag[原镜像名:tag号][目标镜像名:tag号]
如果tag号省略,默认latest
查看详情
docker inspect NAME[: TAG]
返回一个JSON格式的消息
如果只要其中一项内容时,可以使用参数-f来指定
搜寻镜像
docker search 名称
搜索DockerHub仓库镜像,私有仓库无法搜索
删除镜像
docker rmi NAME[: Tag]
当同一个镜像拥有多个标签时,该命令只是删除该镜像多个标签中的指定标签,并不影响镜像文件
docker rmi IMAGE ID
使用镜像ID删除镜像
如果有容器正在运行该镜像,则不能删除
想强行删除使用-f(不建议)
上传镜像
docker push NAME[: TAG]
上传镜像到仓库,默认上传到DockerHub(需登录)
操作容器
创建容器
docker create NAME[: TAG]
可加参数
-i
交互模式
-t
伪终端
-d
后台运行
-rm
容器退出后是否自动删除
启动容器
docker start 容器ID
docker ps
查看运行的容器
docker ps -a
查看所有容器
新建并启动
docker run NAME[: TAG]
相当于 docker create + docker start
可加参数
-network host
使用宿主机IP地址
man docker run
docker run -help
终止容器
docker stop 容器ID -t 时间
首先向容器发送SIGTERM信号,等待一段超时时间(默认10s)后,再发送SIGKILL信号来中止容器
docker kill 容器id
直接发送SIGKILL命令来强行终止容器
docker restart
将一个运行态的容器先终止,然后再重新启动
处于终止状态的容器,可以通过start命令来重新启动
进入容器
docker exec -it[容器ID] /bin/bash
早期有attach命令,对于阻塞命令会等待,所以不方便
v1.3.0后提供了exec可以再容器内直接执行任意命令
exec:容器执行某命令,操作为容器ID后的命令
-it 以伪终端模式,相当于进入容器中
无论再容器内进行何种操作,依据镜像创建的其他容器都不会受影响(namespace隔离,但将数据持久化的操作除外)
查看容器
docker inspect [容器ID]
docker stats [容器ID]
删除容器
docker rm [容器ID]
只能删除处于终止或退出状态的容器,并不能删除还处于运行态的容器
要直接删除运行中的容器,可以添加-f参数
docker会先发送SIGKILL信号给容器,终止其中应用后强行删除
访问仓库
DockerHub
最大的公共镜像仓库,在其中注册一个账号,每ID可以免费拥有一个私有镜像
登录仓库
docker login -u username -p password
默认登录DockerHub
登录成功的用户可以上传个人的镜像
用户无需登录即可通过search命令来查找官方仓库中的镜像,并利用docker pull来将它下载到本地
登出仓库
docker logout
可以同时登录多个docker仓库,故此命令一般不执行
认证文件
/root/.docker/config.json
Mac/Win机器上是隐藏密码的,但Linux下显示密码,只不过进行base64编码
拷贝该文件到其他机器指定目录下即可免登录
常用软件的容器化部署
MySql
操作
--network host
使用宿主机IP,不能再使用端口映射
-p
宿主机端口:容器端口,只能使用容器端口
--rm
当容器停止后,对容器机器申请的卷执行删除操作
-e key=value
指定环境变量
-d
后台运行
Tomcat
操作
-it
交互式伪客户端
--rm
当容器停止后,对容器及其申请的卷执行删除操作
--network host
使用宿主机IP
Nginx
操作
--name
运行的容器名称
Redis
操作
3. 核心原理
内部结构
Docker_Engine是具有以下主要组件的客户端-服务器应用程序
服务器是一种长期运行的程序,称为守护程序进程(dockerd)
REST_API,它指定程序可用用来与守护程序进行通信并指示其操作的接口
命令行界面(CLI),客户端(docker命令)
好处
可以通过REST_API将客户端和服务端解耦
服务端可以做到Volume/Network等做成插件化组装
容器生命周期
状态/命令
created:初创建
docker create
running:运行状态
docker run、docker start、docker restart、docker unpause
stopped:停止状态
docker stop、docker kill
paused:暂停状态
docker pause
deleted:删除状态
docker rm
命名空间
简介
命名空间是Linux内核的一个强大特性,为容器虚拟化的实现带来极大便利
命名空间要对内存、CPU、网络IO、硬盘IO、存储空间、文件系统、网络、PID、UID、IPC等相互隔离
进程命名空间 PID
PID命名空间对集成PID重新编号,即两个不同的namespace下的进程可以用相同的PID
内核为所有PID_namespace维护了一个树状结构,最顶层的是系统初始时创建的,被称为root_namespace(PID:1)
root创建的PID_namespace被称为child_namespace
不同的PID_namespace会形成一个层级体系,所属的父节点可以看到子节点中的进程,并通过信号等方式对子节点中的进程产生影响,反之子节点看不到父节点的任何内容
网络命名空间 network
通过网络命名空间,可以实现网络隔离
网络命名空间为进程提供了一个完全独立的网络协议栈的视图,包括网络设备接口、IPv4和IPv6协议栈、IP路由表、防火墙规则、sockets等,这样每个容器的网络就能隔离开来
Docker采用虚拟网络设备的方式,将不同命名空间的网络设备连接到一起
默认情况下,容器中的虚拟网卡将同本地主机上的docker0网桥连接在一起
IPD命名空间 IPC
IPC:进程间通信 Inter-Process-Communication
IPC涉及的资源包括常见的信号量、消息队列和共享内存
申请IPC资源就申请了一个全局唯一的32位ID,所以IPC_namespace中实际上包含了系统IPC标识符以及实现POSIX消息队列的文件系统
PID_namespace和IPC_namespace可以组合起来一起使用,在同一个IPC_namespace下的进程彼此可见,不同IPC_namespace下的进程互相不可见
挂载命名空间 Mount
类似于chroot,将一个进程放到一个特定的目录执行
挂载命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间中的进程所看到的文件目录彼此被隔离
它通过隔离文件系统挂载点对隔离文件系统提供支持,是Linux支持的第一个namespace
隔离后的挂载命名空间中的文件结构发生变化也互不影响
可以通过/proc/[pid]/mounts查看到所有挂载在当前namespace中的文件系统
可以通过/proc/[pid]/mountstats查到挂载命名空间中文件设备的统计信息,包括挂载文件的名字、文件系统、挂在位置等
UTS命名空间 UTS
UTS:UNIX Time-Sharing System
UTS命名空间允许每个容器拥有独立的主机名和域名,从而可以虚拟出一个有独立主机名和网络空间的环境,就跟网络上一台独立的主机一样
这样每个Docker容器可以拥有独立的主机名和容器,在网络上可以被视作一个独立的节点,而非宿主机上的一个进程
Docker中,每个镜像基本上都以自身提供的服务名来命名镜像的hostname,而且不会对宿主机产生任何影响,其原理就是利用了UTS_namespace
默认情况下,Docker容器的主机名就是返回的容器ID
用户命名空间 user
每个容器可以有不同的用户和组id,即可以在容器内使用特定的内部用户执行程序,而非本地系统上存在的用户
每个容器内部都可以有root账号,但跟宿主机不在一个命名空间
通过使用隔离的用户命名空间可以提高安全性,避免容器内进程获取到额外的权限
资源配额限制
说明
控制组(CGroups)是Linux内核的一个特新,主要用来对共享资源进行隔离、限制、审计等
只有能控制分配到容器的资源,才能避免多个容器同时运行时对宿主机系统的资源竞争
控制组可以提供对容器的内存、CPU、磁盘IO等资源进行限制和管理
默认情况下,容器没有资源限制,且可以使用主机内核调度程序允许的尽可能多的给定资源
查看容器状态时看到docker stats containerID
docker提供了一些方法来控制容器可以使用多少内存或CPI,通过设置run命令的运行时配置标志
CPU
--cpus = value
指定一个容器可以使用多少可用的CPU资源
如主机有两个CPU,设置--cpus=1.5,则可以保证容器最多容纳一半的CPU
相当于设置
--cpu-period = 100000
--cpu-quota = 150000
在Docker1.13及更高版本中可用
--cpu-period = value
指定CPU_CFS调度程序周期,该周期与--cpu-quota一起使用
默认位100ms,一般不进行修改
使用Docker1.13或更高版本,建议使用--cpus
--cpu-quota = value
在容器上设置CPU_CFS资源
--cpu-period节流之前,容器被限制为每个微秒数,这样就充当了有效的上限
使用Docker1.13或更高版本,建议使用--cpus
--cpuset-cpus
限制容器可以使用的特定CPU或内核
可以使用逗号分隔,或使用“-”标识范围
--cpu-shares
将此标志设置位>=默认1024的值,以增加或减少容器的重量,并使其可以访问更多/更少比例的主机CPU周期,仅在限制CPU周期时才执行此操作
当有足够的CPU周期可用时,所有容器都会根据需要使用尽可能多的CPU
这是一个软限制,它不会阻止以集群模式调度容器,它将容器CPU资源的优先级分配给可用的CPU周期
它不保证或保留任何特定的CPU访问权限
内存
-m, --memory=
容器可以使用的最大内存量
设置此选项,则最小允许值位4m
--memory-swap *
允许此容器交换到磁盘的内存量
--memory-swappiness
默认情况下,主机内核可以换出一定比例的容器使用的匿名页面
可以设置该参数位一个0~100的值来调整该比例
--memory-reservation
允许指定一个小于--memory的,Docker在主机上检测到争用或内存不足时激活的软限制
--kernel-memory
容器可以使用的最大内核内存量,允许最小值为4m
由于无法交换内核内存,因此内核内存不足的容器可能会阻塞主机资源,这可能会对主机和其他容器产生副作用
--oom-kill-disable
默认情况下,如果发生OOM,则内核将终止容器中的进程,要更改该行为,使用本选项
仅在还设置了--memeory的容器上禁用该选项
如果-m未设置该标志,则主机可能会用完内存,内核可能需要终止主机系统的进程以释放内存
大部分选项取正整数,跟后缀b、k、m、g表示容量大小
磁盘读写
docker可以通过设置权重、限制bps和iops的方式控制容器读写磁盘的带宽
联合文件系统
简介
UnionFS是一种轻量级的高性能分层文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,应用看到的是挂载的最终结果
UnionFS可以把文件系统上多个目录内容联合挂载到同一个目录下,而目录的物理位置是分开的
UnionFS是实现Docker镜像的技术基础,Docker镜像可以通过分层来进行继承
Docker存储
Docker目前通过插件化方式支持多种文件系统后端
Docker镜像自身由多个文件层组成,每层有唯一的编号(层ID)
当Docker利用镜像启动一个容器时,将在镜像文件系统的最顶端再挂载一个新的可读写的层级容器,容器中的内容更新会发生在可读写层
通过history命令查看一个镜像由哪些层组成
AUFS
Another Union File System/Advanced Multilayered Unification File System(v2版本后)
Debian/Ubuntu上成熟的AUFS就是一种联合文件系统实现
它支持位每一个成员目录设定只读(readonly)、读写(readwrite)或写出(writeout-able)权限
它有一个类似分层的概念,对只读权限的分支可以再逻辑上进行增量地修改(不影响只读部分)
文件系统比较
AUFS
最早支持的文件系统,对Debian/Ubuntu支持好,虽然没有合并到Linux内核中,但成熟度很高
OverlayFS
类似于AUFS,性能更好一些,已经合并到内核
未来会取代AUFS,但成熟度有待提高
Device Mapper
Redhat和Docker一起开发用于支持RHEL的文件系统
内核支持,性能略慢,成熟度高
btrfs
参考zfs等特性设计的文件系统,由Linux社区开发
视图未来取代Device_mapper,成熟度有待提高
vfs
基于普通文件系统的中间层抽象
性能差,比较占用空间,成熟度一般
zfs
最初设计为Solaris10上的写时文件系统,拥有不少好特性,但对Linux支持不够成熟
通过docker info的Storage Driver可以看到文件系统类型
容器网络
Docker本地网络实现实现利用了Linux上的网络命名空间和虚拟网络设备
Docker中的网络接口默认都是虚拟接口,Docker容器网络在本地主机和容器内分别创建一个虚拟接口,并让它们彼此联通
这样的一对接口叫做veth pair
Docker网络定义
bridge
默认值,在Docker网桥docker0上为容器创建新的网络栈
host
对于独立容器,不要将容器网络放到隔离的命名空间中,然后直接使用宿主机的网络
host仅可用于v17.06及更高版本上的集群服务
overlay
覆盖网络将多个Docker守护程序连接在一起,并使集群服务能够互相通信
还可以使用它来促进集群服务和独立容器之间或不同Docker守护程序上的两个独立容器之间的通信
该策略消除了在这些容器之间进行操作系统级路由的需要
macvlan
Macvlan网络允许将Mac地址分配给容器,使其在网络上显示为物理设备
Docker守护程序通过其Mac地址将流量路由到容器
Macvlan在处理希望直接连接到物理网络而不是通过Docker主机的网络堆栈进行路由的旧应用程序时,使用驱动程序有时是最佳选择
none
对于此容器,禁用所有联网
通常与自定义网络驱动程序一起使用
网络插件
可以在Docker上安装和使用第三方网络插件
命名
查看已经安装的驱动
docker network ls
使用默认网络
docker run --rm -d --name myNginx nginx
使用宿主机网络
docker run --rm -d --network host --name myNginx nginx
使用物理网卡模式
docker network create -d macvlan --subnet=172.16.206.0/24 --gateway=172,16.206.1 -o parent=eth0 myMacvlanNet
docker run --it --rm -d --network myMacvlanNet nginx
存储卷
说明
默认情况下,在容器内创建的所有文件都存储在可写容器层上,这样会
当该容器不再存在时,数据将不会持久保存,如果另一个进程需要它,则可能很难从容器中取出数据
容器的可写层与运行容器的主机紧密耦合,不能轻易地将数据移动到其他地方
写入容器的可写层需要存储驱动程序来管理文件系统,性能比直接写入主机要低
Docker为容器提供了两个选项来将文件存储再主机中,以便即使容器停止后也可以持久存储
数据卷 Data Volumes
容器内数据直接映射到本地主机环境
数据卷容器 Data Volumes Containers
使用特定容器维护数据卷,也成为bind mounts
如果在Linux上运行Docker,还可以使用tmpfs挂载,如果在Windos上运行Docker,还可以使用命名管道
数据卷
概念
由Docker创建和管理,是一个可供容器使用的特殊目录
它将主机操作系统目录直接映射进容器,类似于Linux中的mount操作
特性
可以在容器之间共享和重用
对数据卷内数据的修改会立马生效
对数据卷的更新不会影响镜像
卷会一直存在,直到没有容器使用,可以安全地卸载它
创建方式
显式创建
docker volume create
在容器内创建
docker run -v
场景
在多个运行中的容器之间共享数据
当要将容器数据存储在远程主机或云提供商时
当需要将数据从一个Docker主机备份,还原或迁移到另一个Docker主机时
操作
创建
docker volume create myVol
清单
docker volume ls
检查体积
docker volume inspect myVol
删除
docker volume rm myVol
启动一个卷的容器
如果使用不存在的卷启动容器,则Docker将创建该卷
数据卷容器
概念
数据卷容器也称为绑定挂载,使用绑定挂载时,主机上的文件或目录将安装到容器中
该文件或目录不需要再Docker主机上已经存在,如果尚不存在,则按需创建
可以通过容器中运行的进程来更改主机文件系统,包括创建、修改或删除重要的系统文件或目录
场景
多个容器之间共享一些持续更新的数据
Docker主机上的开发环境和容器之间共享源代码或构建工件
操作
创建
docker run -d -it --name devtest -v “${pwd}” /target:/app nginx:latest
验证
docker inspect devtest
使用只读绑定安装
对于某些开发应用程序,容器需要写入绑定安装,因此更改将传播回Docker主机,在其他时间,容器仅需要读取访问权限
tmpfs挂载
概念
tmpfs进存储在主机系统的内存中,不会写入主机系统的文件系统中
不会持久化在磁盘上,无论是在Docker主机上还是在容器内
场景
可以使用它来存储非持久状态或敏感信息
操作
要在容器中使用tmpfs,使用--tmpfs标志,或将--mount与type=tmpfs和destination一起使用
通过运行docker container inspect tmpfs来验证安装是否成功
卸载
选项
tmpfs安装允许两个非必需配置选项,如果需要指定这些选项,则必须使用--mount,因为--tmpfs不支持它们
tmpfs-size
tmpfs安装的大小,字节为单位,默认情况下不受限制
tmpfs-mode
tmpfs的文件模式(8进制数值,如1770-非全局可读)
4. 高级
DockerFile
简介
DockerFile是一个文本格式的配置文件,用户可以使用DockerFile来快速创建自定义镜像
基本结构
DockerFile由一行行命令语句组成,且支持以#开头的注释行
DockerFile分为四部分
基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令
每条指令创建一层
FROM
指明所基于的镜像名称
MAINTAINER
维护者信息,docker_user维护(可不写)
COPY
从Docker客户端的当前目录添加文件,镜像操作指令
RUN
构建镜像时执行make命令,每运行一条RUN指令,镜像旧添加新的一层,并提交
CMD
指定在容器中运行的命令,用来指定运行容器时的操作命令
Docker镜像由只读层组成,每个只读层代表一个DockerFiler指令,这些层是堆叠的,每层都是上一层的变化的增量
Docker可以通过读取DockerFile指令来自动构建镜像
指令
FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认取DockerHub下载
任何DockerFile的第一条指令必须为FROM,且如果同一DockerFile创建多个镜像,可以使用多个FROM指令,每个镜像一次
MAINTAINER
指定维护者信息,可以不写
该信息会写入生成镜像的Author属性域中
RUN
运行指定命令
格式
1、RUN
默认将在shell终端中运行命令,即/bin/sh-c
2、RUN["executable", "parm1", "parm2"]
指定会被解析为Json数组,因此必须用双引号
exec执行,不会启动shell环境
每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像,当命令较长时可以使用\来换行
CMD
用来指定启动容器时默认指定的命令
每个DockerFile只能有一条CMD命令,如果指定了多条,只有最后一条会被执行
如果用户启动容器时手动指定了运行的命令(作为run的参数),则会覆盖该配置
COPY
复制本地主机下的内容到镜像中的路径下,目标路径不存在时,将自动创建
ENV
指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在
形式
ENV
将一个变量设置为一个值,第一个空格之后的整个字符串将被视为value,包括空格字符
该值将为其他环境变量解释,因此如果不对引号字符进行转义,则将其删除
ENV =
允许一次设置多个变量
与命令行解析一样,引号和反斜杠可用于在值中包含空格
ENV从结果镜像运行容器时,使用设置的环境变量将保留
使用inspect查看
使用run -env key=value修改
ADD
该命令将复制指定的路径下的内容到容器中的路径下
源路径可以是DockerFile所在目录的一个相对路径,也可以是一个URL,还可以是一个tar文件(tar文件会自动解压到路径下)
目标路径可以是镜像内的绝对路径,或相对于工作目录的相对路径
与COPY的区别
1、DockerFile中的COPY/ADD都可以将主机上的资源复制或加入到容器镜像中,都是在构建镜像过程中完成的
2、COPY和ADD区别在于是否支持从远程URL获取资源
COPY只能从执行build所在的主机上读取资源并复制到镜像中
ADD值支持通过URL从远程服务器读取资源并复制到镜像中
3、满足同等功能情况下,推荐使用COPY,ADD更擅长读取本地tar文件并解压
4、当要读取URL资源时,并不推荐使用ADD,而是建议使用RUN,在RUN中执行wget/curl
ENTRYPOINT
指定镜像的默认入口,该入口会在启动容器时作为根命令执行,所有传入值作为该命令的参数
形式
ENTRYPOINT ["executable", "parm1", "parm2"]
EXEC形式,优先选择的方式
ENTRYPOINT command parm1 parm2
其中实际执行 /bin/sh -c command parm1 parm2
多个ENTRYPOINT只有最后一条生效
VOLUME
创建一个数据卷挂载点
可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等
WORKDIR
为后续的RUN、CMD和ENTRYPOINT配置工作目录
可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径
EXPOSE
该指令通知Docker容器在运行时监听指定的网络端口,可以指定TCP/UDP,默认为TCP
无论EXPOSE如何设置,都可以在运行时使用“-p”覆盖配置
创建镜像
build 构建
编写完成DockerFile后,可以通过docker build来创建镜像
build将读取指定路径下(包括子目录)的DockerFile,并将该路径下的所有内容发送给Docker服务端,由服务端来创建镜像
如果使用非内容路径下的DockerFile,可以通过-f来指定其路径
要指定生成镜像的标签信息,可以使用-t
build最后需要“ .”号,是在指定镜像构建过程中的上下文环境的目录
镜像管理
镜像由一系列层组成,每层代表镜像的Dockerfile中的一条指令,除最后一层外的每一层都是只读的
运行镜像并生成容器时,可以在基础层上添加一个新的可写层(“容器层”),对运行中的容器所做的所有更改都将写入此可写容器层
容器和镜像之间的主要区别是可写顶层,在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中,删除容器后,可写层也会被删除,基础镜像保持不变
因为每个容器都有自己的可写容器层,且所有更改都存储在该层中,所以多个容器可以共享对同一基础镜像的访问,但具有自己的数据状态
查看镜像分层信息
docker history 镜像ID
磁盘上容器大小
docker ps -s
size
用于每个容器的可写层的数据量(磁盘上)
virtual size
容器使用的只读图像数据加上容器的可写层使用的数据量size
多个容器可以共享部分或全部只读图像数据,从同一图像开始的两个容器共享100%的只读数据,而具有不同图像的容器(具有相同的层)共享这些公共层
因此,不能只对虚拟大小进行总计
通过docker仓库来传输镜像,也可以通过文件模式
模板
建议
从适当的基础镜像开始
如需要JDK镜像基于正式openjdk镜像
使用多阶段构建
如,可以使用maven镜像构建Java应用程序,然后将其重置为tomcat镜像并将Java构件复制到正确的位置以部署应用程序
这意味着最终镜像不包括构建所引入的所有库和依赖库,而仅包括运行它们所需的工件和环境
通过最小化Dockerfile中RUN单独命令的数量来减少镜像中的层数
可以通过将多个命令合并为RUN一行并使用Shell的机制将它们组合在一起来实现此目的
如果由多个具有很多共同点的图像,请考虑使用共享的组件来创建自己的基础镜像,Docker只需要加载一次公共层,然后将它们缓存
这意味着派生镜像将更有效地使用Docker主机上的内存,并更快地加载
数据持久化
操作
1、创建一个卷,待后续使用
docker volume create test_volume
2、分别启动2个容器挂载该卷
docker run -it --rm -v test_volume:/test nginx:latest /bin/bash
docker run -it --rm -v test_volume:/test nginx:latest /bin/bash
3、在/test文件夹创建文件,则两个容器中均可以看到该文件,即实现了多个容器间的数据共享
说明
挂载在容器/test目录内创建,Docker不支持容器内安装点的相对路径
多个容器可以在同一时间段内使用相同的卷,如果两个容器需要访问共享数据,则该操作很有用
不能将相同的卷名与两个驱动程序一起使用,卷名在驱动程序内必须唯一
除了使用卷,也可以使用将宿主机的文件映射到容器的卷,命令类似
宿主机上的目录可以不存在,在启动容器时会创建
5. 运维
swarm集群
简介
Docker_Swarm是Docker官方提供的一套容器编排系统,是Docker公司推出的官方容器集群平台,基于Go语言实现
核心概念
集群
一个集群由多个Docker主机组成,这些Docker主机以集群模式运行,并充当管理者(用于管理成员资格和委派)和工作人员(运行集群服务)
集群的主要优势之一是可以修改服务的配置,包括它所连接的网络和卷,而无需手动重新启动服务
独立容器和集群服务之间的主要区别在于,只有集群管理器可以管理集群,而独立容器可以在任何守护程序上启动
节点
swarm是一系列节点的集合,而节点可以是一台裸机或一台虚拟机,一个节点能扮演一个或两个角色
manager
swarm集群需要至少一个manager,节点之间使用Raft_consensus_protocol进行协同工作
通常,第一个启动的节点将成为Leader,后加入的都是follower,当前Leader宕机,剩余节点将重新选举出一个新Leader
每个Manger都有一个完整的当前集群状态的副本,可以保证manager的高可用
worker
worker节点是运行实际应用服务的容器所在的地方,理论上一个manager节点也能同时称为worker,但生产环境不建议这样做
worker之间通过control_plane进行通信,这种通信使用gossip协议,且是异步的
服务和任务
services
swarm_service是一个抽象概念,它只是一个对运行在集群上的应用服务,所期望状态的描述
它就像一个描述了下面属性的清单列表一样
服务名称
使用哪个镜像来创建容器
要运行多少个副本
服务的容器要连接到哪个网络上
应该映射哪些端口
task
task是一个部署的最小单元,task与容器是一对一的关系
stack
stack是描述一系列相关Services的集合,通过在一个YAML文件中来定义一个stack
负载均衡
集群管理器使用入口负载均衡将要从集群外部获取的服务公开给集群
集群管理可以自动为服务分配一个已发布端口,也可以为该服务配置一个已发布端口
可以指定任何未使用的端口,如果未指定,则集群管理器会为服务分配30000-32767范围内的端口
集群模式具有一个内部DNS组件,该组件自动为集群中每个服务分配一个DNS条目
集群管理器使用内部负载均衡根据服务的DNS名称在集群内的服务之间分配请求
安装
下载镜像
docker pull swarm
查看版本
docker run --rm swarm -v
集群
创建新集群
执行命令后,该机器自动加入swarm集群,这会创建一个集群token,作为集群唯一标识,后续其他节点加入集群都会用到这个token
--advertise-addr
表示其他swarm中的worker节点使用此IP地址与manager联系
命令的输出包含了其他节点如何加入集群的命令
查看集群状态
添加工作节点
创建了一个集群与管理器节点,就可以添加工作节点
发布服务到集群
参数
-p
端口映射
--replicas
运行实例个数
--name
服务名
扩展一个或多个服务
更新服务
节点管理
docker node demote
从集群管理器中降级一个或多个节点
docker node inspect
显示一个或多个节点的详细信息
docker node ls
列出集群中的节点
docker node promote
从集群管理器中升级一个或多个节点
docker node ps
列出在一个或多个节点上运行的任务,默认为当前节点
docker node rm
从集群删除一个或多个节点
docker node update
更新一个节点
Docker compose
简介
Compose定位是“定义和运行多个Docker容器的应用”,它允许用户通过一个单独的docker-compose.yml文件来定义一组相关联的应用容器为一个项目
概念
Compose将所管理的容器分为三层
项目
由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义
服务
一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
容器
docker容器
Compose运行目录下的所有文件组成一个项目,一个项目包含多个服务,每个服务定义了容器运行的镜像、参数、依赖,一个服务可以包括多个容器实例
Compose默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理
Compose由Phython编写,实现上调用了Docker服务提供的API来对容器进行管理
只要所操作的平台支持DockerAPI,就可以在其上利用Compose来进行编排管理
安装
1、下载
2、将可执行权限应用于二进制文件
3、添加到环境中
4、测试
5、卸载
docker-compose.yml
模板文件是使用Compose的核心,默认的模板文件名称为Docker-compose.yml
常见指令
version
版本,与swarm结合,要3.0以上
services
定义服务
image
指定服务的镜像名称或镜像ID,如果镜像在本地不存在,Compose会拉取镜像
ports
端口映射,HOST:CONTAINER
build
指定dockerfile,Compose将会利用它自动构建这个镜像,然后使用这个镜像启动服务容器
command
使用command可以覆盖容器启动后默认执行的命令
depends_on
确定容器的启动顺序
environment
设置镜像变量
volumes
挂载一个目录或一个已存在的数据卷容器,可以直接使用[host:container]这样的格式,或使用[host:container:ro]的格式,后者对容器来说,数据卷是只读的
Compose的数据卷指定路径可以是绝对路径或相对路径
network_mode
网络模式,默认bridge
networks
定义网络
常见命令
ps
列出所有运行容器
logs
查看服务日志输出
port
打印绑定的公共端口
build
构建或重新构建服务
start
启动指定服务已存在的容器
up以后没有down,可以运行start
stop
停止已运行的服务的容器
不删除容器
rm
删除指定服务的容器
up
通过docker-compose.yml,自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作
大多数时候都可以直接通过该命令来启动一个项目
默认情况下,up启动的容器都在前台,控制台会同时打印所有容器的输出信息,可以很方便进行调试
当通过ctrl+c停止时,所有容器都会停止
使用-d,将会在后台启动并运行所有容器,一般推荐在生产环境下使用该选项
run
在一个服务上执行一个命令
down
停止并删除容器
-v:可以删除容器使用的数据
结合Swarm
docker-compose.yml可以来一次配置、启动多个容器,Swarm集群也可以使用Compose文件来配置、启动多个服务
私有仓库 Harbor
简介
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器
它是由VMWare在Docker_Registry基础上进行二次封装,加入很多额外程序,并提供了一个Web界面
主要组件
proxy
一个nginx前端代理,主要是分发前端页面UI访问和镜像上传和下载流量
ui
提供了一个Web管理页面,还包括一个前端页面和后端API,底层使用Mysql数据库
registry
镜像仓库,负责存储镜像文件,当镜像上传完毕后通过hook通知UI创建repository
adminserver
系统的配置管理中心,附带检查存储用量,UI和JobServer启动时需要加载AdminServer的配置
JobService是负责镜像复制工作的,它和Registry通信,从一个Registry pull镜像,然后push到另一个Registry,并记录Job_log
log
日志汇总组件,通过Docker的log-driver把日志汇总到一起
安装
1、下载解压
2、使用docker加载镜像
配置
harbor.yml
hostname
采用域名
data_volume
数据库路径
启动/停止
1、运行prepare脚本
Harbor将nginx实例用作所有服务的反向代理
使用prepare脚本来配置nginx为使用HTTP和HTTPS
2、利用docker-compose启动和停止Harbor
访问/登录
1、配置hosts映射,做IP和域名的映射
2、通过浏览器浏览
3、修改daemon.json,配置私有仓库
4、从Docker客户端访问Harbor
Pull镜像
1、为要推送的镜像加tag
2、推送镜像到Harbor
生产环境使用
1、生成CA证书
2、生成服务器证书
3、向Harbor和Docker提供证书
4、修改Harbor配置
开启Https
5、启动Harbor
./prepare
docker-compose up -d
6、从Docker客户端登录Harbor
0 条评论
下一页