zoukankan      html  css  js  c++  java
  • Docker镜像

    镜像的缓存特性

          Docker会缓存已有的镜像层,构建新镜像时,如果镜像层已经存在,就直接使用,无需重新构建

    举例说明

          在前面构建的test/ubuntu镜像中添加新的内容,往里面复制一个文件

    root@ubuntu:~# ls           ①
    
    Dockerfile  testfile
    
    root@ubuntu:~#
    
    root@ubuntu:~# docker build -t test/ubuntu:v2 .
    
    Sending build context to Docker daemon 32.77 kB
    
    Step 1 : FROM ubuntu
    
     ---> f753707788c5
    
    Step 2 : RUN apt-get update && apt-get install -y vim
    
     ---> Using cache         ②
    
     ---> 35ca89798937
    
    Step 3 : COPY testfile /---> 8d02784a78f4
    
    Removing intermediate container bf2b4040f4e9
    
    Successfully built 8d02784a78f4

          对上面的步骤进行相应的说明:先确保testfile文件存在。在Dockerfile文件执行过程中,运行RUN指令时,由于之前已经运行过相同的RUN指令,这次直接使用缓存中的镜像层。最后直接执行COPY指令,其过程是启动临时容器,复制testfile文件,提交新的镜像层,再删除生成的临时容器。全部过程执行完毕,就得到了所需的在test/ubuntu镜像上直接添加一层新的镜像的test/ubuntu:v2

          如果构建镜像时不想使用缓存,可以在docker build命令中添加--no-cache参数

          Dockerfile中每一个指令都会创建一个镜像层,上层依赖下层。无论什么时候,只要某一层发生变化,其上面的所有层的缓存都会失效。也就是说,如果我们修改Dockerfile指令的顺序,或者修改、添加指令,都会使缓存失效

          比如这里修改前面的Dockerfile文件,交换一下指令的执行顺序

          从逻辑上说,这对整个镜像的构建没有什么影响,但对于docker镜像的缓存来说,这里已经改变了下层镜像的结构,而上层镜像依赖于下层镜像,当下层镜像发生变化时,原来的镜像缓存则不再生效。这里的执行过程:先执行FROM指令,在本地找到基础镜像并运行一个容器,然后在该容器中执行COPY指令,该指令执行完毕后删除生成的临时容器,最后再执行RUN指令。如果是前面的顺序,执行RUN指令时会直接用test/ubuntu镜像的缓存,但这里先是执行了COPY指令,导致下层镜像发生变化,所以这里得重新执行RUN指令,其过程与test/ubuntu的过程一样

    调试Dockerfile

    先后顾Dockerfile构建镜像的过程

          1. 从基础镜像运行一个容器

          2. 执行一条指令,对容器进行修改

          3. 执行类似docker commit的操作,生成一个新的镜像层

          4. Docker再基于刚提交的镜像运行一个新的容器

          5. 重复2-4步,直到Dockerfile中的所有指令执行完毕

          从这个过程可以看出,如果Dockerfile由于某种原因执行到某个指令失败了,我们也能够得到前一个指令成功执行构建出的镜像,这对调试很有帮助,可以运行最新的镜像来定位指令失败的原因

    下面来看一个调试的例子,Dockerfile文件的内容如下 

    执行docker build

    Dockerfile运行到第三部时失败,我们可以利用第二步得到的镜像进行调试,方法是docker run -it启动镜像的一个容器 

          手工执行RUN命令很容易定位失败的原因,此处是因为busybox镜像中没有bash。这个例子很好的展示了Dockerfile的调试方法

    Dockerfile常用的指令

          FROM:指定基础镜像

          MAINTAINER:说明镜像作者信息,可以是任意字符串。它不是Dockerfile的必要内容,但为了便于镜像的维护,建议写上去

          COPY:将文件从build context复制到镜像

          ADD:与COPY类似,从build context复制文件到镜像。不同的是,如果src是归档文件,文件会被自动解压到dest

          ENV:设置环境变量,环境变量可被后面的指令使用

          EXPOSE:指定容器中的进程会监听某个端口,Docker可以将该端口暴露出来

          VOLUME:将文件或目录声明为volume

          WORKDIR:为后面的RUN、CMD、ENTRYPOINT、ADD、COPY指令设置镜像中的当前工作目录

          RUN:在容器中运行指定的命令

          CMD:容器启动时运行指定的命令。Dockerfile中可以有多个CMD指令,但只有最后一个生效。CMD可被docker run之后的参数替换

          ENTRYPOINT:设置容器启动时运行的命令。Dockerfile中可以有多个ENTRYPOINT指令,但只有最后一个生效。CMD或docker run之后的参数会被当做参数传递给ENTRYPOINT

    RUN、CMD、ENTRYPOINT的区别

          1. RUN执行命令并创建新的镜像层,RUN经常用于安装软件包

          2. CMD设置容器启动后默认执行的命令及其参数,但CMD能够被docker run后面跟的命令行参数替换

          3. ENTRYPOINT配置容器启动时运行的命令

    RUN

          下面是使用RUN安装多个软件包的例子

    RUN apt-get update && apt-get install -y   
    
     wireshark
    
     vim
    
     wget 
    
     mercurial 
    
     subversion

          注意:apt-get update和apt-get install被放在一个RUN指令中执行,这样能够保证每次安装的是最新的包。如果apt-get install在单独的RUN中执行,则会使用apt-get update创建的镜像层,而这一层可能是很久以前的缓存了

    CMD

    此命令在容器启动且docker run没有指定其他命令时运行

          1. 如果docker run指定了其他命令,CMD指定的默认命令会被忽略

          2. 如果Dockerfile中有多个CMD指令,只有最后一个有效

    下面看看CMD是如何工作的,Dockerfile片段如下

    CMD echo “Hello world”

    运行容器docker run -it [ image ] 将输出

    Hello world

    但当后面加一个命令,比如docker run -it [ image ] /bin/bash,CMD会被忽略掉,命令bash将被执行

    root@10a32dc7d3d3:/#

    ENTRYPOINT

          ENTRYPOINT指令可让容器以应用程序或者服务的形式运行

          ENTRYPOINT看上去和CMD很像,它们都可以指定要执行的命令及其参数,不同的地方在于ENTRYPOINT不会被忽略,一定会被执行,即使运行docker run时指定了其他命令

    使用公共Registry

    下面介绍如何使用Docker Hub存放镜像

    1. 首先得在Docker Hub上注册一个账号(当我们在hub.docker.com上注册账号时发现不能注册,可以在用谷歌浏览器登录,并在上面安装谷歌访问助手,安装完成后并可以注册。另一种方法是直接翻墙)

    2. 在Docker Hub上登录 

    这里用的是我自己的账号,用户名为chenjin2018,输入密码即可登录

    3. 修改镜像的repository使之与Docker Hub账号匹配

    Docker Hub为了区分不同用户名的同名镜像,镜像的registry中要包含用户名,完整个格式为:[username]/xxx:tag

    我们通过docker tag命令重命名镜像 

    4. 通过docker push将镜像上传到Docker Hub 

    5. 登录hub.docker.com,在Public Repository中就可以看到上传的镜像 

    如果要删除镜像,只能在Docker Hub界面上操作

    6. 其他用户只需用docker pull就可以下载并使用这个镜像了

    搭建本地的Registry

    1. 启动registry容器

    我们使用的镜像是registry:2

    -d是以守护方式启动容器

    -p将容器的5000端口映射到Host的5000端口。5000是registry服务端口

    -v将容器/var/lib/registry目录映射到Host的/myregistry,用于存放镜像数据

    2. 通过docker tag重命名镜像,使之与registry匹配 

    我们在镜像前面加了运行registry的主机名称和端口

    repositroy的完整格式:[registry-host]:[port]/[username]/xxx

    只有Docker Hub上的镜像可以省略[registry-host]:[port]

    3. 通过docker push上传镜像 

    4. 现在已经可以通过docker pull从本地registry下载镜像了

    Docker镜像小结

    下面是镜像的常用操作子命令

          images   显示镜像列表
    
          history  显示镜像构建历史
    
          commit   从容器创建新镜像
    
          build    从Dockerfile中构建新镜像
    
          tag      给镜像打tag
    
          pull     从registry下载镜像
    
          push     将镜像上传到registry
    
          rmi      删除Docker host中的镜像
    
          search   搜索Docker Hub中的镜像
  • 相关阅读:
    网络编程的基础
    day31作业
    异常处理其他内容
    异常处理的使用
    常见的异常种类
    ansible条件使用--实践
    Ansible的循环
    Ansible的条件语句
    ansibleplaybook的使用
    ansible官方文档翻译之变量
  • 原文地址:https://www.cnblogs.com/chenjin2018/p/9822609.html
Copyright © 2011-2022 走看看