看完这篇,再也不用焦虑如何写dockerfile了( 二 )


EXPOSE 80/tcpEXPOSE 80/udpUSER格式: USER <user>[:<group] 或者 USER <UID>[:<GID>]
USER指令设置了user name和user group(可选) 。在它之后的RUN,CMD以及ENTRYPOINT指令都会以设置的user来执行 。
WORKDIR格式: WORKDIR /path/to/workdir
WORKDIR指令设置工作目录,它之后的RUN、CMD、ENTRYPOINT、COPY以及ADD指令都会在这个工作目录下运行 。如果这个工作目录不存在,则会自动创建一个 。WORKDIR指令可在Dockerfile中多次使用 。如果提供了相对路径,则它将相对于上一个WORKDIR指令的路径 。例如
WORKDIR /aWORKDIR bWORKDIR cRUN pwd输出结果是 /a/b/c
RUN格式1: RUN <command> (shell格式)格式2: RUN ["executable", "param1", "param2"] (exec格式,推荐使用)
RUN指令会在前一条命令创建出的镜像的基础上创建一个容器,并在容器中运行命令,在命令结束运行后提交容器为新镜像,新镜像被Dockerfile中的下一条指令使用 。
RUN指令的两种格式表示命令在容器中的两种运行方式 。当使用shell格式时,命令通过/bin/sh -c运行 。当使用exec格式时,命令是直接运行的,容器不调用shell程序,即容器中没有shell程序 。exec格式中的参数会被当成JSON数组被Docker解析,故必须使用双引号而不能使用单引号 。因为exec格式不会在shell中执行,所以环境变量的参数不会被替换 。
比如执行RUN ["echo", "$HOME"]指令时,$HOME不会做变量替换 。如果希望运行shell程序,指令可以写成 RUN ["/bin/bash", "-c", "echo", "$HOME"] 。
CMDCMD指令有3种格式 。
格式1:CMD <command> (shell格式)格式2:CMD ["executable", "param1", "param2"] (exec格式,推荐使用)格式3:CMD ["param1", "param2"] (为ENTRYPOINT指令提供参数)
CMD指令提供容器运行时的默认值,这些默认值可以是一条指令,也可以是一些参数 。一个Dockerfile中可以有多条CMD指令,但只有最后一条CMD指令有效 。CMD ["param1", "param2"]格式是在CMD指令和ENTRYPOINT指令配合时使用的,CMD指令中的参数会添加到ENTRYPOING指令中.使用shell和exec格式时,命令在容器中的运行方式与RUN指令相同 。
不同之处在于,RUN指令在构建镜像时执行命令,并生成新的镜像;CMD指令在构建镜像时并不执行任何命令,而是在容器启动时默认将CMD指令作为第一条执行的命令 。如果用户在命令行界面运行docker run命令时指定了命令参数,则会覆盖CMD指令中的命令 。
ENTRYPOINTENTRYPOINT指令有两种格式 。
格式1:ENTRYPOINT <command> (shell格式)格式2:ENTRYPOINT ["executable", "param1", "param2"] (exec格式,推荐格式)
ENTRYPOINT指令和CMD指令类似,都可以让容器在每次启动时执行相同的命令,但它们之间又有不同 。一个Dockerfile中可以有多条ENTRYPOINT指令,但只有最后一条ENTRYPOINT指令有效 。
当使用Shell格式时,ENTRYPOINT指令会忽略任何CMD指令和docker run命令的参数,并且会运行在bin/sh -c中 。这意味着ENTRYPOINT指令进程为bin/sh -c的子进程,进程在容器中的PID将不是1,且不能接受Unix信号 。即当使用docker stop <container>命令时,命令进程接收不到SIGTERM信号 。
推荐使用exec格式,使用此格式时,docker run传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT指令的参数中 。从ENTRYPOINT的使用中可以看出,CMD可以是参数,也可以是指令,而ENTRYPOINT只能是命令;另外,docker run命令提供的运行命令参数可以覆盖CMD,但不能覆盖ENTRYPOINT 。
Dockerfile实践心得使用标签给镜像打上标签,有利于帮助了解进镜像功能
谨慎选择基础镜像选择基础镜像时,尽量选择当前官方镜像库的肩宽,不同镜像的大小不同,目前linux镜像大小由如下关系:
busybox < debian < centos < ubuntu
同时在构建自己的Docker镜像时,只安装和更新必须使用的包 。此外相比Ubuntu镜像,更推荐使用Debian镜像,因为它非常轻量级(目前其大小是在100MB以下),并且仍然是一个完整的发布版本 。
充分利用缓存Docker daemon会顺序执行Dockerfile中的指令,而且一旦缓存失效,后续命令将不能使用缓存 。为了有效地利用缓存,需要保证指令的连续性,尽量将所有Dockerfile文件相同的部分都放在前面,而将不同的部分放到后面 。
正确使用ADD与COPY命令当在Dockerfile中的不同部分需要用到不同的文件时,不要一次性地将这些文件都添加到镜像中去,而是在需要时添加,这样也有利于重复利用docker缓存 。另外考虑到镜像大小问题,使用ADD指令去获取远程URL中的压缩包不是推荐的做法 。应该使用RUN wget或RUN curl代替 。这样可以删除解压后不在需要的文件,并且不需要在镜像中在添加一层 。


推荐阅读