??前面的docker镜像管理章节有说到,构建镜像的方式有两种:一种是基于容器制作,另一种就是通过Dockerfile。Dockerfile其实就是我们用来构建Docker镜像的源码,当然这不是所谓的编程源码,而是一些命令的组合,只要理解它的逻辑和语法格式,就可以编写Dockerfile。
??简要概括Dockerfile的作用:它可以让用户个性化定制Docker镜像。因为工作环境中的需求各式各样,网络上的镜像很难满足个人的需求。
?
Dockerfile整体就两类语句组成:
Dockerfile中需要调用的文件必须跟Dockerfile文件在同一目录下,或者在其子目录下,父目录或者其它路径无效。
?
Introduction
Syntax
FROM <Repository>@<Digest>
Introduction
Syntax
Introduction
Syntax
Introduction
Syntax
COPY ["<src>",... "<dest>"]
Rules
Introduction
ADD指令跟COPY类似,不过它还支持使用tar文件和URL路径。
Syntax
Introduction
Syntax
WORKDIR 相对路径或者绝对路径
Introduction
Syntax
Introduction
Syntax
Introduction
Syntax
ENV <key>=<value> ...
Example
# 基于busybox启动一个镜像,将test文件拷贝至容器内的/usr/local/aaa/目录下。
[root@docker1 docker]# pwd
/server/docker--rm
[root@docker1 docker]# echo 1111 >test
[root@docker1 docker]# vim Dockerfile
# Description: test image
FROM busybox
ENV file=aaa
ADD ./test /usr/local/$file/
[root@docker1 docker]# docker build -t busy:v1 ./
# 根据此镜像启动容器并查看文件是否拷贝成功,并且查看file变量的值
[root@docker1 docker]# docker run --name busy02 --rm busy:v1 ls /usr/local/aaa
test
[root@docker1 docker]# docker run --name busy02 --rm busy:v1 printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=57111b7b246c
file=aaa
HOME=/root
# 接下来我们在启动容器的时候加上-e参数为file变量指定一个新值,并且查看file变量的值
[root@docker1 docker]# docker run --name busy02 -e file=bbb --rm busy:v1 printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=787ad8585fc0
file=bbb
HOME=/root
# 此时再看test的文件,依然是在aaa的目录下的
[root@docker1 docker]# docker run --name busy02 -e file=bbb --rm busy:v1 ls /usr/local/aaa
test
# 这是因为docker build属于第一阶段,而docker run属于第二阶段。第一阶段定义file变量的值aaa已经被引用了,生米已经煮成熟饭了,后续阶段再改file变量的值也影响不了aaa。
Introduction
Syntax
RUN ["executable", "param1", "param2"]
Introduction
类似于RUN指令,也可以运行任意命令或程序,但是两者的运行时间点不同
Syntax
CMD ["param1","param2"]
Introduction
Syntax
Example
# 还是以httpd服务做举例,先以CMD指令开始
[root@docker1 docker]# vim Dockerfile
# Description: test image
FROM busybox
LABEL maintainer="merle <merle@freeit.com>" app="httpd"
ENV WEBDIR="/data/web/html"
RUN mkdir -p ${WEBDIR} && echo 'this is a test web' > ${WEBDIR}/index.html
CMD [ "sh","-c","/bin/httpd -f -h ${WEBDIR}" ]
[root@docker1 docker]# docker build -t httpd:v1 ./
[root@docker1 docker]# docker run --name web01 -it --rm httpd:v1
# 此时为前台运行,复制一个窗口,kill掉容器,然后开始docker run结尾传入新的指令
[root@docker1 ~]# docker kill web01
web01
[root@docker1 docker]# docker run --name web01 -it --rm httpd:v1 ls /data/web/html
index.html
# 可以看出命令行的参数已经替代了原本的CMD指令指定的程序。下面我们再用ENTRYPOINT指令做测试。
-------------------------------------------------------------------------------------------------------------
[root@docker1 docker]# vim Dockerfile
# Description: test image
FROM busybox
LABEL maintainer="merle <merle@freeit.com>" app="httpd"
ENV WEBDIR="/data/web/html"
RUN mkdir -p ${WEBDIR} && echo 'this is a test web' > ${WEBDIR}/index.html
ENTRYPOINT [ "sh","-c","/bin/httpd -f -h ${WEBDIR}" ]
[root@docker1 docker]# docker build -t httpd:v2 ./
[root@docker1 docker]# docker run --name web01 -it --rm httpd:v2
# 也是前台启动,复制一个窗口,kill掉容器,然后开始docker run结尾传入新的指令
[root@docker1 docker]# docker run --name web01 -it --rm httpd:v2 ls /data/web/html
# 可以看到没有反应,这种情况其实是吧ls /data/web/html当做参数传给了/bin/httpd -f -h ${WEBDIR}程序。只是httpd不识别罢了。我们kill掉容器。加上--entrypoint参数再试一下
[root@docker1 docker]# docker run --name web01 -it --rm --entrypoint="" httpd:v2 ls /data/web/html
index.html
# 使用--entrypoint参数替换命令成功。
# 再测试下CMD的第三种语法,CMD指令的后面的命令作为参数传给ENTRYPOINT指令后的命令
[root@docker1 docker]# vim Dockerfile
# Description: test image
FROM busybox
LABEL maintainer="merle <merle@freeit.com>" app="httpd"
ENV WEBDIR="/data/web/html"
RUN mkdir -p ${WEBDIR} && echo 'this is a test web' > ${WEBDIR}/index.html
CMD [ "/bin/httpd -f -h ${WEBDIR}" ]
ENTRYPOINT [ "sh","-c" ]
[root@docker1 docker]# docker build -t httpd:v3 ./
[root@docker1 docker]# docker run --name web01 -it --rm httpd:v3
# OK的,前面有说过:指定ENTRYPOINT的情况下,如果docker run命令行结尾有参数指定,那CMD后面的参数不生效,下面咱再试试,还用v3的镜像。
[root@docker1 docker]# docker run --name web01 -it --rm httpd:v3 "ls /data/web/html"
index.html
Introduction
Syntax
USER <UID>[:<GID>]
Introduction
Syntax
HEALTHCHECK NONE
HEALTHCHECK指令让我们去定义一个CMD,在CMD后面编写一条命令去判断我们的服务运行是否正常。检查肯定不是一次性的,所以OPTIONS就是指定检查的频率等等。
CMD健康检测命令发出时,返回值有三种情况
HEALTHCHECK NONE就是不做健康检查
Example
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
Introduction
Syntax
Introduction
Syntax
Introduction
Syntax
Example
[root@docker1 docker]# vim Dockerfile
FROM nginx:1.14-alpine
ARG AUTHOR="merle <merle@freeit.com>" # 指定默认值
LABEL maintainer=$AUTHOR
ENV NGXDIR='/data/web/html/'
ADD index.html $NGXDIR
ADD entrypoint.sh /bin/
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
[root@docker1 docker]# docker build --build-arg AUTHOR="Jtt <Jtt@freeit.com>" -t nginx:v4 ./
[root@docker1 docker]# docker image inspect nginx:v4 | grep maintainer
"maintainer": "Jtt <Jtt@freeit.com>"
# 上面只是以maintainer举例,实践环境中可以修改为不同jar包的名字构建不同java程序镜像。
Introduction
Syntax
ONBUILD [INSTRUCTION]
Example
[root@docker1 docker]# vim Dockerfile
FROM nginx:1.14-alpine
LABEL maintainer="merle <merle@freeit.com>"
ENV NGXDIR='/data/web/html/'
ADD index.html $NGXDIR
ADD entrypoint.sh /bin/
ONBUILD add http://nginx.org/download/nginx-1.14.0.tar.gz /usr/local/
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
[root@docker1 docker]# docker build -t nginx:v5 ./
[root@docker1 docker]# docker run -it --name web01 --rm nginx:v5 ls /usr/local/
bin lib share
# 上面的结果或者docker build的过程都可以看出并没有执行ONBUILD后面的指令。我们修改Dockerfile中FROM指定的基础镜像为上面构建完的nginx:v5,然后删除ONBUILD指令。
[root@docker1 docker]# vim Dockerfile
FROM nginx:v5
LABEL maintainer="merle <merle@freeit.com>"
ENV NGXDIR='/data/web/html/'
ADD index.html $NGXDIR
ADD entrypoint.sh /bin/
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
[root@docker1 docker]# docker build -t nginx:v6 ./
Sending build context to Docker daemon 6.656kB
Step 1/7 : FROM nginx:v5
# Executing 1 build trigger
Downloading [=======
# 这里查看构建过程就会发现从第一层构建就开始执行上面的ONBUILD后面的指令了。我们启动容器并查看下/usr/local目录下的文件。
[root@docker1 docker]# docker run -it --name web01 --rm nginx:v6 ls /usr/local
bin nginx-1.14.0.tar.gz
lib share
?
?
原文:https://www.cnblogs.com/ccbloom/p/11174186.html