DockerFile
一般来说,通用的Docker image没法满足公司的业务需求,需要根据公司的实际需求制作特定image,方法主要有两个:
1.基于容器创建
2. DockerFile

DockerFile Format
1. # 注释
2. INSTRUCTION 参数 (INSCTRUCTION最好用大写)
3. 顺序执行INSTRUCTION
4. 第一个非注释行的INSTRUCTION必须以FROM开始,去指定基础image
5. 必须以一个专用目录,Dockerfile文件必须存在,首字母必须大写,引用文件的路径必须是专用目录为开始,也可以用子目录来包含所有文件,一定不能是父目录。也可以用.dockerignore来指定文件路径,打包时所有在此文件中指定的文件都不包含,类似黑名单,起文件排除的作用。
6. 制作image的指令是docker build,docker build会隐式启动一个容器,同时在Dockerfile中能执行的命令必须是基础image中包含的。
7. 可以用环境变量Environment variables,Dockerfile中的变量和shell的变量非常类似
${variable:-word}:indicates that if variable is set then the result will be that value. If variable is not set then word will be the result.
${variable:+word} :indicates that if variable is set then word will be the result, otherwise the result is the empty string.
DockerFile INSTRUCTION
FROM
1:定义
指令是最重的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境。实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry或指定的Registry上拉取所需的镜像文件。
2:语法
• FROM
• FROM
•
•
LABEL
1.:定义
用于让Dockerfile制作者提供本人的详细信息
Dockerfile并不限制LABEL指令可在出现的位置,但推荐将其放置于FROM指令之后
2:语法
- LABEL
- LABEL 是键值类型
- 一个image可以有多个label
- 可以在一行中指定多个label
COPY
1:定义
用于从Docker主机复制文件至创建的新映像文件
2:语法
- COPY
- COPY ["
•
•
3:文件复制准则
-
- 如果
- 如果指定了多个
- 如果
4:实例
# vim Dockerfile
#Description: test image
FROM busybox
LABEL maintainer="Evan liangjindong0@qq.com" app="httpd"
COPY index.html /data/web/html/
# 当前目录下,创建index.html: echo hello > index.html
# docker build -t tinyhttpd:v0.1-1 ./
# docker run --name tinyweb1 --rm tinyhttpd:v0.1-1 cat /data/web/html/index.html
# cp -r /etc/yum.repos.d/ ./
# vim Dockerfile
#Description: test image
FROM busybox
LABEL maintainer="Evan liangjindong0@qq.com" app="httpd"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/ (会把yum.repos.d下的所有文件copy到/etc/yum.repos.d/目录下,必须以/结尾)
# docker build -t tinyhttpd:v0.1-2 ./
# docker run --name tinyweb1 --rm tinyhttpd:v0.1-2 ls /etc/yum.repos.d/
ADD
1:定义
ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径
2:语法
• ADD
• ADD ["
3:操作准则
- 同COPY指令
- 如果
- 如果
- 如果
4:实例
# vim Dockerfile
ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/
# docker build -t tinyhttpd:v0.1-3 ./
# docker run --name tinyweb1 --rm tinyhttpd:v0.1-3 ls /usr/local/src/ (只会上传,不会解压)
# 如果nginx-1.15.2.tar.gz是本地文件,会在目标上解压
WORKDIR
1:定义
用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
2: 语法
WORKDIR
• 在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径
• 另外,WORKDIR也可调用由ENV指定定义的变量
例如
• WORKDIR /var/log
• WORKDIR $STATEPATH
VOLUME
1: 定义
用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
2:语法
• VOLUME
• VOLUME ["
如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
3:实例
# vim Dockerfile
VOLUME /data/mysql/
此volume是docker自动管理的类型
# docker build -t tinyhttpd:v0.1-4 ./
# docker run --name tinyweb1 --rm tinyhttpd:v0.1-4 sleep 60
# docker inspect tinyweb1
EXPOSE
1:定义
用于为容器打开指定要监听的端口以实现与外部通信
2:语法
EXPOSE
•
• EXPOSE指令可一次指定多个端口,例如
EXPOSE 11211/udp 11211/tcp (只是可以暴露,需要在docker run -P才会暴露在Dockerfile中定义的EXPOSE端口)
3:实例
# vim Dockerfile
EXPOSE 80/tcp
# docker build -t tinyhttpd:v0.1-5 ./
# docker run --name tinyweb1 --rm tinyhttpd:v0.1-5 /bin/httpd -h /data/web/html
只可以访问Docker IP的网页
# docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-5 /bin/httpd -h /data/web/html
# docker port tinyweb1
可以访问Docker宿主机IP的网页
ENV
1:定义
用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用,调用格式为$variable_name或${variable_name}
2:语法
• ENV
• ENV
• 第一种格式中,
• 第二种格式可用一次设置多个变量,每个变量为一个"
• 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
3:实例
# vim Dockerfile
ENV DOC_ROOT=/data/web/html/
WEB_SERVER_PACKAGE="nginx-1.15.2"
COPY index.html ${DOC_ROOT:-/data/web/html/}
ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/
# image构建和启动是两个不同的过程,两个不同的阶段,Dockerfile中定义的EVN在启动时会注入到容器中
# docker build -t tinyhttpd:v0.1-6 ./
# docker run --name tinyweb1 --rm -e WEB_SERVER_PACKAGE="nginx-1.15.1" tinyhttpd:v0.1-6 printenv
RUN
1:定义
用于指定docker build过程中运行的程序,其可以是任何命令
2:语法
• RUN
• RUN ["
• 第一种格式中,
• 第二种语法格式中的参数是一个JSON格式的数组,其中
RUN ["/bin/bash", "-c", "
• 注意:JSON数组中,要使用双引号
3:实例
# vim Dockerfile
RUN yum makecache &&
yum install nginx -y &&
yum clean all
#
CMD
1:定义
类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
• RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动一个容器时
• CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
• 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
2:语法
• CMD
• CMD [“
• CMD ["
• 前两种语法格式的意义同RUN
• 第三种则用于为ENTRYPOINT指令提供默认参数
3:实例
- 第一种格式:以shell启动
vim Dockerfile
FROM busybox
LABEL maintainer="Evan liangjindong0@qq.com" app="httpd"
ENV WEB_DOC_ROOT="/data/web/html/"
RUN mkdir -p ${WEB_DOC_ROOT} &&
echo '
Busybox httpd server.
' > ${WEB_DOC_ROOT}/index.htmlCMD /bin/httpd -f -h ${WEB_DOC_ROOT}
# docker build -t tinyhttpd:v0.1-7 ./
# docker run --name tinyweb1 --rm -it tinyhttpd:v0.1-7 ()
# docker ps (启动为/bin/sh的子进程)
"/bin/sh -c '/bin/ht…"
# docker exec -it tinyweb1 /bin/sh (shell中exec COMMAND,exec取代shell为1的进程,shell退出)
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/httpd -f -h /data/web/html/ ()
6 root 0:00 /bin/sh
11 root 0:00 ps
- 第二种格式:不是以shell启动,可以指定用shell
# vim Dockerfile
CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
# docker build -t tinyhttpd:v0.1-8 ./
# docker run --name tinyweb1 --rm -it tinyhttpd:v0.1-8
httpd: can't change directory to ' ${WEB_DOC_ROOT}': No such file or directory (不是以shell启动,所以无法识别${WEB_DOC_ROOT}'变量)
指定用shell启动
# vim Dockerfile
CMD ["/bin/sh","-c","/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
# docker build -t tinyhttpd:v0.1-9 ./
- 第三种格式: 带ENTRYPOINT
# vim Dockerfile
CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
ENTRYPOINT /bin/sh
(CMD的命令会作为ENTRYPOINT的参数传递)
# docker run --name tinyweb1 --rm -it tinyhttpd:v1.4
# docker inspect tinyweb1
"Cmd": [
"/bin/httpd",
"-f",
"-h ${WEB_DOC_ROOT}"
],
"ArgsEscaped": true,
"Image": "tinyhttpd:v1.4",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/bin/sh",
"-c",
"/bin/sh"
],
解释:用/bin/sh -c运行/bin/sh
ENTRYPOINT ["/bin/sh","-c"]
"Cmd": [
"/bin/httpd",
"-f",
"-h ${WEB_DOC_ROOT}"
],
"ArgsEscaped": true,
"Image": "sha256:ba8350e53c013997d443f1f5ee68083a906b76a35e771fe89cf9426947ebc015",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/bin/sh",
"-c"
],
docker run --name tinyweb1 --rm -it tinyhttpd:v1.6 "ls /data" (能执行,CMD作为默认参数时传给ENTRYPOINT,但是docker run运行时传的参数会传给ENTRYPOINT,ls命令作为shell的子进程运行,此时docker run传的参数覆盖的是CMD参数)

注意:RUN基于基础image中的命令;RUN可以运行多次,同样属性的命令用一行描述
docker run中CMD只能有一个
运行的时间点不同,运行的行为不同
ENTRYPOINT
1:定义
• 类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
• 与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
• 另外,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
2:语法
• ENTRYPOINT
• ENTRYPOINT ["
• docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
• Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
3:实例
# vim DockerfileENTRYPOINT /bin/httpd -f -h ${WEB_DOC_ROOT}
# docker run --name tinyweb1 --rm -it tinyhttpd:v1.3
# docker run --name tinyweb1 --rm -it tinyhttpd:v1.3 ls /data/web/html (ls /data/web/html不会覆盖ENTRYPOINT定义的)
# docker run --name tinyweb1 --rm -it --entrypoint "ls /data/web/html" tinyhttpd:v1.3 (可以用--entrypoint来强制覆盖)
4:应用场景
多数情况下,ENTRYPOINT是用来指定一个shell,作为用来启动别的进程的父进程,docker run的命令行参数会作为它的子进程来运行,达到灵活传递参数并且被shell解析
空器接授变量需要通过环境变量
5:实例(Nginx接授变量生成配置文件,而且变量可以在启动容器时传递)
# vim entrypoint.sh
#!/bin/sh
#
cat > /etc/nginx/conf.d/www.conf << EOF
server {
server_name ${HOSTNAME};
listen ${IP:-0.0.0.0}😒{PORT:-80};
root ${NGX_DOC_ROOT:-/user/share/nginx/html};
}
EOF
exec "$@"
# chmod +x entrypoint.sh
# vim Dockerfile
FROM nginx:1.14-alpine
LABEL maintainer="Evan <liangjindong0@qq.com"
ENV NGX_DOC_ROOT="/data/web/html/"
ADD entrypoint.sh /bin/
CMD ["/usr/sbin/nginx","-g","daemon off;"] (前台运行Nginx)
ENTRYPOINT ["/bin/entrypoint.sh"] (首先用此脚本会以shell运行初始化一个配置文件,然后运行CMD,顶替entrypoint.sh,即Nginx进行运行后,shell脚本退出,Nginx成为容器中的唯一进程,而且是主进程)
# docker run --name tinyweb1 --rm -P -e "PORT=8080" -h Apache tinyhttpd:v1.8
# docker run --name tinyweb1 --rm -p 80:80 -h Apache tinyhttpd:v1.8
# docker exec -it tinyweb1 /bin/sh
# / # netstat -tnl (port参数被docker run启动时指定参数8080成功)
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
# / # ps
PID USER TIME COMMAND
1 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off; (Nginx能以PID为1的主进程运行,是因为entrypoint.sh脚本中的exec "$@")
8 nginx 0:00 nginx: worker process
9 root 0:00 /bin/sh
总结:ENTRYPOINT脚本来定义参数,在创建image时传入值,在docker run时接收参数来启动容器

浙公网安备 33010602011771号