看完此文,妈妈还会担忧你docker入不了门?

本文在我的技术博客不一样步发布,详情可猛戳
亦可扫描屏幕右侧二维码关注我的公众号,公众号内有我的联系方式,等你来撩...java

  上周对象忽然心血来潮说想养个小宠物,我问想养啥她又说随便,你看着办!!!这我真的比较难办啊!可是我们程序员能有个对象就不错了,还不赶忙宠着,我只能照办咯!mysql

  我去到了一家宠物店,半天也没有找到合适的目标。正在我犹豫彷徨之时,看到了老板门口鱼缸里面的金鱼游来游去还挺顺眼!因而我问老板
  我:老板,金鱼多少钱?
  老板:加鱼缸一块儿100块钱不讲价!
  我:这...便宜一点咯!
  老板:小伙子看你骨骼惊奇,定是个养鱼的奇才,2块钱卖给你吧!可是鱼缸可不能给你!
  我:那,你帮我打包一条吧,帮我拿个袋子装着就行了!linux

  因而我兴高采烈的拎着小金鱼就回家了,找了个大罐子养着!对象看到我买的小金鱼后露出了幸福的笑容~
  次日早上对象把我从睡梦中摇醒:“嘤嘤嘤,人家的小鱼动不了了,你赔~~~ ”。因而我很愤怒的跑去宠物店找老板索赔!
  我:大家家卖的鱼有问题,回去就不行了!
  老板:不可能,昨天在咱们这都活蹦乱跳的!
  我:就是大家家的鱼有问题!
  老板:确定是你本身买的鱼缸有问题!
  我:手持两把锟斤拷,口中疾呼烫烫烫。
  老板:脚踏千朵屯屯屯,笑看万物锘锘锘?nginx

  这一幕,似曾相识!像极了咱们在开发中
  测试:xx,你的代码在生产环境上运行有问题。
  我:不可能,我本地都运行得好好的。
  测试:你本身上生产环境上看。
  我:我不看,个人代码在本地没问题,确定是运维的锅,你去找运维!git

  或许不少开发人员都有过上面的经历,程序在本地运行都很正常,一上到生产环境就崩了。这是由于程序跟小金鱼同样也会“水土不服”!而致使程序水土不服的缘由通常就是环境配置的差别!加上如今互联网高并发、大流量的访问,一个应用每每须要部署到集群的多台机器上,而且集群扩容缩容的需求也比较频繁。若是按照传统的方式部署,那每一台服务器上都须要装各类软件...而后进行各类配置...我仿佛看到了“工做996,生病ICU”在向运维工程师招手!程序员

  那有没有一种方案不只能屏蔽环境的差别,而且还能快速部署呢?既然“水土不服”那我把程序及整个“水土”都打包迁移,就看你服不服。而docker就是这样的一种让你服技术!web

  昂,上面的对象是我本身new的(* ̄︶ ̄)...redis

Hello Docker

  Docker是什么呢?百度百科是这样跟我说的:Docker 是一个开源的应用容器引擎,让开发者能够打包他们的应用以及依赖包到一个可移植的镜像中,而后发布到任何流行的 Linux或Windows 机器上,也能够实现虚拟化。容器是彻底使用沙箱机制,相互之间不会有任何接口。sql

  这段话已经很归纳的描述了docker是什么,docker能干吗,docker的基本特性!相信刚开始接触docker的你跟我也同样,看了几遍都很懵逼!不要紧,看彻底文再回头看这段话,或许就有不同的体会了!咱们先看看docker官方给出的“定妆照”
docker

  若是非要我用一句话描述这张图片,还在上幼儿园的我会说:“一条可爱的鲸鱼背着多个集装箱,畅游在大海里 ”!而如今我会说:“docker是一个运行在操做系统上的软件,这个软件上面能够运行多个相互隔离的容器”!不一样的表述,同一个意思!这条可爱的鲸鱼就是我们的docker,而大海就是咱们的操做系统,多个集装箱就是在docker上运行的容器!什么是容器我们后面会说~

  假如你想漂洋过海来看我,你能够选择本身造一条船,这样你就得本身备足不少干粮,还得准备不少一些其余的必需品才能出发!可是如今有一条鲸鱼游过来对你说,我这里有不少集装箱,里面有你所须要的一切,你选一个适合你的进来就能够了,我会带你乘风破浪的!

  看到这里,你是否对docker有个初步的印象了呢?至少知道了:一、docker是什么?二、为何须要docker?

与传统虚拟机对比

  前面咱们说过docker能够实现虚拟化,那docker与咱们平时用的虚拟机有什么区别和联系呢?在那些年咱们还买不起云服务器的时候,若是咱们想学linux那就得先安装一个建立虚拟机的软件,而后在软件上面建立虚拟机,而后分配内存、分配磁盘、安装linux操做系统等等一系列的操做,而后等个分把钟让虚拟机运行起来~
  为何传统虚拟机启动会那么慢呢?由于传统虚拟机技术是虚拟出一套硬件后,在其上面运行一个完整的操做系统,而后在该系统上面再运行所须要的应用程序,而且虚拟机的资源须要提早分配,一旦分配这些资源将所有被占用。可是docker容器内的应用程序是直接运行于宿主的内核,容器没有本身的内核,更加不会对硬件进行虚拟。所以docker容器比传统的虚拟机更为轻便!可是docker容器技术也是参考虚拟机一步一步的迭代优化过来的!咱们来看看官方给出的docker容器和传统虚拟机的对比图:

  图中也能看出来,docker就是一个运行在操做系统上的软件!之后若是想在windows上面学习Linux,只须要在本地安装一个windows版本的docker,而后看完本文的剩下的部分,就能轻轻松松的玩转linux啦!不过在windows上安装docker也须要先安装一个虚拟机~

基本组成要素

  前面对docker的基本概念有了个大体印象,可是到目前为止,可能你对docker的认识还比较空泛,那下面部分咱们就从docker的基本组成要素来更深刻的走进docker!docker是一个client-server的结构!先看看官网给出的架构图:

  这张图里面归纳了docker的全部的元素!咱们就逐一分析docker客户端、docker服务、仓库、镜像、容器等概念!

docker客户端

  最左边是docker的客户端,相似咱们操做mysql的工具navcat,只不过咱们这里的是没有图形化界面的命令终端。docker客户端是用户与docker服务交互的窗口!咱们能看到图中就是各类操做的命令!

docker服务

  中间的是docker后台运行的服务,一个称为docker daemon的守护进程。能够理解为咱们mysql的服务,咱们的操做命令都是在这部分进行处理!docker deamon监听着客户端的请求,而且管理着docker的镜像、容器、网络、磁盘(图中只列出了镜像与容器)等对象。一样,docker的客户端与服务能够运行在同一机器上,也能够用某台机器上的客户端远程链接另外一台机器上的docker服务,这跟咱们的mysql同样的呢。

仓库

  右边部分是注册仓库,在远古时代作开发的都知道,咱们之前须要一个第三方包的时候须要去网上下载对应的jar包,很麻烦不说,还容易下的包是不稳定的版本。有了maven以后,咱们只要在maven配置文件中引入对应的依赖,就能够直接从远程仓库中下载对应版本的jar包了。docker中的仓库与maven的仓库是一个概念,能够远程下载经常使用的镜像,也能够push包到远程仓库(如图中的redis、nginx等镜像),同一个镜像又能够有多个版本,在docker中称为tag!

镜像&容器

  前面咱们有屡次提到镜像和容器,这是docker里面很核心的两个概念。那镜像和容器分别是什么呢?镜像和容器的关系是什么呢?

  镜像
  官方给出的定义是:docker镜像是一个只读模板,能够用来建立docker容器。镜像是一种轻量级的、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。它包含运行某个软件所须要的全部的内容,包括代码、运行时、库、环境变量、配置文件等。咱们开发的web应用须要jdk环境、须要tomcat容器、须要linux操做系统,那咱们能够把咱们所须要的一切都进行打包成一个总体(包括本身开发的web应用+jdk+tomcat+centos/ubuntu+各类配置文件)。打包后的镜像在某台机器上能运行,那它就可以在任何装有docker的机器上运行。

  任何镜像的建立会基于其余的父镜像,也就是说镜像是一层套一层,好比一个tomcat镜像,须要运行在centos/ubuntu上,那咱们的tomcat镜像就会基于centos/ubuntu镜像建立(在后面的操做部分咱们能够经过命令查看),这样的结构就相似于咱们吃的洋葱,若是你愿意一层一层一层地剥开个人心~

  容器
  官方给出的定义是:docker的容器是用镜像建立的运行实例,docker能够利用容器独立运行一个或一组应用。咱们可使用客户端或者API控制容器的启动、开始、中止、删除。每一个容器之间是相互隔离的。上一步咱们构建的镜像只是一个静态的文件,这个文件须要运行就须要变为容器,咱们能够把容器看作是一个简易版的linux系统和运行在其中的应用程序!就是前面看到的鲸鱼背上的一个一个的集装箱,每一个集装箱都是独立的!

  镜像与容器关系
  上面的概念很抽象,能够理解为容器就是镜像的一个实例,相信你们都写过相似下面的代码:

public void Dog extends Animal{  
    ......
}  
......
Dog dog = new Dog()

  咱们在代码中定义了一个Dog类,这个类就至关于一个镜像,能够根据这个类new出不少的实例,new出来的实例就至关于一个个的容器。镜像是静态的文件,而容器就是有生命的个体!Dog类能够继承父类Animal,若是不显式的指定继承关系,Dog类就默认继承Object类。一样上面也说到过docker中的镜像也有继承关系,一个镜像能够继承其余的镜像建立,添加新的功能!

  看到这里的你是否是对docker有了更多的了解了呢?咱们再回头看看百度百科对docker的描述,可能你又会有更深的印象:
  Docker 是一个开源的应用容器引擎,让开发者能够打包他们的应用以及依赖包到一个可移植的镜像中,而后发布到任何流行的 Linux或Windows 机器上,也能够实现虚拟化。容器是彻底使用沙箱机制,相互之间不会有任何接口。

容器数据卷

  上面说到容器是一个简易版的linux系统和运行在其中的应用程序,那咱们的应用程序产生的数据(好比操做日志、异常日志、数据)也是在容器内的系统中存放的,默认不会作持久化,咱们能够进入到容器中查看。可是万一有一天,docker这条鲸鱼不满人类的压迫,反抗了...老子打烂你的集装箱!

  随着容器的关闭,容器内的数据也会丢失,从新开启的容器不会加载原来的数据(简单说就是容器从新启动又是另一个实例了)。那对容器内的数据须要持久化到宿主机上就颇有必要了,这就须要了解咱们的容器数据卷~

  容器数据卷的设计目的就是作数据的持久化容器间的数据共享,数据卷彻底独立于容器的生命周期,也就是说就算容器关闭或者删除,数据也不会丢失。简单点说就将宿主机的目录挂在到容器,应用在容器内的数据能够同步到宿主机磁盘上,这样容器内产生的数据就能够持久化了。关于容器卷的命令咱们后面会有操做实例!

命令操做

  上面说了那么多,下面就到了我们的实操环节啦!这一节的内容会经过一些经常使用的命令让你们更进一步的了解docker,注意!!这里只是一些经常使用的命令来加深理解,而不是命令大全!若是没有安装docker的小伙伴能够本身按照官网的文档进行安装,本文不会讲到这部分的内容!因此我假设你在本身的服务器上已经装好了docker!

帮助命令

  一、docker version 查看docker客户端和服务的版本。

  二、docker info 查看docker的基本信息,若有多少容器、多少镜像、docker根目录等等。

  三、docker --help 查看docker的帮助信息,这个命令能够查看全部docker支持的命令~

  这几个命令很是简单,有过一点linux基础的小伙伴应该很容易理解!

镜像命令

  一、docker images 查看本地主机上全部的镜像。注意是本地主机的!这里能看到镜像的名称、版本、id、大小等基本信息,注意这里的image ID是镜像的惟一标识!还能够经过docker images tomcat指定某个具体的镜像查看对应信息。这里还要注意的是centos的镜像才200MB的大小,比咱们物理机器上装的centos要小得多的多,这是由于centos的镜像只保留了linux核心部分,这也是为何docker虚拟化技术比虚拟机运行效率更高的缘由!那为何tomcat的镜像这么大呢?那是由于咱们以前说过咱们的镜像就像一个洋葱同样,是一层套一层的!tomcat的运行须要基于centos、jdk等等镜像,tomcat在上层因此体积比较大啦!
  

  二、docker rmi 删除本地的镜像,以下图所示,能够加上-f参数进行强制删除。这里的rmi命令跟linux中的删除命令就很像啦,只是这里加了一个i表明image!
  

  三、docker search 根据镜像名称搜索远程仓库中的镜像!
  

  四、docker pull 搜索到某个镜像以后就能够从远程拉取镜像啦,有点相似我们git中的pull命令,固然对应的还有个docker push的命令。如图,若是咱们没有指定tag,默认就会拉取latest版本,也能够经过docker pull tomcat:1.7的方式拉取指定版本!注意这里在拉取镜像的时候打印出来的信息有不少,这也是前面说到的镜像是一层套一层,拉取一个镜像也是一层一层的拉取!
  

容器命令

  经过镜像命令咱们就能获取镜像、删除镜像等操做啦!镜像有了下面天然就须要经过镜像建立对应的实例啦,也就是咱们的容器。下面咱们以tomcat为例:

  一、docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 能够基于某个镜像运行一个容器,若是本地有指定的镜像则使用本地镜像,若是没有则从远程拉取对应的镜像而后启动!因为这个命令很是重要,因此下面列出几个比较重要的参数:

-d:启动容器,而且后台运行(docker容器后台运行,就必需要有一个前台进程,容器运行的命令若是不是一直挂起的命令,容器启动后就会自动退出);
-i:以交互模式运行容器,一般与-t同时使用;
-t:为容器从新分配一个伪输入终端,一般与-i同时使用(容器启动后进入到容器内部的命令窗口);
-P:随机端口映射,容器内部端口随机映射到主机的高端口;
-p:指定端口映射,格式为:主机(宿主)端口:容器端口;
-v:创建宿主机与容器目录的同步;
--name="myTomcat": 为容器指定一个名称(若是不指定,则有个随机的名字);

  

  上面我经过命令启动了一个tomcat的容器,因为使用了 -t 的参数,因此容器启动后就进入到了容器的内部的命令窗口,打印了不少tomcat启动的日志。而且使用 -p 参数指定了端口映射,也就是容器内tomcat运行的端口是8080,而且映射到了宿主机上的8888端口,这样咱们在外部就能够同过服务器的ip+8888端口 访问到咱们容器内部tomcat部署的服务了。

  前面咱们提到过容器内的数据会随着容器的关闭而丢失。那咱们就须要有容器数据卷的技术能将容器内的数据持久化到宿主机。这里须要用到 -v 参数!咱们看下面的截图
  

  这里第一个要注意的是咱们用的 -d 参数,启动后没有进入到容器内部,仍是在宿主机。(能够对比一下与上面 -it 参数的区别)。第二个要注意的是 -v /宿主机:/容器内目录 实现了宿主机与容器内指定目录的数据同步!容器启动后就可使用 linux 的 ll 命令查看宿主机上已经同步到了容器内的文件。第三个要注意的是这里的同步是双向的,也就是说在宿主机上对文件的修改也会同步到容器内部!多个不一样的容器映射到宿主机的同一个目录,就能够实现不一样容器间的数据共享啦!
  

  二、进入到容器后能够经过exit命令退出容器,也能够经过ctrl+P+Q快捷键退出容器,这两种方式的不一样之处是exit会退出而且关闭容器,而ctrl+P+Q快捷键只是单纯的退出,容器还在运行,而且还能再次进入!

  三、docker ps咱们能够经过该命令查看正在运行的容器的信息,这里能看到容器的惟一id,启动时间等等...这里跟linux的ps命令相似,因此也能够把容器理解为一个运行在docker上的进程!docker ps -a能够查看运行中与中止的全部容器。
  

  四、docker attach [OPTIONS] CONTAINER上面说过经过ctrl+P+Q快捷键退出容器后容器还在后台运行,那若是想再次进入容器怎么办呢?咱们就能够经过attach命令+容器的id再次进入容器!

  五、docker exec [OPTIONS] CONTAINER这个命令与attach同样均可以再次进入后台运行的容器,可是该命令能够不进入容器而在运行的容器中执行命令!比attach更增强大!

  六、docker stop docker kill docker restart这三个命令分别用来中止容器、强制中止容器和重启容器,就跟咱们在linux上中止、强制中止和重启某个进程同样的啦,这里就不作演示了!

  七、docker rm 使用这个命令就能够删除某个容器,这里跟删除镜像的区别是这里少了一个 i 啦!须要注意的是经过stop和kill中止的容器还存在于docker中,而使用 rm 命令操做后的容器将再也不存在!
  

  八、docker inspect 查看容器的详情(也能查看镜像详情)。

Dockerfile

  前面咱们对docker以及相关概念、经常使用命令有了基本的了解,咱们也知道了能够从远程pull一个镜像,那远程的镜像是怎么来的呢?若是咱们想本身建立一个镜像又该怎么作呢?
对,Dockerfile!Dockerfile是一个包含用户可以构建镜像的全部命令的文本文档,它有本身的语法以及命令,docker可以从dockerfile中读取指令自动的构建镜像!
  咱们要想编写本身的Dockerfiler并构建镜像,那对Dockerfile的语法和命令的了解就是必须的,了解规则才好办事嘛!

相关指令

FROM
  FROM <image> [AS <name>]
  FROM <image>[:<tag>] [AS <name>]
  FROM <image>[@<digest>] [AS <name>]
  指定基础镜像,当前镜像是基于哪一个镜像建立的,有点相似java中的类继承。FROM指令必是Dockerfile文件中的首条命令。

MAINTAINER
  MAINTAINER <name>
  镜像维护者的信息,该命令已经被标记为不推荐使用了。

LABEL
  LABEL <key>=<value> <key>=<value> <key>=<value> ...
  给镜像添加元数据,能够用LABEL命令替换MAINTAINER命令。指定一些做者、邮箱等信息。

ENV
  ENV <key> <value>
  ENV <key>=<value> ...
  设置环境变量,设置的变量可供后面指令使用。跟java中定义变量差很少的意思!

WORKDIR
  WORKDIR /path/to/workdir
  设置工做目录,在该指令后的RUN、CMD、ENTRYPOINT, COPY、ADD指令都会在该目录执行。若是该目录不存在,则会建立!

RUN
  RUN <command>
  RUN ["executable", "param1", "param2"]
  RUN会在当前镜像的最上面建立一个新层,而且能执行任何的命令,而后对执行的结果进行提交。提交后的结果镜像在dockerfile的后续步骤中可使用。

ADD
  ADD [--chown=<user>:<group>] <src>... <dest>
  ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
  从宿主机拷贝文件或者文件夹到镜像,也能够复制一个网络文件!若是拷贝的文件是一个压缩包,会自动解压缩!

COPY
  COPY [--chown=<user>:<group>] <src>... <dest>
  COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
  从宿主机拷贝文件或者文件夹到镜像,不能复制网络文件也不会自动解压缩!

VOLUME
  VOLUME ["/data"]
  VOLUME用于建立挂载点,通常配合run命令的-v参数使用。

EXPOSE
  EXPOSE <port> [<port>/<protocol>...]
  指定容器运行时对外暴露的端口,可是该指定实际上不会发布该端口,它的功能是镜像构建者和容器运行者之间的记录文件。
  回到容器命令中的run命令部分,run命令有-p和-P两个参数,若是是-P就是随机端口映射,容器内会随机映射到EXPOSE指定的端口,若是是-p就是指定端口映射,告诉运维人员容器内须要映射的端口号。

CMD
  CMD ["executable","param1","param2"]
  CMD ["param1","param2"]
  CMD command param1 param2
  指定容器启动时默认运行的命令,在一个Dockerfile文件中,若是有多个CMD命令,只有一个最后一个会生效!一样是能够执行命令,可能你会以为跟上面的RUN指令很类似,RUN指令是在构建镜像时候执行的,而CMD指令是在每次容器运行的时候执行的!docker run命令会覆盖CMD的命令!

ENTRYPOINT
  ENTRYPOINT ["executable", "param1", "param2"]
  ENTRYPOINT command param1 param2
  这个指令与CMD指令相似,都是指定启动容器时要运行的命令,若是指定了ENTRYPOINT,则CMD指定的命令不会执行!在一个Dockerfile文件中,若是有多个ENTRYPOINT命令,也只有一个最后一个会生效!不一样的是经过docker run command命令会覆盖CMD的命令!执行的命令不会覆盖ENTRYPOINT,docker run命令中指定的任何参数都会被当作参数传递给ENTRYPOINT!

RUN、CMD、ENTRYPOINT区别
一、RUN指令是在镜像构建时运行,然后两个是在容器启动时执行!
二、CMD指令设置的命令是容器启动时默认运行的命令,若是docker run没有指定任何的命令,而且Dockerfile中没有指定ENTRYPOINT,那容器启动的时候就会执行CMD指定的命令!有点相似代码中的缺省参数!
三、若是设置了ENTRYPOINT指令,则优先使用!而且能够经过docker run给该指令设置的命令传参!
四、CMD有点相似代码中的缺省参数

USER
  USER <user>[:<group>]
  USER <UID>[:<GID>]
  用于指定运行镜像所使用的用户。

ARG
  ARG <name>[=<default value>]
  指定在镜像构建时可传递的变量,定义的变量能够经过docker build --build-arg = 的方式在构建时设置。

ONBUILD
  ONBUILD [INSTRUCTION]
  当所构建的镜像被当作其余镜像的基础镜像时,ONBUILD指定的命令会被触发!

STOPSIGNAL
  STOPSIGNAL signal
  设置当容器中止时所要发送的系统调用信号!

HEALTHCHECK
  HEALTHCHECK [OPTIONS] CMD command (在容器内运行运行命令检测容器的运行状况)
  HEALTHCHECK NONE (禁止从父镜像继承检查)
  该指令能够告诉Docker怎么去检测一个容器的运行情况!

SHELL
  SHELL ["executable", "parameters"]
  用于设置执行命令所使用的默认的shell类型!该指令在windows操做系统下比较有用,由于windows下一般会有cmd和powershell两种shell,甚至还有sh。

构建

  Dockerfile执行顺序是从上到下,顺序执行!每条指令都会建立一个新的镜像层,并对镜像进行提交。编写好Dockerfile文件后,就须要使用docker build命令对镜像进行构建了。
  docker build的格式:docker build [OPTIONS] PATH | URL | -

-f :指定要使用的Dockerfile路径,若是不指定,则在当前工做目录寻找Dockerfile文件!
-t: 镜像的名字及标签,一般 name:tag 或者 name 格式;能够在一次构建中为一个镜像设置多个标签。

  例如咱们能够docker build -t myApp:1.0.1 .这样来构建本身的镜像,注意后面的 . ,用于指定镜像构建过程当中的上下文环境的目录。若是你们想了解那些官方镜像的Dockerfile文件都是怎么样写的,能够上https://hub.docker.com/ 进行搜索,以tomcat镜像为例

  能看到tomcat镜像的父镜像是openjdk镜像,咱们再搜索openjdk的Dockerfile文件

  openjdk镜像的父镜像又是oraclelinux镜像,咱们再搜索oraclelinux的Dockerfile文件


  openjdk镜像的父镜像是scratch,这是根镜像,全部的镜像都会依赖该镜像,就像咱们代码中全部的对象的父类都是Object!因此能看到tomcat镜像就是这样一层一层的构建出来的,这也是为何前面经过docker images查看到的tomcat镜像为何会有四百多兆的缘由啦!

  看到这里的你,是否对docker是什么?为何须要docker?docker镜像、docker容器的概念是什么?docker中经常使用的命令有哪些?Dockerfile有哪些指令?怎么去构建本身的镜像?这些问题都能明白了呢?

相关文章
相关标签/搜索