Docker简介
Docker是一个开源的应用容器引擎,用于开发、交付、运行应用,它允许用户将基础设施中的应用单独分割出来,形成更小的颗粒,从而提供交付软件的速度。简单来说,用户可以将他们的应用、依赖库连同操作系统一同打包到一个可移植的image(镜像)文件中去,然后可以将其发布到其他运行有Docker的机器上,方便软件的测试,发布等。
Docker的用途
要想搞清楚Docker的用途,我们不妨先了解下目前软件开发所面临的一些难题。想必几乎所有的开发者都做过环境配置,是不是都觉得异常的繁琐。主要原因是一个软件要想运行起来,需要依赖的组件太多,包括操作系统的配置,各种依赖库的安装以及不同版本之间的适配等。开发者经常会遇到的一类问题是,明明在自己的机器上可以运行起来,换了一台机器就出问题了。
环境配置如此麻烦,每当换一个新的环境,就需要要做重复的工作,于是人们想到,可不可以将软件运行所依赖的环境也一起打包呢?也就是说在发布软件的时候,把环境也一起发布出去,这样软件运行就不会再担心环境配置等问题,Docker正是为了解决这类问题而生。
Docker的主要用途,目前主要有三大类:
- 提供一次性的环境。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
- 提供弹性的云服务。因为 Docker 容器可以随开随关,很适合动态扩容和缩容。
- 组建微服务架构。通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。
Docker的安装
Docker支持多种操作系统平台,不同平台的具体安装方法详见官网: https://docs.docker.com/get-docker/
Image文件
Image文件可以看做是一种特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数。镜像文件不包含任何动态数据,其内容在构建之后也不会被改变。Docker可以根据Image文件生成容器的实例。同一个Image文件可以生成多个可以同时运行的容器实例。Image是一个二进制文件,实际开发中,我们通常是在已有的Image文件中加上一些个性化设置而生成。举个例子,我们可以下载一个rehel6.5的基础镜像,然后在里面装上git,然后形成我们自己的image。
Image文件是通用的,一个Image文件可以直接拷贝到其他机器然后打开,为了加快开发,我们通常可以在别人已经创建好的Image文件上进行加工,形成我们自己的Image文件,可以提高效率。
Docker官方提供的Image文件仓库网址:https://hub.docker.com/
我们可以在上面搜索我们想要的Image文件,然后通过docker pull指令下载到本地。
Container 文件
当我们使用docker run 指令的时候,我们实际上创建了一个容器实例,它本身也是一个文件,成为容器文件。关闭容器之后,容器并不会被删除,只是被暂停了而已。
Docker中容器与Image的关系有点类似于面向对象编程中对象和类的关系:
Docker | 面向对象 |
---|---|
容器 | 对象 |
镜像 | 类 |
通俗点来说,可以认为Image是静态的,容器是动态的。一个Image可以创建多个容器。Image是不可更改的,但是容器在Image的基础上增加了一个可写层,在容器内部的更改会被写到容器的文件系统中,然后而这并不会影响到Image文件,如果想更新对应的Image文件,docker提供了一个commit命令,可以将容器的存储层保存下来成为镜像。换句话说,在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。我们后面以新的镜像文件运行时,就会拥有原有容器最后的文件变化。
下面我会用一个例子来说明如何操作。
一个具体例子
上面讲过,为了提高效率,我们通常会在先有的镜像基础上进行加工。因此,首先我们可以在dockerhub搜索我们想要的镜像文件,选择一个点击进去之后,会有具体的下载方式。
以Redhat6.5为例,可通过以下方式获取:
docker pull richxsl/rhel6.5
拉取下来之后,可以通过以下命令查看是否成功:
docker images
可以看到已经在本地镜像列表中了。
image.png
接着我们使用docker run指令启动该镜像,具体指令如下:
docker run -it --name=halo richxsl/rhel6.5 /bin/bash
其中参数说明:
- -i: 交互式操作
- -t: 终端
- --name: 给容器取一个名字
执行成功之后,此时你会发现你的终端窗口发生了变化,如下图:
image.png
这表明我们此时是处于容器之中,root后面的ID其实就是容器ID。
紧接着,我们就可以在此容器中执行我们想要的操作了。比如安装git、boost等开发所依赖的工具和库等。此处就不赘述。
当我们把所有依赖的环境都安装完成之后,其实我们所做的修改已经被写到了容器文件中了,但是此时Image文件并没有修改。如果要保存修改到镜像的话,我们可以使用commit指令,commit指令的作用是我们可以从容器中创建一个新的镜像。
具体用法如下:
docker commit -a "halo" -m "install git wget gcc" fa99d5c7957d richxsl/rhel6.5:v2
参数说明:
- -a: 提交的镜像坐着
- -m: 提交时候的说明文字,类似于git
紧接着后面分别填写容器的ID和新镜像的名称,在这里分别是fa99d5c7957d和richxsl/rhel6.5:v2
耐心等待指令执行完成之后,我们可以通过docker ps指令来查看是否创建成功:
docker ps -a
可以看到已经创建出了新的Image文件
image.png
同样的道理,如果我们下次还想继续对此镜像做出修改,那么就在此版本的镜像文件上创建一个容器,然后进行修改,最后再commit,整体感觉是不是有点像git的版本管理呢?
对于运行在容器内的web类服务,需要考虑外部程序如何访问的问题,这涉及端口映射的问题。容器在启动的时候,如果不指定端口映射参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。
我们可以通过 -p、-P来实现:
- -p指定要映射的端口,一个指定端口上只可以绑定一个容器
- -P将容器内部开放的网络端口随机映射到宿主机的一个端口上
因此我们可以通过以下方式将容器指定端口映射到宿主机的指定端口上:
docker run -it -p 5000:8080 richxsl/rhel6.5:v2 /bin/bash
这条指令的意思是,启动容器并且将容器的8080端口映射到主机的5000端口,当外部的程序访问宿主机的5000端口时,请求会被转发到容器内部的8080端口上,由此可以实现外部程序与容器内程序的交互。
当一切就绪之后,我们可以将容器导出为新的镜像文件,可以发布到dockerhub上,也可以直接拷贝到其他机器上直接运行。
可以通过以下指令来进行导出:
docker export 71743c47f4a1 > server.tar
其中71743c47f4a1是对应的容器ID,导出的镜像文件就在当前文件夹,可以直接通过ls指令来查看。
紧接着,我们可以将此文件拷贝到其他机器上,然后再本地通过docker import指令进行导入:
docker import - new_server < server.tar
然后通过docker images进行查看是否导入成功。
如果成功的话,就相当于在另外的机器上搭建了一个一模一样的环境,省去了传统方式需要重新配置开发环境的烦恼。
有一点要注意,docker实现本地镜像的导出、导入有两种方案。分别是
- 使用export 和 import
- 使用save 和 load
注意不可混用,具体可参考Docker-实现本地镜像的导出导入。
网友评论