一.Docker简介
- 经常在开发中遇到开发工程师在本机上写好的项目运行没有问题,但是丢给运维工程师喊它部署,报一大堆错误…
- 出现以上问题主要就两条原因,环境和配置
- Docker就是为了解决上面的问题出现的
- 环境配置如此麻烦,换一台机器,就要重来一次,费力费时,能不能从根本上解决问题,软件带环境安装?也就是说,安装的时候,把原始环境一模一样的复制过来。
- 简单来说以前是搬家…现在是直接搬楼了
- Dokcer镜像设计,使得Docker得以打破过去程序即引用的观念,透过镜像将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作
- 一次构建,处处运行
- 基于Go语言实现的云开源项目
- 只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化操作
1.Docker是什么
- 解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术
- docker三要素:仓库,镜像,容器
2.能干什么
A.之前的虚拟机技术
- 虚拟机是带环境安装的一种解决方案
- 在一种操作系统里面运行另一种操作系统,比如在windows系统里面运行Linux系统。对于底层系统来说,虚拟机就是一个普通文件,不需要就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间逻辑不变
- 缺点:1.资源占用多 2.启动慢 3.冗余步骤多
B.容器虚拟化技术
- 前面虚拟机存在上面这些缺点,Linux发展出另一种虚拟化技术:Linux容器
- Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离,有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此变得高效轻量并保证部署在任何环境中的软件都能始终如一运行
- 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程
- 容器内的应用进程直接运行于宿主的内核,容器没有自己内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便
- 每个容器之间互相隔离,每个容器都有自己的文件系统,容器之间进程不会相互影响,能区分计算资源
C.开发/运维
- 一次构建,处处运行
- 更快速的应用交付和部署
- 更便捷的升级和扩缩容
- 更简单的系统运维
- 更搞笑的计算资源利用
D.企业级
- 新浪,美团,蘑菇街…
3.去哪下
- 学技术必须要去看官网
- 仓库:就是你在本机上写项目时运行的环境打包传到仓库,之后可以喊运维去下来使用…
二.Docker安装
- Docker可以装windows下的…但是企业都是装在Linux下的
1.前提说明
- Docker支持CentOS 7(64)和CentOS 6.5(64)或更高版本
- Docker运行在CentOS7上,系统内核版本要3.10以上
- Docker运行在CentOS6.5或更高版本,系统内核版本2.6.32-431或者更高版本
- 查看自己内核
uname -r
- 查看CentOS版本信息
cat /etc/redhat-release
2.docker架构图
- Client有点像连接客户端
- 中间那块就是主机,主机上面装了一个Docker,打开连接终端就是Docker客户端,也叫Docker终端
- Registry就是仓库,从远程仓库拉下来一个,拉到本机上面就是镜像,某个镜像的实例就是容器,放在Docker,各自独立的集装箱就是一个一个的环境,第一个集装箱可以是redis,第二个集装箱可以是nginx…
3.docker基本组成
- 镜像就是模板
- 容器就是镜像的实例
- p1,p2,p3是三个不同的实例,就是三个不同的容器,但是都来自于Person这个类,这个镜像
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
- Docker镜像就是一个只读模板,镜像可以用来创建Docker容器,一个镜像可以创建很多容器
- 容器相当于对象,镜像相当于类
- Docker利用容器独立运行的一个或一组应用。容器是用镜像创建的运行实例
- 它可以被启动,开始,停止,删除。每个容器都是相互隔离的(一个集装箱),保证安全的平台
- 可以把容器看做是一个简易版的Linux环境(包括root用户权限,进程空间和网络空间等)和运行在其中的引用程序,容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面哪一层是可读可写的
- 仓库是集中存放镜像文件的场所,仓库和仓库注册服务器是有区别的,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(类似于版本号)
- 仓库分为公开仓库和私有仓库两种形式
- 最大的公开仓库是Docker Hub
- 存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云,网易云等
- Docker本身是一个容器运行载体或称之为管理引擎。我们把引用程序和配置依赖打包好行程一个可交付的运行环境,这个打包好的运行环境就是image镜像文件,只有通过这个镜像文件才能生成Docker容器。image文件可以看做是容器的模板。Docker根据image文件生成容器的实例,同一个image文件,可以生成多个同时运行的容器实例
- image文件生成的容器实例,本身也是一个文件,镜像文件
- 一个容器运行一种服务,当我们需要的时候,就可以通过dokcer客户端创建一个对应的运行实例,也就是我们的容器
- 至于仓库,就是放一堆镜像的地方,我们可以把镜像发布到仓库中,需要时候从上面拉下来就可以了
4.CentOS6.8安装
- Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL仓库,否则先检查OS的版本,然后安装响应的EPEL包
yum install -y epel-release
- 正式安装docker
yum install -y docker-io
- 安装后的配置文件
/etc/sysconfig/docker
- 启动Docker后台服务
service docker start
- docker version验证
docker version
- 其他版本的安装可以直接去官网看,上面有详细说明
5.CentOS7安装
docker官网安装指南
6.阿里云镜像加速器配置
- helloworld是docker在dockerHub上专门提供的helloworld镜像
- docker主机就是我主机,需要从仓库抓取下helloworld镜像,然后以镜像为模板,运行一个helloworld容器实例进行验证
- 但是直接连接docker Hub很慢,因为是国外的网站…
- 可以改成阿里云镜像或者网易云之类国内的
阿里云容器镜像
- 注册
- 获取加载器地址连接
- 登陆阿里云开发者平台
- 获取加速器地址
- 配置本机docker运行镜像加速器
- 重新启动Docker后台服务
systemctl docker restart
- linux系统下配置完加速器需要检查是否生效
ps -ef | grep docker
- centos7.x用docker info查看
7.helloworld镜像
- 启动docker后台容器
- docker run hello-world
- run干了什么
- 由于本地没有hello-world镜像,会下载一个hello-world镜像,并在容器内运行
- 容器没有就去找hello world的镜像,也没有就去阿里云上拉去下这个镜像拉到本地再生成再运行
8.运行底层原理
- Docker运行机制
- Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器
- 容器是一个运行时环境,就是我们说到的集装箱
- 为什么Docker比VM(虚拟机)快
- docker有着比虚拟机更少的抽象层,由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU,内存利用率上docker将会在效率上有明显优势
- docker利用的是宿主机的内核,而不需要Guest OS,因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引寻,加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟
- 从这里可以引出一个面试题:说下容器虚拟化技术和虚拟机的区别,右上角这个图对比可以说下
三.Docker常用命令
1.帮助命令
docker version
docker info
docker --help
2.镜像命令
- 镜像相当于类,一个镜像可以生成多个容器实例
- 蓝色的大海里面-宿主机系统windows10
- 鲸鱼-docker
- 集装箱-容器实例 from 来自我们镜像模板
A.列出本地主机上的镜像
- 同一仓库源可以有多个TAG,代表这个仓库源的不同个版本,我们使用REPOSITORY:TAG来定义不同的镜像,如果你不指定一个镜像的版本标签,例如你只使用ubuntu,docker将默认使用ubuntu:latest镜像
docker images //查看可以执行的镜像列表
镜像的仓库源 镜像的标签 镜像ID 镜像创建时间 镜像大小
-a:列出本地所有的镜像(含中间映像层)
-q:只显示镜像ID
--digests:显示镜像的摘要信息(备注)
--no-trunc:显示完整的镜像信息
B.查询镜像
- 去hub,docker.com上查找的
docker search [OPTIONS] 镜像名字
--no-trunc:显示完整的镜像描述
-f=stars=xx:列出收藏数不小于指定值的镜像
--automated:只列出automated build类型的镜像
C.下载镜像
docker pull 镜像名字[:TAG]
docker pull tomcat等价于docker pull tomcat[:lastest]//最新版
D.删除镜像
docker rmi [OPTIONS] 镜像名
-f:强制删除
docker rmi [OPTIONS] 镜像名1:TAG 镜像名2:TAG
docker rmi -f ${docker images -qa}
- 猜猜是否会有docker commit/docker push,根据git学习心得来想想?肯定有!
3.容器命令(上)
- 拉了一个centos下来发现比tomcat还小,这里的centos只包含核心的东西,什么图形界面库之类的都不存在…
A.新建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS说明[常用]:有些是一个减号,有些是两个减号
--name="容器新名字":为容器指定一个名称
-d:后台运行容器,并返回容器ID,也即启动守护式容器
-i:以交互模式运行容器,通常与-t同时使用
-t:为容器重新分配一个伪输入终端,通常与-i同时使用
-P:随机端口映射
-p:指定端口映射,有以下四种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
docker run -it id号
B.列出当前所有正在运行的容器
docker ps
OPTIONS说明[常用]
-a:列出当前所有正在运行的容器+历史上运行过的
-l:显示最近创建的容器
-n:显示最近n个创建的容器
-q:静默模式,只显示容器编号
--no-trunc:不截断输出
C.退出容器
- 两种退出方式
exit 容器停止退出
ctrl+P+Q 容器不停止退出
D.启动容器
docker start 容器ID或者容器名
E.重启容器
docker restart 容器ID或者容器名
F.停止容器
docker stop 容器ID或者容器名
G.强制停止容器
docker kill 容器ID或者容器名
H.删除已停止的容器(用docker ps查不到了)
docker rm 容器ID或者容器名
//一次性删除多个容器
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
4.容器命令(下)
A.启动守护式容器
- 我们一般用下面的命令启动centos,但是我们不想交互,后台跑就行了
docker run -it centos
- 后台运行是这个命令
docker run -d centos
- 但是注意用这个命令启动的用docker ps是看不到的
- docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令(比如top,tail),就是会自动退出的
- 这是docker机制问题,比如你的web容器,nginx为例,正常情况下,我们配置启动服务需要启动响应的service即可,例如service nginx start,但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀因为他觉得他没事可做了
- 最佳的解决方案是,将你要运行的程序以前台进程的形式运行
B.查看容器日志
docker logs -f -t --tail 容器ID
//-t是加入时间戳
-f跟随最新的日志打印
--tail数字 显示最后多少条
- 执行这个是说明前台每2s打印hello zzyy一次,这样就不会停止了
docker run -d centos /bin/sh -c "while true;do echo hello zzyy;sleep 2;done"
C.查看容器内运行的进程
docker top 容器ID
//linux用top查看自己的进程,可以把容器看成简易版的linux环境
D.查看容器内部细节
docker inspect 容器ID
E.进入正在运行的容器并以命令行交互
docker exec -it 容器ID bashShell
重新进入docker attach 容器ID
- 上述两个区别
- attach:直接进入容器启动命令的终端,不会启动新的进程
- exec:是在容器中打开新的终端,并且可以启动新的进程
- exec功能更加强大,可以隔山打牛
- exec会启动一个新的bash,exit只会退出当前的bash,不会终止容器
- 使用attach进入容器后,exit会退出容器,容器会被关闭
F.从容器内拷贝文件到主机上
docker cp 容器ID:容器内路径 目的主机路径
//linux也有cp命令
四.Docker镜像
1.镜像是什么
A.UnionFS(联合文件系统)
- 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,运行时,库,环境变量和配置文件
- UnionFS(联合文件系统):Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统上
- Union文件系统是Docker镜像的基础
- 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
- 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
B.Docker镜像加载原理
- docker镜像实际上由一层一层的文件系统组成,这样层级的文件系统UnionFS
- bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动会加载bootfs文件系统,在Dokcer镜像的最底层是bootfs,这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
- rootfs(root file system),在bootfs纸上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等
平时我们安装进虚拟机的CentOS都是好几个G,为什么docker才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库,因为底层直接用Host的kernel,自己只需要日工rootfs就行了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs
C.分层的镜像
- 我们在pull下载时,看到docker的镜像是一层一层在下载
- 为什么pull下来的tomcat400多M?这个tomcat多半内部有多层文件构成,一层在一层上面打包,就像上图一样
D.为什么Docker镜像要采用这种分层结构
- 共享资源
- 比如,有多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享
E.镜像的特点
- Dokcer镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为“容器层”,”容器层”之下都叫“镜像层”
2.镜像commit操作补充
- docker commit提交容器副本使之成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者"容器ID要创建的目标镜像名:[标签名]
A.案例演示
- 从Hub上下载tomcat镜像到本地并成功运行
docker run -it -p 8080:8080 tomcat
//-p 主机端口:docker容器端口
-P 随机分配端口
i 交互
t 终端
//看看访问ip:8080能否访问到tomcat
- 故意删除上一步镜像生产tomcat容器的文档
//进入到/usr/local/tomcat/webapps下
rm -rf docs
- 也即当前的tomcat运行实例是一个没有文档内容的容器,以它为模板commit一个没有doc的tomcat新镜像plyamker/tomcat02
docker commit -a="playmaker" -m="tomcat without docs" id playmaker/mytomcat:1.2
//运行docker images你会发现多了一个mytomcat
//docker rm -f $(docker ps -q) 关闭所有正在运行的容器
//docker ps没有一个在运行的容器
- 启动我们的新镜像并和原来的对比
docker run -it -p 7777:8080 playmaker/mytomcat:1.2
//然后访问一下
docker run -it -p 8888:8080 tomcat
- 不同镜像运行了不同的容器实例
docker run -d -p 6666:8080 tomcat //没有打印日志,安安静静的运行