学习是一个逐步发现自己无知的过程!

Dockerfile构建镜像详解

Dockerfile

​ Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfile指令翻译真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。

Dockerfile文件说明

​ 默认文件名”Dockerfile“ Dcoker默认就读取这个文件进行构建。

​ Dockerfile的指令是忽略大小写的,建议使用大写,使用#作为注释,每一行只支持一条指令,每条指令可以携带多个参数。

​ Dockerfile的指令根据作用可以分为两种,构建指令和设置指令。构建指令用于构建image,其指定的操作不会在运行image的容器上执行;设置指令用于设置image的属性,其指定的操作将在运行image的容器中执行。

  • 这张图非常的形象,下面有详细解释

file

Dockerfile指令

1. FROM 基础镜像

​ 功能为指定基础镜像,并且必须是第一条指令、后续的指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库。

​ 如果不以任何镜像为基础,那么写法为:FROM scratch。

​ 同时意味着接下来所写的指令将作为镜像的第一层开始。

格式:
  FROM <image>
  FROM <image>:<tag>
示例:
  FROM mysql:5.7

2. MAINTAINER 维护者信息

​ MAINTAINER指令设置生成图像的作者字段,用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。

格式:
    MAINTAINER <name>
示例:
    MAINTAINER Jasper Xu
    MAINTAINER sorex@163.com
    MAINTAINER Jasper Xu <sorex@163.com>

3. ENV 环境变量

​ 该ENV指令将环境变量<key>设置为 value <value>。此值将在构建阶段的所有后续指令的环境中,并且也可以在许多中内联替换。该值将被解释为其他环境变量,因此如果未转义引号字符将被删除。与命令行解析一样,引号和反斜杠可用于在值中包含空格。

格式:
    ENV <key> <value>  #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
    ENV myName JoJo Li
    ENV myDom Rex The Dom
    ENV myCat=fluffy

4. WORKDIR 工作目录

​ 该WORKDIR指令集的工作目录对任何RUNCMDENTRYPOINTCOPYADD它后面的说明Dockerfile。如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,也会被创建。

​ 该WORKDIR指令可以在一个Dockerfile. 如果提供了相对路径,它将相对于前一条WORKDIR指令的路径 。例如:

格式:
    WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
    WORKDIR b  (这时工作目录为/a/b)
    WORKDIR c  (这时工作目录为/a/b/c)

5. RUN 执行命令

RUN有两种形式:

  • RUN <command>shell形式,命令在 shell 中运行,默认/bin/sh -c在 Linux 或cmd /S /CWindows 上)
  • RUN ["executable", "param1", "param2"]执行形式)

RUN指令将在当前镜像之上的新层中执行任何命令并提交结果。生成的提交v将用于Dockerfile,分层RUN指令和生成提交符合 Docker 的核心概念,其中提交成本低,并且可以从镜像历史中的任何点创建容器,就像源代码控制一样。

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:
    RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

6. ADD 复制文件并解压缩

​ 构建指令,所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0;如果是一个目录,那么会将该目录下的所有文件添加到container中,不包括目录;如果文件是可识别的压缩格式,则docker会帮忙解压缩(注意压缩格式);如果是文件且中不使用斜杠结束,则会将视为文件,的内容会写入;如果是文件且中使用斜杠结束,则会文件拷贝到目录下。

​ tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget。

格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /www/    # 添加 "test" 到 /www/
    ADD test.tar.gz /www/    # 添加 "test.tar.gz" 到 /www/ 并自动解压

7. COPY 复制文件

​ 复制文件到容器中,与ADD指令作用相同,但是不会自动解压,因此一般文件都是用该指令。

8. EXPOSE 映射端口

​ 设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项。

格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080    EXPOSE 11211/tcp 11211/udp
注:  
    EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

9. CMD

​ 设置指令,用于container启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD echo "This is a test." | wc -
    CMD ["/usr/bin/wc","--help"]注:   CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

10. USER 运行用户

​ 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

​ 使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

 格式:
  USER user
  USER user:group
  USER uid
  USER uid:gid
  USER user:gid
  USER uid:group

 示例:
  USER www
  USER daemon 
  ENTRYPOINT ["memcached", "-u", "daemon"]

11. VOLUME 挂载点

​ 创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。

​ Volume设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。

格式:
    VOLUME [“”]

示例:
    FROM base  
    VOLUME ["/tmp/data"]

​ 运行通过该Dockerfile生成image的容器,/tmp/data目录中的数据在容器关闭后,里面的数据还存在。例如另一个容器也有持久化数据的需求,且想使用上面容器共享的/tmp/data目录,那么可以运行下面的命令启动一个容器:

docker run -t -i -rm -volumes-from container1 image2 bash

# container1为第一个容器的ID,image2为第二个容器运行image的名字。

12. ENTRYPOINT container启动参数

​ 设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。

格式:
    ENTRYPOINT [“executable”, “param1”, “param2”] # 可执行文件 优先 
    ENTRYPOINT command param1 param2 # shell内部命令

​ 该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用。

​ 当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效。

# CMD指令将不会被执行,只有ENTRYPOINT指令被执行  
CMD echo “Hello, World!”  
ENTRYPOINT ls -l

​ 另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分;ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数。

FROM ubuntu  
CMD ["-l"]  
ENTRYPOINT ["/usr/bin/ls"]

13. ONBUILD 镜像触发器

​ 该ONBUILD指令将一个触发指令添加到图像中,以便稍后在该图像用作另一个构建的基础时执行。触发器将在下游构建的上下文中执行,就好像它是FROM在下游的指令之后立即插入 的Dockerfile

​ 任何构建指令都可以注册为触发器。

​ 例如,如果您的映像是可重用的 Python 应用程序构建器,则需要将应用程序源代码添加到特定目录中,并且可能需要之后调用构建脚本。您不能只调用ADDand RUNnow,因为您还没有访问应用程序源代码的权限,并且每个应用程序构建都会有所不同。您可以简单地为应用程序开发人员提供一个样板,Dockerfile以便将其复制粘贴到他们的应用程序中,但这效率低下、容易出错且难以更新,因为它与特定于应用程序的代码混合在一起。

​ 当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

格式:
    ONBUILD [INSTRUCTION]
示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src
赞(0)
未经允许不得转载:劉大帥 » Dockerfile构建镜像详解

你的评论可能会一针见血! 抢沙发

登录

找回密码

注册