第一口docker的感觉——初识docker相见恨晚

  1. 云栖社区>
  2. 博客>
  3. 正文

第一口docker的感觉——初识docker相见恨晚

luckyharry4 2018-08-19 11:39:00 浏览526
展开阅读全文

前言

前一阵的工作,大多数是与部署相关的,通过将项目打包,然后利用docker,部署在AWS上去。就在这一段时间里面我便对docker产生了浓厚的兴趣,这也就激发我去深入研究的一个动力。那么下面开始我们的docker之旅。

什么是docker

我们可以首先通过以下网址对docker有一个认识:docker的讲解。简单来说docker可以让我们的部署变得更加简洁。(这里我就不做那么更详细的解释了,因为我觉得它总结的要比我总结好的多。)

为什么用docker

在没出现docker的时候,我们完成的java web项目需要打成一个war。然后得在服务器中配置各种各样的参数,例如说jdk,tomcat,数据库等。配置的周期相当的冗杂并且繁琐。但是现在有了docker,我们不但可以使用一个空的镜像,从头开始构建,还可以使用之前各种大牛已经build好的镜像,直接使用。而且在项目需要迁移的时候,我们只需要在需要部署的地方,直接使用之前项目使用的docker放置好自己的项目即可,方便快捷。

docker的基本概念

docker最重要的三个概念是:镜像(image),容器(container),仓库(repository),在这三个概念中,镜像是最重要的概念。

  • 镜像
    我们可以把镜像理解为一个文件系统,并且是一个只读的文件系统。镜像是由一层层的只读层构造起来的,但是从使用者的角度来看我们只有一个镜像而已。那么问题就来了,镜像是只读的,那么我们在使用它的过程中,如果需要对它进行修改,该怎么办呢,别着急,这个就得看我们的容器了。
  • 容器
    容器是镜像的一个运行实例,可以不准确的把镜像当作类,容器当作对象。容器其实他的结构是与镜像相类似的,底部也是一层层的只读层,只不过在最上层会存在一个存储层,我们可以在这一层定制化我们的这个容器,还可以通过build命令,把容器打包成我们自己需要的镜像。另外镜像启动后会形成一个容器,容器在计算机中是一个进程,但这个进程对其他进程并不可见。
    容器的启动过程:
    检查镜像是否在本地存在,如果不存在去远程仓库下载
    ==>利用镜像创建一个容器
    ==>启动刚刚创建的容器
    ==>分配一个文件系统给容器,并且在镜像层外挂载一个可读可写层
    ==>从宿主主机的网桥接口中桥接一个给容器
    ==>从网桥中分一个ip地址给容器
    ==>执行用户指定的应用程序
    ==>执行完毕后容器自动终止
  • 仓库
    这个理解起来就很简单了,大家应该有使用过git,他是有一个远程的仓库,这个仓库记录着我们的代码,和每一次我们提交的记录。但是在这里,把docker的仓库比做maven仓库更加恰当,就相当于我们可以去maven远程仓库取我们需要的依赖,多个依赖构成了我们的整个项目,这个思想同样适用于docker。默认情况下,我们都是从docker hub中取得的镜像(http://registry.hub.docker.com/

使用docker

实践是检验真理最好的方式,我会在不断的实践中给大家讲解docker命令。
本人使用mac,所以所有操作都会在mac进行。如果使用docker的话,强烈不推荐搭建使用windows系统,因为docker对于windows很不友好,用起来十分不方便,那怎么办呢,win的同学,可以在电脑上安装虚拟机,然后安装一个linux系统(centos,red hat,ubantu)。
下面给出安装的链接:
Mac:mac安装docker的方法
Linux:centos安装docker的方法
在使用docker之前,如果是不熟悉linux命令的,推荐强烈去学一下,因为我自己感觉这对于docker的学习是很有帮助的。
安装好docker,那就开始我们的表演。

1.docker search <镜像名称>

当我们在对docker的镜像一无所知的时候,我们可以通过查询镜像,看看自己想要的镜像存不存在。例如说我们这里可以docker search tomcat。


img_5caedea8c1016421be0a76b837f2af2e.png
docker search.png

2.docker pull <镜像名称>:<镜像版本>

其实我们的版本都可以不用填写,默认情况下是latest,也就是去取最新的版本。


img_28360027f1669c66d7f3a44db20be266.png
docker pull.png

3.docker run -d -p <外部端口>:<内部端口> <镜像名称>:<镜像的tag>

打开terminal终端,在终端中输入:docker run -d -p 8080:8080 tomcat 这里启动一个tomcat镜像作为演示。熟悉tomcat的应该知道,默认的端口号为8080,所以我这里使用了默认端口。这里解释一下外部/内部端口,这个很容易理解,docker在运行的时候,会启动一个tomcat,这个tomcat的端口为8080。外部端口指的就是宿主电脑的端口。就是我们可以通过我们的电脑访问的端口。

  • -d <指的是后台运行容器>
  • -p <指的是指定端口>
  • --link <连接的容器名称>:<连接的别名>
    可以使容器和容器之间相互连接
  • -v <挂载到容器的目录>
  • --volumes-from <可以挂载的数据卷容器名称> (通过启动一个新容器,使用 -v 命令挂载一个目录,然后通过这个命令把容器挂载到数据卷容器上,可以多个容器挂载同一个数据卷容器上,而且数据卷容器本身可以不是启动的状态。)
  • -v <本地已有的目录>(这个路径必须是绝对路径):<容器的目录>。如下,我自己创建了一个宿主机与容器中的文件夹映射,然后创建了一个文件,宿主机相应的也产生了文件。


    img_9dfc7fd5637bb8039e83519211302ec7.png
    docker run -v.png

    img_9f6e1dadfff51eb42fb25f1f56071e72.png
    local file.png

    (Tips:其实我们本可以不使用pull进行下载镜像,因为docker镜像在启动的时候,如果放下这个镜像不存在,那么自己会去下载镜像。)如果想的话,可以添加上 -- name 作为这个启动容器的名称,如果我们不定义名称,可以通过容器的id操纵这个容器。并且docker run 是一个组合命令,实际上组合的是 create+start


    img_2283ad10d893f59726f0f0693cbd2a18.png
    docker run.png

4.docker create --name <容器名称> <镜像名称>:<镜像tag>

5.docker start <容器的id>

这里把create 以及start一起讲一下,create命令就是在镜像的只读层的最上面加上一个存储的可读可写层。上面的 -d 与 -p 的option 都是create命令的,创建一个容器可配的option相当的多,这里就不详细说明了。create命令后,容器是处于stop状态的,得需要start命令启动。start命令则是给容器分配一个进程,然后启动起来。

6.docker images

查看本地已经有的docker镜像。
通过 docker images - -format [.ID]:[.Repository]指定显示镜像id以及名称


img_961d293204f9550139e514ba07fbcabd.png
docker image.png

7.docker rmi <容器名称>:<容器tag>

移除已经存在的指定的容器。


img_2d4b708f849f2aea144a4bd40ecc8003.png
docker rmi.png

8.docker ps -a

查看所有的容器。
当把-a换成-qa的时候就是查看所有容器的id。


img_944ad2b1fb3342b550016602ef43a0dc.png
docker ps -a.png

9.docker exec -it <容器Id> /bin/bash

进入docker 容器 docker exec -it(后面可以接上容器id或者容器名称) /bin/bash

  • -it 是 -i以及-t。
  • -i是保持标准输入打开
  • -t是表示分配一个伪终端。


    img_43f2ba34eaf9e7b00cd6e00a1a5b2b87.png
    docker exec.png

10.docker tag <已有镜像名>:<已有镜像版本> <新镜像名>:<新镜像版本>

我们可以使用docker tag tomcat:latest mytomcat:latest。这样就会新生成一个镜像名字叫做mytomcat,版本为latest,只有别名不同而已,但是同样指向了同一个镜像。

11.docker inspect <镜像名称>:<镜像版本>

显示镜像的详细信息,包括制作者,适应框架,各层的数字摘要。

12.docker history <镜像名称>:<镜像版本>

前面已经说过,既然镜像是一层一层构成的,那么我们肯定可以看到,各层的记录,使用此命令,可以看出镜像发生的变化。过长的信息会被自动拦截我们可以使用 --no-trunc显示信息完整的信息。

13.docker commit <进程号>/<容器名称> <镜像名称>:<版本号>

基于现有镜像,形成自己的镜像 。原理就是在原有的镜像基础上增加自己修改过的存储层,叠加为一个新的镜像,保存下来。成功后,会返回一个 sha256的码作为镜像的唯一标实。
形成新的自己的镜像,一共有三个方法:

  • 通过 commit 命令
  • 通过模版进行构建
    我们可以通过openVZ为我们提供的模板进行创建,也可以通过自己导出的模板进行创建,openvz网址 openvz模板下载地址。
    我们以ubantu的模板为例。命令为cat ubuntu-x86_64-minimal.tar.gz | docker import ubuntu:14.04。执行完以上命令,就可以通过docker images 看到我们的镜像了。
  • 通过Dockerfile文件进行构建。
    但是docker commit 需要慎用,因为具体做了什么修改任何人都是看到的,完全就是一个黑盒操作。而且进行的删除操作,并不是真正意义上的删除,每一次的修改都是在上一次的基础上,这使得 镜像越来越臃肿。如果我们想要定制我们的docker镜像可以使用dockerfile

13.docker save -o 导出的镜像名称(后缀为.tar) <镜像名称>:<镜像的版本>

14.docker load --input 导出的镜像名称(后缀为.tar)

15.docker export -o 导出的镜像名称(后缀为.tar) <容器Id>

16.docker import 导出的镜像名称(后缀为.tar) <镜像名称>:<镜像的版本>

前两个命令是搭配在一起的,我们通过save命令,把镜像打包成tar文件的形式,这就可以分享给别人进行使用,然后其他人可以通过 load 命令将 导出的文件,保存到本地。
后两个命令也是搭配起来的将正在运行的容器,打包成一个tar文件。然后把tar文件import进来,形成一个镜像。
我们可以看出load和import命令十分相似,那他们的区别在哪呢?

  • load 命令导入镜像存储文件到本地镜像库
  • import 导入一个容器快照到本地镜像库
    容器快照文件将丢弃所有的历史记录以及元数据信息,仅保留快照时的状态
    镜像存储文件保持完整记录,相对的体积也会更大。
    在我动手实践的时候也明显感觉到了,使用export要比save的速度快的多。


    img_5321b80456ac05a4d9c052f7834fcaf5.png
    docker save load.png

    这里的 load的时候犯了一个错误,在后面跟上了镜像的名称与版本,其实是并不需要的,切记下次不会再加了。


    img_d967446c3e63a2c70c84160c52f28b2a.png
    docker import export.png

17.docker stop <容器的ID>

停止正在运行的容器实例。

18.docker rm <容器的ID>

在删除一个容器实例之前,应该先要将容器停止。
主要支持的选项:

  • -f , --force = false 强制删除一个正在运行的容器
  • -l , --link=false 删除容器的连接,但是保存容器
  • -v , --volumes=false 删除容器挂载的数据卷

19.docker restart <容器的ID>

重新启动容器,将容器先停止,后启动。

20.docker build -t <生成镜像的名称>:<镜像的版本> <Dockerfile的位置>

这是三种创建自己镜像的方法之一,也是最好的一种方法,很多时候我们看到Dockerfile的位置上为".",表示的是当前目录,说明我们cmd和我们的Dockerfile在同一目录下。

后续

在下一篇文章,我会继续整理有关Dockerfile的编写,以及其他相关的内容。我希望这样的总结,可以给大家带来帮助,也对自己梳理知识体系有所帮助,谢谢大家
本文参考书籍:《Docker技术入门与实战》

网友评论

登录后评论
0/500
评论
luckyharry4
+ 关注