ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

docker镜像

2020-02-21 17:10:38  阅读:18  来源: 互联网

标签:容器 RUN CMD ENTRYPOINT 镜像 docker



base镜像(通常为各种linux发行版的docker镜像):

 (1)不依赖其他镜像,从scratch构建

 (2)其他镜像可以以之为基础创建

镜像的分层结构

 新镜像是从base镜像层一层一层叠加生成的。没安装一个软件,就现有镜像的基础层面上面增加一层

 好处:共享资源。比如有多个镜像都是从相同的base镜像构建而来,那么docker host只需要在磁盘上保存一份base镜像;同时,内存中也只需要增加一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享

 镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,用户只能访问上层容器中的文件。在容器层中,用户看到的是一个叠加之后的文件系统

 (1)添加文件。在容器中创建文件时,新文件被添加到容器层中

 (2)读取文件。在容器中读取某个文件时,docker会从上往下依次搜索各镜像层中查找此文件,一旦找到,打开并读入内存

 (3)修改文件。在容器中修改已存在的文件时,docker会从上往下依次在各镜像层中查找此文件,一旦查找到,立即将其复制到容器层,然后修改之

 (4)删除文件。在容器中删除文件时,docker也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作

注:只有方需要修改时才复制一份数据。这种特性被称做copy-on-write。可见。容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改

构建镜像

 (1)docker commit

     步骤:1.运行容器

                 2.修改容器
                 3.将容器保存为新镜像(docker commit 旧镜像名 新镜像名)

 (2)docker file

     步骤:1.编写dockerfile文件

                 2.运行docker build命令(docker build -t 新镜像名 .(命令末尾的.指明build-context为当前目录。docker默认会从build context中查找dockerfile文件,我们也可以通过-f参数指定dockerfile的位置))

                  3.开始构建过程,首先docker将docker context中的所有文件发送给docker daemon。build context为镜像构建提供所需要的文件或目录。dockerfile中的ADD、COPY等命令可以将build context中的文件添加到镜像

                  4.按dockerfile文件内容进行执行指令

                  5.镜像构建成功

查看镜像分层结构:docker history 镜像名

 

注:missing表示无法获取image id,通常从docker hub下载的镜像会有这个问题

镜像的缓存特性

 docker会缓存已有的镜像层,构建镜像时,如果某镜像层已经存在,就直接使用,无需创建,如果不希望在构建镜像时使用缓存,可以在docker build命令中加上--no-cache参数。dockerfile中每一个指令都会创建一个镜像层,上层依赖于下层的。无论什么时候,只要某一层发生变化,其上面所有层的缓存都会失效。除了构建时使用缓存,docker在下载镜像时也会使用

调试dockerfile

 在执行dockerfile时,如果因为某种原因执行到某个指令失败了,也能够得到前一个指令成功执行构建出的容器,可以运行新的镜像,手动运行那条失败的指令,从而定位失败的原因

dockerfile常用指令

 FROM:指定base镜像

 MAINTAINER:设置镜像的作者,可以是任意字符串

 COPY:将文件从build context复制到镜像。COPY支持两种形式:COPY src dest与COPY [“scr”,”dest”]

       注意:src只能指定build context中的文件或目录

  ADD:与COPY类似,从build context复制文件到镜像。不同的是,如果src是归档类文件(tar、zip、tgz、xz等),文件会被解压到dest

  ENV:设置环境变量,环境变量可被后面的指令使用。例如:ENV MY_VERSION 1.3 RUN apt-get install -y mypackage=$MY_VERSION

  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 vs CMD vs ENTRYPOINT

 RUN、CMD、ENTRYPOINT这三个dockerfile指令看上去很类似,很容易混淆。本节将通过实践详细讨论它们的区别

 简单的说:

  1. RUN:执行命令并创建新的镜像层,RUN经常用于安装软件包
  2. CMD:设置容器启动后默认执行的命令及参数,但CMD能够被docker run后面跟的命令行参数替换
  3. ENTRYPOINT:配置容器启动时运行的命令

 shell和exec格式

 可以用两种方法指定RUN、CMD和ENTRYPOINT要运行的命令:shell格式和exec格式,二者在使用上有细微的差别。

 shell格式:<instruction> <command>

 例如:

 RUN yum install python3

 CMD echo “hello world”

 ENTRYPOINT echo “hello world”

 当执行指令时,shell格式底层会调用/bin/sh -c [command]。例如下面片段:

 ENV name cloud ENTRYPOINT echo “hello,$name”

 执行docker run时,将输出hello,cloud

 exec格式:<instruction> [“executable”,”paraml”,”param2”]

 例如:

 RUN [“apt-get”,”install”,”python3”]

 CMD [“/bin/echo”,”hello world”]

 ENTRYPOINT [“/bin/echo”,”hello world”]

 当执行指令时,会直接调用command,不会被shell解析。例如下面片段:

 ENV name cloud [“/bin/echo”,”hello,$name”]

 运行容器将输出hello,$name

注意:环境变量name没有被替换,如果希望使用环境变量,做如下修改

ENV name cloud ENTRYPOINT [“/bin/sh”,”-c”,”echo hello,$name”]

运行容器将输出hello,cloud

CMD和ENTRYPOINT推荐使用exec格式,因为指令可读性更强,更容易理解。RUN则两种格式都可以

RUN

RUN指令通常用于安装应用和软件包,RUN在当前镜像的顶部执行命令,并创建新的镜像层。dcokerfile中常常包含多个RUN指令。

 RUN有两种格式:

(1)shell格式:RUN

(2)exec格式:RUN [“executable”,”param1”,”param2”]

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

 RUN apt-get u[date && apt-get install -y subversion

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

 CMD

 CMD指令允许用户指定容器的默认执行的命令,此命令会在容器启动且docker run没有指定其他命令时运行

 如果docker run指定了其他命令,CMD指定的默认命令将被忽略,如果dockerfile中有多个CMD指令,只有最后一个有效

 CMD有三种格式:

(1)exec格式:CMD [“executable”,”param1”,”param2”]这是CMD推荐格式

(2)CMD [“param1”,”param2”]为ENTRYPOINT提供额外的参数,此时ENTRYPOINT必须使用exec格式

(3)shell格式:CMD command param1 param2

 第一种和第三种已经介绍过了,第二种要与exec格式的ENTRYPOINT指令配合使用,其用途是为ENTRYPOINT设置默认的参数。

下面看看CMD是如何工作的。dockerfile片段如下:

CMD echo “hello world”

运行容器docker run -it [image]将输出:hello world,但在后面加上一个命令,比如docker run -it [image] /bin/bash,CMD会被忽略掉,命令bash将被执行

 ENTRYPOINT

 ENTRYPOINT指令可以让容器以应用程序或者服务的形式运行,ENTRYPOINT看上去与CMD很像,它们都可以指定要执行的命令及参数。不同之处在于ENTRYPOINT不会被忽略,一定会被执行,即使docker run时指定了其他命令

 ENTRYPOINT有两种格式:

  1. exec格式:ENTRYPOINT [“executable”,”param1”,”param2”]这是ENTRYPOINT的推荐格式
  2. shell格式:ENTRYPOINT command param1 param2

 在为ENTRYPOINT选择格式时必须要小心,因为这两种格式的效果差别很大

  1. exec格式

 ENTRYPOINT的exec格式用于设置要执行的命令及参数,同时可以通过CMD提供额外的参数,ENTRYPOINT中的参数始终会被使用,而CMD的额外参数可以在启动容器时动态替换

 比如下面的dockerfile片段:

 ENTRYPOINT [“/bin/echo”,”hello”] CMD [“world”]

 当容器通过docker run -it [image]启动时,输出为:hello world

 而如果通过docker run -it [image] cloud时,输出为:hello cloud

       2.shell格式

 ENTRYPOINT的shell格式会忽略任何CMD给docker run提供的参数

分发镜像

 为镜像命名

     镜像名一般是两部分组成的:[image name]=[repository]:[tag],如果没有指定tag,默认会使用latest,tag常用于描述镜像的版本信息,可以是任意字符串

     注:latest其实没有什么特殊含义。当没有指定镜像tag时,docker会使用默认值latest,仅此而已。docker hub上很多仓库将latest作为最新稳定版本的别称,但这只是一种约定,而不是强制规定,所以最好还是避免使用这个

     命令:docker tag 旧镜像名 新镜像名

使用公共registry

 docker hub是docker公司维护的公共registry。用户可以将自己的镜像保存在docker hub免费的repository中,如果不希望别人访问自己的镜像,也可以购买私有repository

 (1)首先在docker hub上注册一个账号

 (2)在docker host上登录(docker login -u 用户名)

 (3)修改镜像的repoistory,使之与docker hub账号对应。docker hub为了区分不同的同名镜像,镜像的registry中要包含用户名,完整的格式为:[username]/xxx:tag。通过docker tag命令重命名镜像

 (4)docker push 镜像名:将镜像上传到docker hub

 搭建本地registry

 (1)启动registry容器(使用的是registry:2镜像)

 -d:后台启动容器

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

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

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

 

 在镜像前面加上了registry的主机名称和端口。前面已经讨论了镜像名称由repository和tag两部分组成。而repository的完整格式为:[registry-host]:[port]/[username]/xxx,只有docker hub上的镜像可以省略registry-host:[port]

 (2)通过docker push上传镜像,此时,就可以使用docker pull进行下载镜像。

啸月々兲狼 发布了11 篇原创文章 · 获赞 1 · 访问量 1250 私信 关注

标签:容器,RUN,CMD,ENTRYPOINT,镜像,docker
来源: https://blog.csdn.net/qq_37339132/article/details/104424532

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有