目录
一、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