Docker从入门到上手实战

栏目: 编程工具 · 发布时间: 5年前

内容简介:Docker简述Docker是一种OS虚拟化技术,是一个开源的应用容器引擎。它可以让开发者将应用打包到一个可移植的容器中,并且该容器可以运行在几乎所有linux系统中(Windows10目前也原生支持,Win10前需要内置虚拟机),正所谓“一次打包,到处运行”。Docker容器的运行是完全的沙箱机制,相互之间不会有任何关联(除非自己串联集群)。网络、存储、进程等资源,不仅对于不同的容器是相互隔离,对于宿主机和容器直接也是隔离的,除非你手动映射暴露端口或者挂载存储卷。

Docker简述

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

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

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

Docker从入门到上手实战 Docker从入门到上手实战

从这两张结构图来看,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管理代码的仓库一样,可以管理多版本的镜像。

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

Docker从入门到上手实战

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

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

拉取镜像

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

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

Docker从入门到上手实战

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

Docker从入门到上手实战

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

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

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

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

Docker从入门到上手实战

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

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

Docker从入门到上手实战 Docker从入门到上手实战

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

Docker从入门到上手实战

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

更新镜像

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

Docker从入门到上手实战

这样我们的容器里面就有一个jdk了,但是如果我们再用这个ubuntu原始镜像再创建一个容器,它是不会用这个jdk的。所以我们就需要把这个容器的内容,提交到镜像当中。通过docker commit ${container_id} ${repository}:${tag},在本地将容器内容提交到镜像当中。然后就可以拥有一个带jdk的ubuntu镜像了。

Docker从入门到上手实战

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

镜像仓库

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

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

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

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

Docker从入门到上手实战

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

Docker从入门到上手实战

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

Docker从入门到上手实战

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

Docker从入门到上手实战

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

Dockerfile构建镜像

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

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

Docker从入门到上手实战

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

Docker从入门到上手实战

Dockerfile高级技巧

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

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

Docker从入门到上手实战

红框里面就是镜像一层层的提交,如果这层已经本地构建过了,下次不需要构建了,同理如果远端已经有这层了,也不需要推送这层。而且这种分层是可以在不同镜像间共享的,例如不同的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命令,就可以把一套的容器按照你的编排全部启动起来。

Docker从入门到上手实战

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

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

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-02/157117.htm


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First Web Design

Head First Web Design

Ethan Watrall、Jeff Siarto / O’Reilly Media, Inc. / 2009-01-02 / USD 49.99

Want to know how to make your pages look beautiful, communicate your message effectively, guide visitors through your website with ease, and get everything approved by the accessibility and usability ......一起来看看 《Head First Web Design》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具