一.简介html
Docker是一个使用Go语言开发的开源的应用容器引擎,让开发者能够打包他们的应用以及依赖包到一个可移植的容器中,而后发布到任何流行的机器上。Docker的发展速度和火爆程度着实使人惊叹,一发不可收拾,造成了席卷整个IT界的新浪潮。学完本课程你将了解到什么是docker,docker的思想以及诸如镜像,仓库,容器等核心概念。你将学会怎样运行一个容器,如何搭建私有仓库,怎么写dockerfile以及怎样把本身的应用放到容器中运行。mysql
Docker为何这么火?它确实解决了大部分企业的痛点,好比快速的持续集成、服务的弹性伸缩、部署简单、解放运维,更重要的是为企业节省了机器资源。目前有很是多的公司在生产环境中大规模的使用Docker,京东618在2015年的618大促中,大胆启用了基于Docker的容器技术来承载大促的关键业务,在2016年11月份,阿里超大规模Docker化之路,在2015年的3月份,腾讯万台规模的Docker应用实践。Docker已成为IT从业人员的必备技能,无论你是从事开发、测试、运维,在从此的工做中,都会接触到Docker。nginx
二.什么是Dockergit
1.Docker历史github
2010 dotCloud PAASweb
2013年docker开源spring
2014年6月,Docker1.0sql
2014年7月,C轮$4000万docker
2015年4月,D轮$9500万数据库
至今Docker1.13
2.什么是Docker?
Docker是一个用来装应用的容器,就像杯子能够装水,笔筒能够放笔,书包能够放书同样,你能够把Hello World放到Docker里,你能够把网站放到Docker里,你能够把任何你想获得的程序放到Docker里。
Docker is the world's leading software containerization platform,Docker是世界领先的软件容器化平台。
Docker公司开发的,开源,托管在github。
跨平台,支持Windows、Macos、Linux。
三.理解Docker
1.Docker思想
a.集装箱:把运行程序放到新的机器上去,Docker集装箱保证咱们程序无论放在哪均可以正常运行。
b.标准化:
运输方式标准化(Docker运输程序它有一个超级码头,任何一个地方须要货物的时候,都由鲸鱼送到超级码头,而后再由鲸鱼把货物送到目的地去。对应技术来讲,假如你要把你的台式机上的应用部署到你的笔记本上,用Docker就标准化了这个过程,只需在台式机上执行一个命令,把鲸鱼派过来,把程序送到超级码头去,再在你的笔记本上执行一个Docker命令,由鲸鱼把程序从超级码头送到笔记本上去)
存储方式标准化(把程序拷贝到笔记本上的时候,得给它指定一个目录,还得记住这个命令,由于下次有改动一些东西的时候,可能还须要继续往这传,有了Docker以后就不用了,由于存储方式标准化,不须要关心应用存储在什么地方,要运行它或中止它的时候,只需执行一个命令就能够了)
API接口标准化(Docker提供了一系列的resful API接口,包含了对Docker应用的控制(启动、中止、查看、删除等),如当你要启动你的程序的时候,你可能须要执行tomcat startup命令,中止的时候执行shutdown命令,若是不是tomcat命令,须要用别的命令来控制它。有了Docker接口标准化后,只须要执行一样的命令就能控制全部的应用。
c.隔离
在用虚拟机时,有自已可用内存、CPU、硬盘,彻底感受不到外面主机的存在,Docker差很少,不过它的技术更加的轻量,能够实现快速的建立和销毁。好比你建立一个虚拟机可能要等个几分钟,而建立Docker只须要1秒。最底层的技术实际上就是Linux的一种内核的限制机制,叫作LXC(LXC是一种轻量级的容器虚拟化技术,它最大效率的隔离了进程和资源,经过CGoup、NameSpace的限制,隔离进程组所使用的物理资源,好比CPU、Memory、IO等),其实这个机制早在七、8年前就加到了Linux内核了,直到2013年Docker出世时它才火起来。云计算、敏捷开发、高频率的弹性伸缩需求、IT行业这些年的长足发展造就了Docker的火爆。
2.Docker解决了什么问题?
a.Docker解决了运行环境不一致带来的问题。
若是一个应用要能运行起来,须要最底层的操做系统,操做系统上它依赖JDK、Tomcat、代码、配置文件。
1).操做系统变了可能致使程序运行失败,好比个人程序调用了系统的某些命令,换了个系统调不起来了。
2).JDK版本也可能致使程序运行失败,好比Class文件是JDK1.7编译的,机器上装了一个1.6的JDK,就会出现Class版本识别不了。
3).Tomcat版本也可能致使失败,好比旧版本的配置在新版本中再也不支持了。
4).代码更是有可能了,好比你的代码依赖了磁盘D盘的一个文件,或者用了系统的环境编码等等。
5).配置也是同样,要不是你的配置是和系统相关的,换了个环境就跑不起来
Docker把操做系统、JDK、Tomcat、代码、配置都一个个的给放到集装箱里,再打包放到鲸鱼上,由鲸鱼给咱们送到服务器上,在你的机器上怎么运行,在服务器上也将怎么运行,不会有任何的问题。
b.系统好卡,哪一个哥们又写死循环了?!
若是有和别人共用服务器呢,可能会有这样的体会,莫名其妙的发现程序挂了,一查缘由,要不是内存不够,要不是硬盘满了,或者忽然发现某一个服务变慢了,甚至终端都比较卡,Linux自己是一个多租户的操做系统,能够供多我的使用,怎么办呢?用Docker,Dockder的隔离性就彻底解决了这个问题。它是怎么解决的呢?若是把你们的程序都放到Docker里运行,就算别人的程序仍是死循环,疯狂吃CPU,或者是疯狂的打日志把磁盘占满,或者是占用大量的内存,内存泄露,都不会致使别人的程序运行错误,只会致使自已的程序错误,由于Docker在启动的时候就给它限定好了最大使用的CPU、内存、硬盘,若是它超过了,就杀掉。
c.双十一来了,服务器撑不住啦!
你们知道,业务系统的业务量不必定是平均的,特别是电商系统,每一年老是有那么几天,业务量会比平时多几倍,甚至几十倍,若是按平时的量去准备服务器,到双十一确定撑不住,但要是按双十一的规模去准备服务器,平时就是极大的浪费,因此就只能在节日前临时扩展机器,过完节再把多余的节点下线,这就给运维带来很是大的工做量,一到这种节日就须要在各类机器上部署各类各样的服务,你们知道,我启动一个程序,我要装操做系统、JDK、Tomcat等好多好多东西,还有可能启不来,还要调试,这是一个很是繁重的工做。Docker让这一切变得很是美好了,只须要点一下鼠标,就能够立马从10台服务器变成100台,甚至1000、1000台,都是分分钟的事,由于Docker无论在哪台机器上,无论要运行什么服务,都是用标准的方式把咱们的程序运过来,再用标准的方式把它运行起来,这样就能够作到,我只要在每台机器上执行一两条命令就可让程序跑起来,而且不用担忧会不会有问题。
Docker的标准化让快速扩展、弹性伸缩变得简单。
四.走进Docker
1.Docker里有三个核心词汇:Build、Ship、Run
镜像就是集装箱,仓库就是超级码头,容器就是运行程序的地方,用Docker运行一个程序的过程就是去仓库把镜像拉到本地,而后用一条命令把镜像运行起来,变成容器。
Build:构建,就是构建镜像。
Ship:运输,运输镜像,从仓库、主机上运输。
Run:运行的镜像,就是一个容器。
2.Docker镜像
镜像的英文名是image,前面咱们讲到了集装箱,想像一下,鲸鱼驮着的全部集装箱都是一个镜像,那么从本质上来讲,镜像究竟是什么呢?
其实镜像就是一系列的文件,它能够包括咱们运行程序的文件,也能够包括咱们应用运行环境的文件,既然都是文件,Docker把它保存到本地了吗?答案是确定的。可是它以什么格式保存的呢?说到镜像的存储格式,就要提到Linux的存储技术,叫作联合文件系统Union File System(UFS),它是一种分层的文件系统,它能够将不一样的目录挂到同一个虚拟文件系统下。
好比test1目录下有三个文件夹,test2目录下有一个文件README、两个文件夹,联合文件系统就是能够在同一个文件夹下看到这里的五个文件夹和一个文件README,也就是这两个文件夹的集合。
经过这样一种方式呢,联合文件系统就能够实现文件的分层,好比test1能够看作第一层,test2能够看作第二层,每一层有每一层的文件,Docker就是利用了这种分层的概念来实现了镜像存储,下面就是镜像的存储格式图。
很明显地能够看到这张图是分层的,下面有一层,上面也是一层一层的,一个个集装箱挪在一块儿,这就是镜像最直观的存储形式,这个例子它的最底层是操做系统的引导,上面是具体的Linux操做系统,再上面是相关的软件(若是是咱们的程序,那可能就是JDK、Tomcat),最上面一层先忽略不看,是下面讲容器时要看到的一种。
Docker镜像每一层文件系统都是只读的,把每一层加载完成以后呢,这些文件都会被看做是同一个目录,至关只有一个文件系统,Docker的这种文件系统被称做为镜像。
3.Docker容器
容器的本质就是一个进程,为了便于理解,能够想像成一个虚拟机,每一个虚拟机都有自已的文件系统,能够把整个这一部分看做是容器的文件系统,至关于虚拟机里面全部的文件系统,它和虚拟机的区别是它这里的文件系统是一层一层的,而且这下面的N层都是只读的,只有上面一层是可写的。为何要有可写的这一层呢?想想若是你们的程序运行起来,势必会要写一些日志,写一些文件,或者对系统的某一些文件作一些修改,这是大部分程序都有的需求,因此容器在最上面一层建立了一个可读可写的文件系统。
若是程序在运行过程当中要写一个镜像里面的一个文件,这种状况将发生什么呢?由于镜像的每一层都是只读的,因此它在写这个文件以前会把这个文件这一层拷到文件的最上一层,而后再对它进行修改,修改了以后,当咱们的应用读一个文件的时候会从顶层开始查找,若是没有才会找下一层,由于咱们这个文件已被拷到最上一层了,因此会在最上一层找到它最新的内容。因为容器的最上一层是能够修改的,而镜像是不能够修改的,这样就能够保证同一个镜像能够生成多个容器独立运行,而它们之间没有任何的干扰。
4.Docker仓库
构建镜像的目的就是为了在其它的机器或环境运行个人程序,那我就须要把个人镜像传到目的地去,我该如何完成传输过程?这就用到了Docker仓库,我须要先把个人镜像传到Docker仓库里去,目的地再从仓库把个人镜像拉过去,这就完成了这样的一个传输过程。谁提供Dockder仓库呢?确定有一个中央服务器提供给我地址去访问它,是谁提供了这样的服务呢?Docker自已就提供了,提供服务的地址就是:hub.docker.com。但这这个网站在开始的时候在国内访问不了,如今虽然能够访问了,可是下载镜像的速度很是的慢。为了解决这个问题,国内不少的公司作自已的仓库,比较知名的仓库有163yun.com/product/repo(网易蜂巢的一个镜像中心),这里有一些咱们经常使用的镜像,这些仓库都是其它公司给咱们提供好的中心,咱们能够把镜像传过去,若是个人镜像比较私密,不想让别人看到,只是内部的人使用的话,Docker也支持咱们自已搭建一个镜像中心,好比咱们是一个内网的环境,能够把咱们的镜像中心在内网搭建起来,最后咱们在镜像的传输过程放到内网的Docker仓库里就好了。
五.Docker安装
1.Windows安装
Docker对Win10作了原生的支持。
附:boot2docker.iso下载地址:http://pan.baidu.com/s/1qYyc0ag
运行docker version,输出Client和Server信息,则说明已安装OK,以下所示:
2.MacOS安装
3.Linux安装
Redhat&CentOS的安装详见《》。
Docker是在Ubuntu上开发的,对Ubuntu支持是最好的,下面以Ubuntu为例演示安装过程。
a.检查内核版本,检查其值是否大于3.10
切入到root用户,将apt-get更新到最新版本。
b.apt-get install -y docker.io安装Docker
这种安装方式是用系统自带的安装包,可能不是Docker的最新版本,如要安装Docker最新版本,可使用curl -s https://get.docker.com|sh
这句话的意思就是把get.docker.com网页的内容拿过来,执行sh,这是Docker提供的一种安装方式。
c.service docker start启动Docker
d.执行docker version查看docker是否安装OK
六.Docker初体验
1.第一个Docker镜像
docker pull [OPTIONS] NAME[:TAG]:从Docker远程仓库拉取镜像到本地。NAME是要拉取的镜像的名称,后面的TAG是可选的,若是不加默认是:laster,表示镜像的最新版本,用TAG就会下载TAG指定的版本。OPTIONS是拉取的一些参数。
docker images [OPTIONS] [REPOSITORY[:TAG]]:查看本机有哪些镜像,也能够验证pull是否成功,其中,REPOSITORY表示镜像的名称。
实例:pull hello-world镜像
在此设置使用docker国内镜像DaoCloud,右键点击桌面右下角的docker图标,选择Settings。
在Daemon标签下的Registry mirrors列表中加入下面的镜像地址:http://141e5461.m.daocloud.io,点击 Apply,Docker服务将会自动重启生效。
这块相关资料能够参考《在windows系统下如何查找域名对应IP地址?》、《Docker获取镜像报错 docker: Error response from daemon》。
而后,再pull hello-world镜像。
REPOSITORY:镜像的名字
TAG:latest,最新版
IMAGE_ID:是一个64位的字符串,它能够惟一的标识咱们的镜像,这里只显示16位,后面在显示时自动被截掉了
CREATED:建立时间,说明这个hello-world在五周之前被修改过
SIZE:大小,只有1.84k
若是是Linux系统,则按以下操做设置国内镜像:
1.修改或建立daemon.json文件:vi /etc/docker/daemon.json
将如下配置写入到文件中,保存并退出:
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
2.重启docker:systemctl restart docker.service
2.第一个Docker容器
docker run [OPTIONS] IMAGE[:TAG][COMMAND][ARG...]:IMAGE表示镜像的名字,COMMAND表示这个镜像在运行起来的时候要执行什么命令,ARG表示这条命令所依赖的参数。
代表运行成功。
最左边Client是咱们在本机的Docker Client,就是咱们执行命令的时候Docker Client的部分,中间这部分DOCKER_HOST也是在咱们本机的Docker服务(Docker Daemon),最右边是Docker的远程仓库。
Docker Client输入docker pull,将会向Docker Daemon发起pull命令,告诉Docker Daemon要拉取某一个镜像,Docker Daemon会先在本机Images去检查镜像是否存在,若是存在且版本就是你所要拉取的版本,就不会作任何的操做,若是不存在将会去Docker仓库找咱们须要拉取的镜像名字,若是找到了就会从Docker仓库传到咱们本地,把咱们要的镜像拉到本地来。
Docker Client输入docker run,第一步也是把咱们的命令发到本地的Docker Daemon,Docker Daemon会检查这个镜像是否在本机已经存在,若是不存在,将会执行一个至关于Docker pull的过程去远端Docker仓库把镜像下载回来,而后经过必定的方式把这个镜像运行起来,变成Docker容器。
七.Docker运行Nginx
1.运行nginx镜像
Nginx是一个Web服务器,是一个持久运行的容器,上面咱们的hello-world是前台运行的(由于咱们能看到它打印出的运行结果),运行Nginx能够选择前台运行,也能够选择后台运行,若是一个前台运行的镜像,能够用Ctrl+C结束进程,进程结束了,镜像也就结束了,因此说Nginx最好的运行方式是后台运行。成功运行Nginx后,能够进入容器内部看看Nginx容器究竟是什么样的。
docker run -d library/nginx命令的返回字符串表明容器的ID,docker ps看到的CONTAINER ID是同样的。
-d表示后台运行,若是想了解更到docker run参数,能够运行docker run --help查看。
docker exec --help能够看到命令的详细解释,这就是在一个运行的容器中运行一个命令。
docker exec -it 30d bash
2.docker网络
a.网络类型
bridge模式
docker的隔离性,网络也是隔离性的一部分,Linux用了namespace来进行资源的隔离,好比PIDNameSpace就是用来隔离进程的,Mount NameSpace用来隔离文件系统的,Network NameSpace是用来隔离网络的,每个Network NameSpace都提供了一份独立的网络环境,包括网卡、路由、iptable规则等等,都是与其它的Network NameSpace隔离的,Docker容器在默认状况下都是分配一个独立的Network NameSpace,也就是网络类型中的bridge模式。
Host模式
若是启动容器的时候,指定使用Host模式,那么这个容器将不会得到一个独立的Network NameSpace,而是和主机共同使用一个,这个时候,容器将不会虚拟出自已的网卡,配置自已的IP等等,而是会使用宿主机上的IP和端口,也就是在Docker里使用网络的时候和在主机上使用网络是同样的。
None模式
Docker将不会和外界的任何东西进行通讯。
b.端口映射
在使用bridge模式的时候,就涉及到了一个问题,既然它使用了网络有独立的NameSpace,这就须要一种技术使容器内的端口能够在主机上访问到,这种技术就是端口映射。Docker能够指定你想把容器内的某一个端口能够在容器所在主机上的某一个端口作一个映射,当你在访问主机上的这个端口的时候,其实就是访问容器里面的那个端口。
docker run --help能够看到,-p会开放一个容器的端口到主机上,默认是空的,-P是开放全部的端口到一个随机的端口。
如上先把原来的nginx容器停掉,再指定映射端口启动,并检查8080端口确实已被占用,这时经过浏览器输入localhost:8080便可正常访问到nginx,以下所示:
咱们再用-P方式来运行一下。
用docker ps能够看到端口映射的状况,在我本机上开了一个32768的随机端口映射到容器里的80端口,用netstat -ano|findstr "32768"检查一下实际端口也是启动了。
此时用localhost:8080就不能够访问了,用localhost:32768能够正常访问。
八.Docker化Java web应用
1.制做自已的镜像
Dockerfile:告诉Docker,我要怎么样来制做个人镜像,我要制做镜像每一步操做是什么。
docker build:用来执行Dockerfile里面所描述的每一件事情,最终会把Docker镜像构建出来。
Jpress:http://jpress.io/,开源的博客平台,我这里用我自已的工程SpringMVC,下载地址:https://bijian1013.iteye.com/blog/2307353
2.将下载下来的SpringMVC配置到Eclipse中,将其Export成war包
将生成的SpringMVC.war包拷贝到E:\develop目录下
3.下载基础library/tomcat镜像
docker pull library/tomcat
4.以上面tomcat基础镜像为起点,制做镜像
编写Dockerfile
from library/tomcat MAINTAINER bijian xxx@126.com COPY SpringMVC.war /usr/local/tomcat/webapps
构建镜像,命令:docker build E:\develop
若是不知道命令参数时,能够用docker build --help命令查看参数。
5.运行自已的镜像
命令:docker run -d -p 8888:8080 springmvc
此时,在浏览器上输入http://localhost:8888/,能正常打开tomcat主页,代表Tomcat启动成功。
输入http://localhost:8888/SpringMVC/greet,页面输出内容以下:
运行正常,在这里咱们的SpringMVC项目不依赖数据库,假如咱们的项目还依赖mysql,那么能够经过pull library/mysql下载library/mysql镜像。
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=000000 -e MYSQL_DATABASE=springmvc library/mysql命令运行mysql镜像,docker restart 7532592dac95重启tomcat应用springmvc。
九.小结
1.集装箱,标准化,隔离
2.镜像、容器、仓库(BUID、SHIP、RUN)
构建镜像,运行容器,镜像经过仓库来传输,Docker集装箱的思想就体如今镜像上,咱们的镜像是分层的,一层一层的,每一层的东西都是固定的,一个镜像打好后,就好像一个大大的集装箱,它里面的东西是固定的文件,不会发生变化。
Docker标准化思想在咱们使用各类Docker命令时应该也会体会到,无论是在启动一个镜像的方式,仍是在下载和运行一个镜像的时候,都会发现咱们所作的操做是基本差很少的。
Docker的隔离思想,网络隔离、进程隔离、磁盘隔离,容器运行起来,就有自已的进程空间、磁盘、网络。
3.docker命令pull,build,run,stop,restart,exec...
docker pull:下拉镜像
docker build:构建镜像
docker run:运行一个容器
docker stop:中止容器
docker restart:重启一个容器
docker exec:进行容器的内部