美文网首页Docker
S2:创建镜像

S2:创建镜像

作者: 睦月MTK | 来源:发表于2020-01-07 20:40 被阅读0次

声明:所有的实验示例大部分来自《learn-docker-in-a-month-of-lunches》的作者Elton Stoneman,但运行结果并不都是照搬,大部分实验结果可能与原书不同


一、基础概念
  1. Q:什么是镜像?
    A:镜像就是一系列只读的命令,这些命令被用来指导如何创建一个容器。一般来说,镜像一般会基于在别的镜像上,然后再此基础上添加用户的个性化内容。
  2. Q:什么是镜像层?
    A:在Dockerfile中的每一行命令都会使得Docker创建一个对应的镜像层,所以镜像就相当一堆镜像层的集合。镜像实际上是一个个只读的文件,被存储在Docker的本地缓存中。Docker在根据Dockerfile创建镜像时,会自动识别可复用的镜像层,这样就避免了重复创建的开销,这也时为什么Docker如此便捷、轻量化并且快速的原因。
  3. Q:什么是Dokcerfile?
    A:Dockerfile就是一个脚本,该脚本定义了如何打包你的应用,如何去生成一个对应的镜像。

二、编写Dockerfile

附:Dockerfile的官方文档

  1. 克隆Elton Stoneman在github上的代码(点颗星应该不算白嫖了吧,咳咳...)
$ git clone https://github.com/sixeyed/diamol
  1. 进入到项目目录下
$ cd diamol/ch03/exercises/web-ping
  1. 查看分析Dockerfile
  • 查看项目目录下的Dockerfile
$ cat Dockerfile
  • 分析Dockerfile
FROM diamol/node

基于diamol/node镜像

ENV TARGET="blog.sixeyed.com"
ENV METHOD="HEAD"
ENV INTERVAL="3000"

设置容器的环境变量

WORKDIR /web-ping

设置容器的文件系统上的项目文件夹

COPY app.js .

哪些数据需要从本地文件系统复制到容器的文件系统里,dot代表容器的项目目录

CMD ["node", "/web-ping/app.js"]

当Docker运行一个容器时,执行这个命令


三、分析镜像的创建过程
  1. 根据Dockerfile创建镜像(确保你自己在项目的目录下,即Dockerfile所在的目录下)
$ docker image build --tag web-ping .

注意最后面还有个dot!!!

  1. 分析镜像创建时输出的日志信息
Sending build context to Docker daemon  4.096kB
Step 1/7 : FROM diamol/node
 ---> 9dfa73010b19

step1/7说明执行的是Dockerfile里面的第1条命令“FROM diamol/node”,并且一共有7步
---> 9dfa73010b19说明执行完第一条命令之后生成的镜像id为9dfa73010b19

Step 2/7 : ENV TARGET="blog.sixeyed.com"
 ---> Running in caa76a3bbee5
Removing intermediate container caa76a3bbee5
 ---> 641e96bf92c8
Step 3/7 : ENV METHOD="HEAD"
 ---> Running in 72f20ca7c727
Removing intermediate container 72f20ca7c727
 ---> b638ad06534b
Step 4/7 : ENV INTERVAL="3000"
 ---> Running in db6d5653dfac
Removing intermediate container db6d5653dfac
 ---> e20424bc0a05
Step 5/7 : WORKDIR /web-ping
 ---> Running in 840065185c08
Removing intermediate container 840065185c08
 ---> 4591d6e9216f

---> Running in caa76a3bbee5
Removing intermediate container xxx
说明执行类的命令,会先运行一个临时的容器,然后根据更改后的容器创建一个新的镜像

Step 6/7 : COPY app.js .
 ---> 7fea8227d6f0
Step 7/7 : CMD ["node", "/web-ping/app.js"]
 ---> Running in d169d4bb485c
Removing intermediate container d169d4bb485c
 ---> df5c3f2e5d42
Successfully built df5c3f2e5d42
Successfully tagged web-ping:latest

Successfully built说明创建镜像成功,镜像id为df5c3f2e5d42

  1. 查看本地缓存的镜像

    • 查看镜像
    $ docker image ls
    REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
    web-ping                       latest              df5c3f2e5d42        23 minutes ago      75.3MB
    diamol/node                    latest              9dfa73010b19        7 months ago        75.3MB
    
    • 查看所有的镜像,包括临时镜像(即上一步骤中的那些临时镜像)
    $ docker image ls --all
    REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
    web-ping                       latest              df5c3f2e5d42        7 minutes ago       75.3MB
    <none>                         <none>              7fea8227d6f0        7 minutes ago       75.3MB
    <none>                         <none>              4591d6e9216f        7 minutes ago       75.3MB
    <none>                         <none>              e20424bc0a05        7 minutes ago       75.3MB
    <none>                         <none>              b638ad06534b        7 minutes ago       75.3MB
    <none>                         <none>              641e96bf92c8        7 minutes ago       75.3MB
    diamol/node                    latest              9dfa73010b19        7 months ago        75.3MB
    
    • 模糊搜索本地的镜像
    $ docker image ls w*
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    web-ping            latest              df5c3f2e5d42        31 minutes ago      75.3MB
    
  2. 根据这个镜像创建一个容器,并查看输出的日志

    • 直接运行
    $ docker container run web-ping
    ** web-ping ** Pinging: blog.sixeyed.com; method: HEAD; 3000ms intervals
    Making request number: 1; at 1578388826200
    Got response status: 200 at 1578388828160; duration: 1960ms
    

    ping的地址为blog.sixeyed.com ,方法为HEAD ,间隔为3s ,可以发现,这些都被设置在Dockerfile的环境变量里

    • 自定义环境变量创建容器
    $ docker container run --env TARGET=baidu.com --name wt1 web-ping
    ** web-ping ** Pinging: baidu.com; method: HEAD; 3000ms intervals
    Making request number: 1; at 1578389292540
    Got response status: 302 at 1578389292703; duration: 163ms
    

    --name指的是为该容器命个名,以后操作该容器就可以通过该名字了,不必通过容器ID了
    可以看到ping的地址已经变成了baidu.com

  3. 修改app.js,然后重新创建一个镜像,并分析创建过程的变化

    • 重新创建一个镜像,命名为web-ping-modappjs
    //随便修改一下app.js,加个空行也行
    $ docker image build --tag web-ping-modappjs .
    
    • 分析新镜像的创建过程
    Step 1/7 : FROM diamol/node
     ---> 9dfa73010b19
    Step 2/7 : ENV TARGET="blog.sixeyed.com"
     ---> Using cache
     ---> 641e96bf92c8
    Step 3/7 : ENV METHOD="HEAD"
     ---> Using cache
     ---> b638ad06534b
    Step 4/7 : ENV INTERVAL="3000"
     ---> Using cache
     ---> e20424bc0a05
    Step 5/7 : WORKDIR /web-ping
     ---> Using cache
     ---> 4591d6e9216f
    

    ---> Using cache说明Docker识别出这个镜像层可以被复用,所以会自动使用本地镜像缓存中已有的镜像

    Step 6/7 : COPY app.js .
     ---> ef985b5a110e
    Step 7/7 : CMD ["node", "/web-ping/app.js"]
     ---> Running in 84847a3f59f2
    Removing intermediate container 84847a3f59f2
     ---> 5720186d593f
    Successfully built 5720186d593f
    Successfully tagged web-ping-modappjs:latest
    

    可以看到第6步和第7步都没有使用镜像,因为第6步中的app.js确实被更改了,第七步没有使用缓存的镜像是因为第7步的镜像是建立在第6步的基础上的,如果之前某个镜像发生过变化,则接下来的所有镜像都会被强制重新生成,所以根据这个原理,优化Dockerfile就势在必行了

  4. 查看指定镜像的镜像层信息(镜像层大小、ID、创建时间、创建的命令)

$ docker image history web-ping-modappjs
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
5720186d593f        23 minutes ago      /bin/sh -c #(nop)  CMD ["node" "/web-ping/ap…   0B
ef985b5a110e        23 minutes ago      /bin/sh -c #(nop) COPY file:f56993489cc9d376…   766B
4591d6e9216f        About an hour ago   /bin/sh -c #(nop) WORKDIR /web-ping             0B
//...
  1. 查看本地镜像的占用的空间大小、数量、正在使用的镜像(不只包括正在运行的容器,还包括处于停止状态的容器)数量等信息
$ docker system df | grep "image"
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              10                  0                   933.2MB             933.2MB (100%)

注意:这里显示的镜像数量有10个是因为实验的机器上有许多原有的镜像,不过即便如此,细心的你也应该发现所有的镜像加起来的实际的占用容量和步骤三.3显示的不同,这正是因为镜像复用的原因docker container ls显示的镜像大小是逻辑上的大小,包含所有镜像层的逻辑上的大小,并不是实际上的大小


四、Dockerfile的优化规则
  1. Dockerfile的优化规则
    • 同一种类型的命令尽量写成一个命令
    • 不经常变动的命令往前写
    • 经常变动的命令往后写
  2. 修改本项目中的Dockerfile(修改后的结果在diamol/ch03/exercises/web-ping-optimized中),并重新创建镜像
    • 修改后的Dockerfile
    FROM diamol/node
    
    CMD ["node", "/web-ping/app.js"]
    
    ENV TARGET="blog.sixeyed.com" \
        METHOD="HEAD" \
        INTERVAL="3000"
    
    WORKDIR /web-ping
    COPY app.js .
    

    这样创建步骤就只剩5步了,且就算修改了app.js,需要重新生成的镜像层也只有最后一步而已,CMD命令只需要放在FROM后面就可以了,结果都是一样的。


五、通过容器创建镜像
  • 其实Docker还可以通过容器来创建镜像,使用docker container commit <容器ID> [镜像名]命令可以把修改过后的容器作为一个新的镜像进行生成
$ docker container commit 0b7 c3lab
sha256:0be745068f061ab1812ee12712b515f8e18b40fce7aada731fe2c5472badbc80
$ docker image history c3lab
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
0be745068f06        6 minutes ago       /bin/sh                                         108B
c46f210501ad        6 months ago        /bin/sh -c #(nop) COPY file:6a4b948f094c8555…   18B
<missing>           6 months ago        /bin/sh -c #(nop) WORKDIR /diamol               0B
<missing>           8 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           8 months ago        /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a…   5.53MB

c46f210501ad就是原来镜像的ID,0be745068f06就是根据容器重建后的镜像ID


参考文档:
[1] learn-docker-in-a-month-of-lunches
[2] 官方文档


附:
[1] Elton Stoneman的github项目

相关文章

  • S2:创建镜像

    声明:所有的实验示例大部分来自《learn-docker-in-a-month-of-lunches》的作者Elt...

  • Docker 使用

    执行 Dockerfile 文件 一、创建镜像 1、创建 centos 7 镜像: 2、创建JDK 镜像(Dcok...

  • Docker镜像创建

    创建镜像 创建镜像有两种方式:1、从已经创建的容器中更新镜像,并且提交这个镜像2、使用 Dockerfile 指令...

  • Docker 常用操作指令

    镜像操作 列出docker下的所有镜像 搜索镜像 拉取镜像 删除镜像 容器操作 查看容器 创建与启动容器 创建容器...

  • Ubuntu网络配置(二)

    一、镜像篇 1. 查看所有镜像 2. 拉取镜像 3. 删除镜像 二、容器篇 1. 创建容器[必须现有镜像,才能创建...

  • Docker 安装Oracle12c

    查询docker镜像 结果如下: 下载镜像 查看镜像 下载完成使用命令查看镜像 结果: 创建备份数据存放目录 创建...

  • Docker入门

    安装 存储镜像 恢复镜像 常用命令 创建镜像两种方法 创建镜像方法1: root@1a9fbdeb5da3:/# ...

  • docker中nginx简单配置

    创建nginx镜像 了解Nginx 镜像的配置文件位置 查看docker运行的镜像 创建nginx 五、修改Ngi...

  • Docker--Jenkins(一键部署)

    dockerfile创建镜像JDK 执行命令构建镜像 查看镜像是否建立完成 创建容器 将服务通过dockerfil...

  • Docker基础命令

    镜像 获取镜像 查看镜像信息 搜寻镜像 删除镜像 创建镜像 存出和载入镜像(类似iso镜像) 上传镜像(类似git...

网友评论

    本文标题:S2:创建镜像

    本文链接:https://www.haomeiwen.com/subject/gobractx.html