都9102年了,还不会Docker?10分钟带你从入门操作到实战上手

Docker简述

Docker是一种OS虚拟化技术,是一个开源的应用容器引擎。它可以让开发者将应用打包到一个可移植的容器中,并且该容器可以运行在几乎所有linux系统中(Windows10目前也原生支持,Win10前需要内置虚拟机),正所谓“一次打包,到处运行”。

Docker容器的运行是完全的沙箱机制,相互之间不会有任何关联(除非自己串联集群)。网络、存储、进程等资源,不仅对于不同的容器是相互隔离,对于宿主机和容器直接也是隔离的,除非你手动映射暴露端口或者挂载存储卷。

很多人不理解,Docker和虚拟机到底有什么区别。


image

image

从这两张结构图来看,Docker比虚拟机少了一层虚拟机操作系统,Docker的应用直接Docker引擎上运行。由于虚拟机需要一层操作系统,所以会导致虚拟机的体积非常大,通常在几G到十几G之间。并且通常一个虚拟机上,不只一个应用,因此对于整体的虚拟集群管理并不太友好,比较难做到灵活分配。

而一个Docker镜像的体积大约在几十M到几百M之间,一般一个镜像只打包一个应用,由多个镜像组成一个完整的项目,并且镜像易于复制,可以跨平台运行,这样可以使项目的部署管理有更好的灵活性。所以Docker无论从资源消耗上、管理上、使用上都在虚拟机之上,因此我们又有何理由不使用这样的容器化技术呢?

对于容器化技术的学习,可谓是深如海。从基本的镜像、容器操作,到镜像的打包、容器的部署,再到企业生产级的容器集群管理技术(Docker官方的Swarm、Google的Kubernetes),如此多的内容,并不是所有人技术人员都能一朝学会。不过除了生产级别的集群管理技术有难度意外,其他内容从学习使用的角度来说,其实是非常简单的,况且K8s这种东西,对于普通开发来说也是很少能接触到。

说到这里,可能还有很多人觉得这个是公司层面、运维层面的操作,不是很了解Docker对于普通开发来说,意味着什么,对我们有什么好处?

  • 多办公环境,一键部署。假如你在公司一套开发环境,在家一套开发环境,当你公司的开发环境变更时,在家的环境就要跟着变,如果是使用Docker,将一些依赖型的应用,如Redis、ZK、Mysql等边缘服务都打包在docker里面。无论你在哪里改变了内容,只要在运行时更新下镜像,就可以按照最新的内容去执行了,不需要一个手动去安装,适配。
  • 联调测试,无需依赖他人。当后端完成对外的接口后,将后端应用打包进docker,这样无论是前端、测试,在何地何时都可以自己把容器启动起来进行联调测试,而不需要自己手动一步步地搭建这个后端环境。
  • ...

下面就来一步步讲解下,普通开发所需要的Docker知识。

概念介绍

学习Docker首先要了解下几个基础概念:

  • 宿主机,Host,运行Docker所在的物理机,是Docker运行的系统环境。
  • 镜像,Image,相当于一个程序模板,通过这个模板可以生成很多个相似的容器。可以理解为Java中的类,它本身不具备执行运行的能力,是一个对象抽象的模板。每个镜像可以有多个版本,用tag来区分。镜像可以通过Dockerfile来构建。
  • 容器,Container,Docker运行的最小单位对象。它是通过镜像实例化出来的一个可运行对象。容器的修改,可以提交反作用于镜像,更新这个容器的模板。
  • 仓库,Repository,用于存储管理镜像的仓库,类似于git管理代码的仓库一样,可以管理多版本的镜像。

镜像、容器、仓库的关系如下:


image

一句话总结就是,从仓库中拉取镜像,利用镜像生成容器。

基本操作

了解完Docker的基本概念,我们开始来开始学习下入门操作。此处省略所有的Docker安装过程,自己去官网下载就行了,基本是傻瓜式安装。

拉取镜像

通过docker pull ${image_uri}:${image_tag}命令,可以从远程仓库(默认是Docker Hub)中拉取所需要的镜像。

Docker Hub的网站上可以搜索下自己需要的镜像以及版本。例如Ubuntu,上面提供了几个版本。

image

我们拉一下16.04版本的ubuntu镜像。然后通过docker images命令,查看保存在本地镜像,发现多了一个ubuntu的镜像。
image

容器创建、启动、停止、登入

有了镜像以后,就可以通过docker run -it ${image_id}创建启动一个容器了。

image_id是镜像的id,通过docker images能查看到,也可以是镜像名(REPOSITORY:TAG)。

-it可以让你在启动后,连上容器的终端。连上终端后,就可以在里面随意操作容器里面的内容了。

image

exit退出容器后,容器就会自动停止了。但是这个容器依然还存在,只是”关机“了。(可以通过ctrl+p,ctrl+q,退出容器登入,而不关闭容器)

通过docker ps -a可以看到我们的容器已经Exited了。

image

通过docker start ${container_id},我们把这个容器再次启动。通过docker ps(加上-a包含显示未启动的容器),可以看到容器的状态为UP

image

同理,我们可以通过docker stop ${container_id}来停止容器,

在用docker start命令的时候,如果不加上-a参数,默认不会连接上容器的。不过我们可以在start后,通过docker attach ${container_id}来登入容器。

image

通过以上的基本操作,你基本可以利用docker当作一个虚拟机来使用了。如果想把容器和虚拟机的网络、存储打通,可以网上搜下了解下网络与卷挂载等容器设置。

更新镜像

在上面的例子中,我们pull下来的仅仅是一个ubuntu的原始镜像,并没有过多的内容。下面我们在这个镜像的容器里面,安装一个jdk。


image

这样我们的容器里面就有一个jdk了,但是如果我们再用这个ubuntu原始镜像再创建一个容器,它是不会用这个jdk的。所以我们就需要把这个容器的内容,提交到镜像当中。

通过docker commit ${container_id} ${repository}:${tag},在本地将容器内容提交到镜像当中。然后就可以拥有一个带jdk的ubuntu镜像了。

image

后面我们就可以利用这个镜像,生成带jdk的容器了。

以上的更新仅限于在本地的镜像,如果想把容器推送到云端就需要用docker push命令。前提是你已经登录了仓库拥有权限。

镜像仓库

上面提到,默认情况下,仓库是用Docker Hub。我们pull 和push都是在Docker hub上操作,但是如果镜像是内部私有使用的话,没有必要去使用Docker Hub,一个是网络慢,另一个是私有安全性问题。

针对以上问题,有两种解决方法,一个是自己搭建私有服务,另一个是用云服务的镜像管理平台(如阿里云的“容器镜像服务”)。前者对于一般开发者来说并没有必要,而且还要搞认证的,比较麻烦,这里不细说。下面介绍下如何用阿里云服务作为自己的私有仓库。

先在阿里云上创建一个镜像仓库,获得一个仓库地址,如registry.cn-shenzhen.aliyuncs.com/zackku/jdk。这里一个仓库地址,对应一种镜像(tag不同)。

利用docker login,先对阿里云的服务进行登录。

image

然后对上面的jdk镜像打tag(其实也是改仓库源的过程)


image

最后把镜像推送到阿里云就行了。


image

推送后,就能在阿里云的仓库上看到这个镜像。


image

通过搭建私有仓库,我们就可以完全抛开宿主机的环境,构建好一个镜像,就可以到处运行了。

Dockerfile构建镜像

从上面介绍,我们已经了解到,如何从拉取一个镜像、修改容器内容、提交镜像去构建一个我们所需要的镜像。但通过这些操作去构建一个镜像,一个是太繁琐,另一个问题是不清晰,没办法直观的了解镜像的构成。

Dockerfile就可以很好的解决该问题。它可以通过编写一个构建过程,来一站式构建镜像。下面同样以ubuntu为基础镜像,安装jdk构建一个新镜像为例,看看Dockerfile是怎么写的。


image

然后执行docker build -t registry.cn-shenzhen.aliyuncs.com/zackku/jdk2:1.0 .就能把镜像构建出来了。

image

Dockerfile高级技巧

上面是Dockerfile的基本使用,但实际情况下我们并不像(或者说不仅是)上面描述那样去构建镜像。下面介绍两个常用的使用原则。

分层构建。其实Docker的镜像是分层结构的,看回之前推送到远端仓库的例子。

image

红框里面就是镜像一层层的提交,如果这层已经本地构建过了,下次不需要构建了,同理如果远端已经有这层了,也不需要推送这层。而且这种分层是可以在不同镜像间共享的,例如不同的Java项目都是依赖于JDK的运行环境,那么它们就可以共用JDK这层镜像内容。

所以,基于这样的特性,我们就应该要分层去构建镜像,抽象镜像共同点。具体操作的话,我们大致可以去分两次构建镜像,先构建一个base镜像,用于不同镜像的底层,例如Java项目的所有基础运行环境,然后再通过base镜像,构建develop表层的应用镜像。相当于把应用程序打包丢到develop层里面。并且这层要告诉Docker是怎么运行程序的。

尽量构建小的base层。镜像的体积也是在使用Docker的时候要考虑的一个重要因素,因为如果镜像的体积过大,在更新镜像,拉取镜像的时候效率会低。尤其在刚刚所说的base层里面,如果base层做得太大太臃肿,里面程序过多,不仅仅体积大,还会让CPU、网络等资源消耗过大。其实我们在用Docker的时候,一般是一个容器只包含一个程序项目,关于这个程序的监控、健康等内容,在容器外通过k8s等集群管理去做,所以容器本身只需要保证自己的程序能够运行起来就行了。

至于上面我用ubuntu作为基础的操作系统是比较多余的,这里推荐只用apline操作系统作为程序的最底层镜像,它是一款轻型的Linux发行版,系统体积与运行时的资源消耗都相当低,十分适合用于Docker容器。基于apline的操作系统,我们在上面添加自己所需要的环境,例如安装一个Tomcat、JDK等,从而构建一个base的镜像。

上所说的base镜像,其实不太需要自己的写一层Dockfile,docker官方就直接提供了各种语言、环境的基础镜像,在github的docker-library里面。如果再有自己的团队的运行环境的要求,可以在这个Dockerfile基础上去添加修改即可,或者再抽象多一层。

至于Dockfile怎么写,语法是什么,网上有大把详细的说明,由于篇幅问题,不在这里展开。

docker-compose启动集群

前面已经介绍完一个单独的容器是如何构建与启动的了,但我们的项目往往不是只有一个容器的,把所有程序打包在一个容器不是正确的做法。所以我们怎么去管理启动这么多的容器,是一个必修的课题。在企业级的层面,有K8S,Swarm这种容器编排的管理工具,但稍微比较复杂,个人使用的话也没有太大必要。

这里推荐用Docker官方的docker-compose,它可以把所有的容器编排方式写在一个文件里,然后通过docker-compose up命令,就可以把一套的容器按照你的编排全部启动起来。

image

在这个例子的services包含每个容器的配置,其中的redis、mongodb用的是默认的镜像、默认的配置,myproject是我们自己的项目。通过这样的编排,我们就能让我们的项目连上redis和mongodb。最后通过docker-compose up就会自动拉取镜像,按照编排跑起来了。

具体的语法也不赘述,关键就是容器的卷挂载,网络的配置,端口的暴露,容器的依赖关系。如果把这套东西用起来,慢慢自然就会了解,重要的是动手去做一遍,尝试一下。


更多技术文章、精彩干货,请关注
博客:zackku.com
微信公众号:Zack说码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容