一、FROM 语法
scratch -- 从头开始
尽量来使用官方提供的image。
二、label语法
meta信息,类似于代码的注释。
三、run语法
没run一次image上会有新的一层。因此有必要使用&&合并执行,避免layer 过多看起来很混乱。
四、workdir 语法
使用workdir不要使用run cd来替代
workdir尽量使用绝对路径。增强dockerfile的可移植性。
五、add 和copy 语法
- 区别:add 还具有解压缩的功能,例如add test.tat.gz /
- workdir 和add的结合
- 添加远程文件/目录使用curl 或者 wget
copy文件夹时候的坑
https://www.jianshu.com/p/9b7da9aacd8a
六、ENV语法
定义常量,增加可维护性,和shell中定义变量一个意思。
七、volume 和expose 语法
八、run、cmd 和entrypoint
例子:
shell 格式的docker file build的image
[root@iZ2vceej7yes1abpm7yec2Z dockerfile]# more Dockerfile FROM centos ENV name Docker ENTRYPOINT echo "hello $name" [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker build -t ninesun0318/centos-entrypoint-shell . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM centos ---> 0d120b6ccaa8 Step 2/3 : ENV name Docker ---> Running in 00b2f71e6d9f Removing intermediate container 00b2f71e6d9f ---> 4be9a34323b3 Step 3/3 : ENTRYPOINT echo "hello $name" ---> Running in cfc67b613f7a Removing intermediate container cfc67b613f7a ---> 865aaaacd1ee Successfully built 865aaaacd1ee Successfully tagged ninesun0318/centos-entrypoint-shell:latest [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ninesun0318/centos-entrypoint-shell latest 865aaaacd1ee 17 seconds ago 215MB centos latest 0d120b6ccaa8 2 months ago 215MB hello-world latest bf756fb1ae65 10 months ago 13.3kB [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker run 865aaaacd1ee hello Docker
很完美这个dockerfile没有问题。
exec格式的docker file build的image
[root@iZ2vceej7yes1abpm7yec2Z dockerfile]# more Dockerfile FROM centos ENV name Docker ENTRYPOINT ["/bin/echo", "hello $name"] [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker build -t ninesun0318/centos-entrypoint-exec . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM centos ---> 0d120b6ccaa8 Step 2/3 : ENV name Docker ---> Using cache ---> 4be9a34323b3 Step 3/3 : ENTRYPOINT ["/bin/echo", "hello $name"] ---> Running in 61c84954936b Removing intermediate container 61c84954936b ---> 2292313abbf0 Successfully built 2292313abbf0 Successfully tagged ninesun0318/centos-entrypoint-exec:latest [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ninesun0318/centos-entrypoint-exec latest 2292313abbf0 5 seconds ago 215MB ninesun0318/centos-entrypoint-shell latest 865aaaacd1ee 8 minutes ago 215MB centos latest 0d120b6ccaa8 2 months ago 215MB hello-world latest bf756fb1ae65 10 months ago 13.3kB [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker run ninesun0318/centos-entrypoint-exec hello $name [root@iZ2vceej7yes1abpm7yec2Z dockerfile]#
奇怪exec 并没有把name 这个ENV打印出来。为何?
只有shell 中才会执行name才会被解释为变量,exec 就是简单的执行。
如何修改呢?
[root@iZ2vceej7yes1abpm7yec2Z dockerfile]# more Dockerfile FROM centos ENV name Docker ENTRYPOINT ["/bin/bash","-c","echo hello $name"] [root@iZ2vceej7yes1abpm7yec2Z dockerfile]#
重新build 然后run
[root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker build -t ninesun0318/centos-entrypoint-exec-new . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM centos ---> 0d120b6ccaa8 Step 2/3 : ENV name Docker ---> Using cache ---> 4be9a34323b3 Step 3/3 : ENTRYPOINT ["/bin/bash","-c","echo hello $name"] ---> Running in 5ee34add9195 Removing intermediate container 5ee34add9195 ---> cf961663ddc1 Successfully built cf961663ddc1 Successfully tagged ninesun0318/centos-entrypoint-exec-new:latest [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker run ninesun0318/centos-entrypoint-exec-new hello Docker [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# more Ddo more: stat of Ddo failed: No such file or directory
这个问题得到了解决。
例子说明:entrypoint 一定会被执行,cmd 会被覆盖。
[root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ninesun0318/centos-cmd-shell latest d4ba5c0ae032 4 minutes ago 215MB ninesun0318/centos-entrypoint-cmd latest d4ba5c0ae032 4 minutes ago 215MB ninesun0318/centos-entrypoint-exec-new latest cf961663ddc1 12 minutes ago 215MB ninesun0318/centos-entrypoint-shell latest 865aaaacd1ee 24 minutes ago 215MB centos latest 0d120b6ccaa8 2 months ago 215MB hello-world latest bf756fb1ae65 10 months ago 13.3kB [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker run -it ninesun0318/centos-entrypoint-shell /bin/bash hello Docker [root@iZ2vceej7yes1abpm7yec2Z dockerfile]# docker run -it ninesun0318/centos-cmd-shell /bin/bash [root@d8c93ad6de43 /]#
ARG和ENV的区别
- ARG 是构建时变量
- ENV是运行时变量
1、ARG
ARG指令定义了一个变量,用户可以在构建时使用--build-arg = 传递,docker build命令会将其传递给构建器。--build-arg 指定参数会覆盖Dockerfile 中指定的同名参数
如果用户指定了 未在Dockerfile中定义的构建参数 ,则构建会输出 警告 。
ARG只在构建期有效,运行期无效
不建议使用构建时变量来传递诸如github密钥,用户凭据等机密。因为构建时变量值使用docker
history是可见的。
ARG变量定义从Dockerfile中定义的行开始生效。
使用ENV指令定义的环境变量始终会覆盖同名的ARG指令。
2、ENV
- 在构建阶段中所有后续指令的环境中使用,并且在许多情况下也可以内联替换。
- 引号和反斜杠可用于在值中包含空格。
- ENV 可以使用key value的写法,但是这种不建议使用了,后续版本可能会删除
ENV MY_MSG hello ENV MY_NAME="John Doe" ENV MY_DOG=Rex\ The\ Dog ENV MY_CAT=fluffy #多行写法如下 ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \ MY_CAT=fluffy
- docker run --env 可以修改这些值
- 容器运行时ENV值可以生效
- ENV在image阶段就会被解析并持久化(docker inspect image查看),参照下面示例
FROM alpine ENV arg=1111111 ENV runcmd=$arg RUN echo $runcmd CMD echo $runcmd #ENV的固化问题: 改变arg,会不会改变 echo的值,会改变哪些值,如何修改这些值?
- 测试案例
FROM alpine ARG arg1=22222 ENV arg2=1111111 ENV runcmd=$arg1 RUN echo $arg1 $arg2 $runcmd CMD echo $arg1 $arg2 $runcmd