Docker-dockerfile
简介
制作容器两种方法
1、基于原有容器进行修改
2、dockerfile制作
dockerfile只是构建docker镜像的源码,只是简单的命令,
语法格式:包含两类语句 1、#注释信息 2、指令及其参数
从上到下逐行操作
第一个非注释行一定是FROM
要求:
- 1)工作目录
- 2)首字母大写
- 3)所有配置文件等需要打包的文件及目录只能放在这个目录内
- 4)可以有一个.dockeringore的文件写入制定不需要打包的文件路径,打包的时候就会把指定文件排除在外
变量
$如果没有该变量或者变量为空则引用字符串(常用){variable:-word} 如果没有该变量或者变量为空则引用word字符串 (常用)
${variable:+word} 如果该变量存在,则使用word字符串
Dockerfile指令
1、FROM
最重要的以一个且必须为Dockerfile文件开篇的第一个非主事行,用于为影响见闻构建过程指定基准镜像,后续的指令
运行与基础镜像所提供的运行环境
- 语法 :
FROM
FROM
2、LABEL
标签 说明 类型:键值对数据
- 语法:
LABEL
3、MAINTAINER
描述
现在已经被LABEL maintainer= 取代
- 语法:
MAINTAINER
4、COPY
拷贝,宿主机当前工作目录中的文件,复制到目标镜像的文件系统
- 语法:
COPY ...
COPY ["",...""] #如果路径中有空格,建议使用该方式
COPY准则
1、
2、如果
3、如果
测试:
#编写Dockfile
[root@node1 ~]# mkdir Dockerfile
[root@node1 ~]# cd Dockerfile
[root@node1 ~/Dockerfile]# echo "123456">index.html
[root@node1 ~/Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
COPY index.html /data/wab/html/
#保存 biuld镜像
[root@node1 ~/Dockerfile]# docker build -t tinyhttpd:v0.1-1 ./
[root@node1 ~/Dockerfile]# ll
total 8
-rw-r--r--. 1 root root 185 Dec 9 16:42 Dockerfile
-rw-r--r--. 1 root root 25 Dec 9 16:43 index.html
[root@node1 ~/Dockerfile]# docker build -t tinyhttpd:v0.1-1 ./
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 :
---> Using cache
---> 9a816e188f25
Step 3/3 : COPY index.html /data/web/html/
---> 31a2b7060b22
Successfully built 31a2b7060b22
Successfully tagged tinyhttpd:v0.1-1
[root@node1 ~/Dockerfile]# docker Dockerfiles
REPOSITORY TAG Dockerfile ID CREATED SIZE
tinyhttpd v0.1-1 e1e084ea0143 4 minutes ago 1.24MB
tinyhttpd v0.1-2 3ee55e975acd 16 minutes ago 1.24MB
busybox latest be5888e67be6 3 days ago 1.22MB
#验证
[root@node1 ~/Dockerfile]# docker run --name tinyweb1 tinyhttpd:v0.1-1 cat /data/web/html/index.html
123456
#测试拷贝目录
#注意:DOCKERFILE内 每执行一行命令就会形成一个镜像层,所以尽可能减少语句,如果可以合并尽量多个合并到一条
[root@node1 ~/Dockerfile]# cp -r /etc/yum.repos.d/ ./
[root@node1 ~/Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
[root@node1 ~/Dockerfile]# docker build -t tinyhttpd:v0.1-2 ./
[root@node1 ~/Dockerfile]# docker build -t tinyhttpd:v0.1-2 ./
Sending build context to Docker daemon 26.62kB
Step 1/3 : FROM busybox
---> be5888e67be6
Step 2/3 : COPY index.html /data/web/html/
---> b9577b34b366
Step 3/3 : COPY yum.repos.d /etc/yum.repos.d/
---> fc352fad6cd0
Successfully built fc352fad6cd0
Successfully tagged tinyhttpd:v0.1-2
#验证
[root@node1 ~/Dockerfile]# docker run --name tinyweb2 --rm tinyhttpd:v0.1-2 ls -l /etc/yum.repos.d
total 40
-rw-r--r-- 1 root root 2523 Apr 18 02:58 CentOS-Base.repo
-rw-r--r-- 1 root root 1309 Apr 18 02:58 CentOS-CR.repo
-rw-r--r-- 1 root root 649 Apr 18 02:58 CentOS-Debuginfo.repo
-rw-r--r-- 1 root root 630 Apr 18 02:58 CentOS-Media.repo
-rw-r--r-- 1 root root 1331 Apr 18 02:58 CentOS-Sources.repo
-rw-r--r-- 1 root root 5701 Apr 18 02:58 CentOS-Vault.repo
-rw-r--r-- 1 root root 314 Apr 18 02:58 CentOS-fasttrack.repo
-rw-r--r-- 1 root root 2880 Apr 18 02:58 docker-ce.repo
-rw-r--r-- 1 root root 664 Apr 18 02:58 epel.repo
5、ADD
ADD 与COPY类似 但是ADD支持TAR文件和URL路径
-
语法
ADD ...
ADD ["",...""]
ADD准则
1、当源文件是URL的时候ADD可以把RUL对应的文件下载下来打包发送
2、如果源文件是tar的压缩包,将会被展开为一个目录,行为类似tar xf 然而 通过URL获取的TAR文件不会自动展开
3、如果src有多个或者使用了通配符,则dest必须是一个以/结尾的目录路径;如果
测试:
[root@node1 Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
#执行测试
[root@node1 ~/Dockerfile]# docker build -t tinyhttpd:v0.1-3 ./
Sending build context to Docker daemon 26.62kB
Step 1/4 : FROM busybox
---> be5888e67be6
Step 2/4 : COPY index.html /data/web/html/
---> Using cache
---> e2227d3d3806
Step 3/4 : COPY yum.repos.d /etc/yum.repos.d/
---> Using cache
---> 9a338fc4bed6
Step 4/4 : ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
Downloading 1.014MB/1.014MB
---> d0fb6e6c82d9
Successfully built d0fb6e6c82d9
Successfully tagged tinyhttpd:v0.1-3
#验证
[root@node1 ~/Dockerfile]# docker run --name tinyweb2 --rm tinyhttpd:v0.1-3 ls -l /usr/local/src/
total 992
-rw------- 1 root root 1014040 Nov 6 2018 nginx-1.14.1.tar.gz
###测试ADD 复制tar文件直接解压
#准备tar包
[root@node1 Dockerfile]# wget http://nginx.org/download/nginx-1.14.1.tar.gz
#编辑
[root@node1 Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
ADD ./nginx-1.14.1.tar.gz /usr/local/src/
[root@node1 Dockerfile]# docker build -t tinyhttpd:v0.1-4 ./
Sending build context to Docker daemon 1.038MB
Step 1/5 : FROM busybox
---> 59788edf1f3e
Step 2/5 :
---> Using cache
---> 9a816e188f25
Step 3/5 : COPY index.html /data/web/html/
---> Using cache
---> 31a2b7060b22
Step 4/5 : COPY yum.repos.d /etc/yum.repos.d/
---> Using cache
---> 821b2c754d7b
Step 5/5 : ADD ./nginx-1.14.1.tar.gz /usr/local/src/
---> c76524b56f3c
Successfully built c76524b56f3c
Successfully tagged tinyhttpd:v0.1-4
#验证
[root@node1 ~/Dockerfile]# docker run --name tinyweb4 --rm tinyhttpd:v0.1-4 ls -l /usr/local/src/
total 0
drwxr-xr-x 8 1001 1001 158 Nov 6 2018 nginx-1.14.1
6、WORKDIR
用于为Dockerfile中所有的RUNCMDENTRYPOINTCOPYADD设定工作目录
-
语法
WORKDIR
在Dockerfile中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过相对的是前一个WORKDIR指令制定的路径
7、VOLUME
用于在 Dockerfile中创建一个挂载点目录,以挂载Docker host上的卷或者其他容器上的卷
-
语法
VOLUME
或者 VOLUME ["
"]
如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后把此前所有文件复制到新挂载的卷中
注意! dockerfile中的存储卷只能指定docker容器内的路径,不能指定宿主机的路径
测试:
[root@node1 Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
WORKDIR /usr/local/
#相对路径
ADD ./nginx-1.14.1.tar.gz ./src/
VOLUME /data/mysql/
#
[root@node1 ~/Dockerfile]# docker build -t tinyhttpd:v0.1-5 ./
Sending build context to Docker daemon 1.041MB
Step 1/7 : FROM busybox
---> be5888e67be6
Step 2/7 : COPY index.html /data/web/html/
---> Using cache
---> e2227d3d3806
Step 3/7 : COPY yum.repos.d /etc/yum.repos.d/
---> Using cache
---> 9a338fc4bed6
Step 4/7 : ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
Downloading 1.014MB/1.014MB
---> Using cache
---> d0fb6e6c82d9
Step 5/7 : WORKDIR /usr/local/
---> Running in 585cdd081817
Removing intermediate container 585cdd081817
---> ab8a64b98ed4
Step 6/7 : ADD ./nginx-1.14.1.tar.gz /usr/local/src/
---> f3f363f4a001
Step 7/7 : VOLUME /data/mysql
---> Running in d5f98b875a9e
Removing intermediate container d5f98b875a9e
---> f598fe5a7c4f
Successfully built f598fe5a7c4f
Successfully tagged tinyhttpd:v0.1-5
###验证
[root@node1 Dockerfile]# docker run --name tinyweb5 --rm tinyhttpd:v0.1-5 mount|grep mysql
/dev/sda3 on /data/mysql type xfs (rw,seclabel,relatime,attr2,inode64,noquota)
8、EXPOSE
等待暴露端口,用于为容器打开指定要监听的端口以实现与外部通信
-
语法
EXPOSE [/] [/] ... ]
protocol 用于指定传输层协议 tcp udp 二选一 默认在TCP
EXPOSE指令可以一次执行多个端口
EXPOSE 11211/udp 11211/tcp
注意: 写入Dockerfile内的EXPOSE的端口不会直接暴露,只是表示可以暴露或者需要暴露该端口,可以在docker run的时候使用-P 来真正暴露端口,此时只是表示可以暴露。
测试:
[root@node1 Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
WORKDIR /usr/local/
#相对路径
ADD ./nginx-1.14.1.tar.gz ./src/
VOLUME /data/mysql/
EXPOSE 80/tcp
#build
[root@node1 Dockerfile]# docker build -t tinyhttpd:v0.1-6 ./
Sending build context to Docker daemon 1.038MB
Step 1/8 : FROM busybox
---> 59788edf1f3e
Step 2/8 :
---> Using cache
---> 9a816e188f25
Step 3/8 : COPY index.html /data/web/html/
---> Using cache
---> 31a2b7060b22
Step 4/8 : COPY yum.repos.d /etc/yum.repos.d/
---> Using cache
---> 821b2c754d7b
Step 5/8 : WORKDIR /usr/local/
---> Using cache
---> 5a746b5d61cf
Step 6/8 : ADD ./nginx-1.14.1.tar.gz ./src/
---> Using cache
---> 33c4c3b5e58d
Step 7/8 : VOLUME /data/mysql/
---> Using cache
---> 024fe1d452bd
Step 8/8 : EXPOSE 80/tcp
---> Running in e2a80b5a4536
Removing intermediate container e2a80b5a4536
---> 6a9ed6279a6e
Successfully built 6a9ed6279a6e
Successfully tagged tinyhttpd:v0.1-6
#验证
[root@node1 Dockerfile]# docker run --name tinyweb1 --rm tinyhttpd:v0.1-5 /bin/httpd -f -h /data/web/html
#复制终端 查看容器ip
[root@node1 ~]# docker inspect tinyweb1
"IPAddress": "172.16.1.2",
#验证
[root@node1 ~]# curl 172.16.1.2
who let the dogs outllll
#此时并未暴露端口
[root@node1 ~]# docker port tinyweb1
[root@node1 ~]#
#停止刚才的容器 使用-P 暴露EXPOSE设置的端口
[root@node1 ~]# docker kill tinyweb1
tinyweb1
[root@node1 ~]# docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-6 /bin/httpd -f -h /data/web/html
[root@node1 Dockerfile]# docker port tinyweb1
80/tcp -> 0.0.0.0:32768
[root@node1 Dockerfile]# curl 172.16.1.2
who let the dogs outllll
9、ENV
环境变量用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其他指令 ENV ADD COPY等调用
-
语法
ENV
或者 ENV
= = ...
第一种格式中key后的所有内容被视为value的组成部分,因此只能设置一个变量,
第二章格式可用一次设置多个变量,每个变量为一个KV键值对,value内可以包含空格 可以用转义 也可以通过对value加引号进行标识,反斜线也可以用于续行.
定义多个变量时,建议使用第二种方式,以便在他那个一层完成所有功能,docker每多一条指令就多一个读写层。
dockerfile中使用ENV定义的变量是注入镜像的,在docker run后直接在容器内引用使用的变量
也可以在docker run 的时候使用 -e为环境变量赋值 类似传参
测试:
[root@node1 Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
ENV DOC_ROOT=/data/weeb/html
WEEB_SERVER_PAC="nginx-1.14.1.tar.gz"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
WORKDIR /usr/local/
#相对路径
ADD ./nginx-1.14.1.tar.gz ./src/
VOLUME /data/mysql/
EXPOSE 80/tcp
#
[root@node1 Dockerfile]# docker build -t tinyhttpd:v0.1-7 ./
Sending build context to Docker daemon 1.038MB
Step 1/9 : FROM busybox
---> 59788edf1f3e
Step 2/9 :
---> Using cache
---> 9a816e188f25
Step 3/9 : ENV DOC_ROOT=/data/weeb/html WEEB_SERVER_PAC="nginx-1.14.1.tar.gz"
---> Running in 80fe5e58eb63
Removing intermediate container 80fe5e58eb63
---> 31bbfd3e788f
Step 4/9 : COPY index.html /data/web/html/
---> c0a8a55325a8
Step 5/9 : COPY yum.repos.d /etc/yum.repos.d/
---> 5f3ca71adb80
Step 6/9 : WORKDIR /usr/local/
---> Running in a2b2c5fb81e1
Removing intermediate container a2b2c5fb81e1
---> 18c8e0ca56ae
Step 7/9 : ADD ./nginx-1.14.1.tar.gz ./src/
---> 67dec88fe23c
Step 8/9 : VOLUME /data/mysql/
---> Running in ff16f01825f1
Removing intermediate container ff16f01825f1
---> e60571d77561
Step 9/9 : EXPOSE 80/tcp
---> Running in 77ccadaef6c1
Removing intermediate container 77ccadaef6c1
---> 1193c3a2de10
Successfully built 1193c3a2de10
Successfully tagged tinyhttpd:v0.1-7
#验证
[root@node1 bs]# docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-7 ls /usr/local/src -l
total 0
drwxr-xr-x 8 1001 1001 158 Nov 6 13:52 nginx-1.14.1
#测试使用-e参数指定环境变量
[root@node1 bs]# docker run --name tinyweb1 --rm -P -e WEB_SERVER_PAC="nginx-1.11" tinyhttpd:v0.1-7 printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=01d586f824c8
WEB_SERVER_PAC=nginx-1.11
DOC_ROOT=/data/weeb/html
WEEB_SERVER_PAC=nginx-1.14.1.tar.gz
HOME=/root
[root@node1 bs]# docker run --name tinyweb1 --rm -P -e WEB_SERVER_PAC="nginx-1.11" tinyhttpd:v0.1-7 ls /usr/local/src -l
total 0
drwxr-xr-x 8 1001 1001 158 Nov 6 13:52 nginx-1.14.1
验证发现 虽然docker run的时候赋予了新变量名,但是还是按照之前build的时候的配置执行,因为在docker build制作镜像的时候已经完成了之前的操作,docker run -e 只是在使用镜像做容器的时候进行传参,所以只影响开启容器后的操作。
10、RUN
运行命令 RUN的命令是在docker build制作镜像的时候运行
-
语法
RUN
RUN ["","<参数1>","<参数2>"]
建议多个RUN写一行 或者 && 换行 执行
第一种格式中,i一般是shell命令,且以"/bin.sh -c"来运行它,这就意味着改进程再容器的PID不是1不,不能接收Unix信号,因此当使用 docker stop 命令停止容器的时候,改进程接受不到SIGTERM信号(docker stop kill等)
第二种格式中的参数是一个JSON格式数组,此格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作比如变量替换 通配符替换等将不会执行,不过如果要运行的命令依赖此shell特性的话,可以将其替换为下面的格式
RUN ["/bin/bash","-c","","<参数>"]
JSON数组中一定要使用双引号。
测试:
[root@node1 Dockerfile]# vim Dockerfile
#test dockerfile
FROM busybox
ENV DOC_ROOT=/data/weeb/html
WEB_SERVER_PAC="nginx-1.14.1.tar.gz"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
WORKDIR /usr/local/
#相对路径
#ADD ./nginx-1.14.1.tar.gz ./src/
VOLUME /data/mysql/
EXPOSE 80/tcp
RUN cd /usr/local/src &&
tar xf ${WEB_SERVER_PAC} &&
ln -s nginx-1.14.1 nginx
#
[root@node1 Dockerfile]# docker build -t tinyhttpd:v0.1-8 ./
Sending build context to Docker daemon 1.039MB
Step 1/10 : FROM busybox
---> 59788edf1f3e
Step 2/10 :
---> Using cache
---> 9a816e188f25
Step 3/10 : ENV DOC_ROOT=/data/weeb/html WEB_SERVER_PAC="nginx-1.14.1.tar.gz"
---> Using cache
---> cbbf442fbe07
Step 4/10 : COPY index.html /data/web/html/
---> Using cache
---> 1ddff90269d0
Step 5/10 : COPY yum.repos.d /etc/yum.repos.d/
---> Using cache
---> adf8d7dc58c8
Step 6/10 : ADD http://nginx.org/download/nginx-1.14.1.tar.gz /usr/local/src/
Downloading 1.014MB/1.014MB
---> b43a41108c10
Step 7/10 : WORKDIR /usr/local/
---> Running in bb083a330502
Removing intermediate container bb083a330502
---> a1dc426a3b35
Step 8/10 : VOLUME /data/mysql/
---> Running in aeb793155a81
Removing intermediate container aeb793155a81
---> 0489fafcd5dc
Step 9/10 : EXPOSE 80/tcp
---> Running in 696a6163e99a
Removing intermediate container 696a6163e99a
---> 8dbc74131301
Step 10/10 : RUN cd /usr/local/src && tar xf ${WEB_SERVER_PAC} && ln -s nginx-1.14.1 nginx
---> Running in 13c5b72b6959
Removing intermediate container 13c5b72b6959
---> 96c6227ca444
Successfully built 96c6227ca444
Successfully tagged tinyhttpd:v0.1-8
#验证
[root@node1 bs]# docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-8 ls /usr/local/src -l
total 992
lrwxrwxrwx 1 root root 12 Dec 9 09:17 nginx -> nginx-1.14.1
drwxr-xr-x 8 1001 1001 158 Dec 9 09:17 nginx-1.14.1
-rw------- 1 root root 1014040 Nov 6 15:26 nginx-1.14.1.tar.gz
11、CMD
定义一个镜像文件启动为容器的时候默认的命令,类似与RUN,CMD也可以用于运行任何命令或应用程序
CMD执行运行于基于Dockerfile构建出的镜像文件启动为容器的时候 docker run,
CMD命令的首要目的在于为启动的容器制定默认要运行的程序且其运行结束后 容器也终止,不过CMD制定的命令其可以被docker run的命令行覆盖,
Dockerfile中可以存在多个CMD 但是只有最后一个生效。
-
语法
CMD
CMD ["","<参数1>","<参数2>"]
CMD["<参数1>","<参数2>"]
前两种和RUN一样 第三者用于为ENTRYPOINT指令提供默认参数
JSON数组中一定要使用双引号
测试:
[root@node1 Dockerfile]# cd ..
[root@node1 ~]# mkdir Dockerfile2
[root@node1 ~]# cd Dockerfile2
[root@node1 Dockerfile2]# vim Dockerfile
FROM busybox
ENV WEB_DOC_ROOT="/data/web/html"
RUN mkdir -p $WEB_DOC_ROOT &&
echo 'command run test' >${WEB_DOC_ROOT}/index.html
CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
~
#
[root@node1 Dockerfile2]# docker build -t tinyhttpd:v0.2-1 ./
Sending build context to Docker daemon 2.048kB
Step 1/5 : FROM busybox
---> 59788edf1f3e
Step 2/5 :
---> Using cache
---> 9a816e188f25
Step 3/5 : ENV WEB_DOC_ROOT="/data/web/html"
---> Running in dc359e634eb8
Removing intermediate container dc359e634eb8
---> 80c2fd145b0b
Step 4/5 : RUN mkdir -p $WEB_DOC_ROOT && echo 'command run test' >${WEB_DOC_ROOT}/index.html
---> Running in ca9141b04389
Removing intermediate container ca9141b04389
---> b1fdaf6afdbb
Step 5/5 : CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
---> Running in 331db2bf0160
Removing intermediate container 331db2bf0160
---> 2ac047c51cf9
Successfully built 2ac047c51cf9
Successfully tagged tinyhttpd:v0.2-1
#验证、
[root@node1 Dockerfile]# docker Dockerfile inspect tinyhttpd:v0.2-1
"Cmd": [
"/bin/sh",
"-c",
"/bin/httpd -f -h ${WEB_DOC_ROOT}"
],
#默认执行程序还是 /bin/sh
[root@node1 Dockerfile]# docker run --name tinyweb1 --rm -P tinyhttpd:v0.2-1
#此时是否使用-it都是一样 因为CMD指定了默认命令 可以使用docker Dockerfile inspect 查看CMD
#可以使用docker exec -it *** /bin/sh进入
[root@node1 ~]# docker exec -it tinyweb1 /bin/sh
/ # netstat -lnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 :::80
#此时httpd对应的进程是1 确认默认的启动命令为httpd
#测试CMD
[root@node1 Dockerfile2]# vim Dockerfile
FROM busybox
ENV WEB_DOC_ROOT="/data/web/html"
RUN mkdir -p $WEB_DOC_ROOT &&
echo 'command run test' >${WEB_DOC_ROOT}/index.html
#CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
~
#
[root@node1 Dockerfile2]# docker build -t tinyhttpd:v0.2-2 ./
Sending build context to Docker daemon 2.048kB
Step 1/5 : FROM busybox
---> 59788edf1f3e
Step 2/5 :
---> Using cache
---> 9a816e188f25
Step 3/5 : ENV WEB_DOC_ROOT="/data/web/html"
---> Using cache
---> 80c2fd145b0b
Step 4/5 : RUN mkdir -p $WEB_DOC_ROOT && echo 'command run test' >${WEB_DOC_ROOT}/index.html
---> Using cache
---> b1fdaf6afdbb
Step 5/5 : CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
---> Running in 70ca535911c6
Removing intermediate container 70ca535911c6
---> 9aca3e7bb653
Successfully built 9aca3e7bb653
Successfully tagged tinyhttpd:v0.2-2
#验证
[root@node1 ~]# docker Dockerfile inspect tinyhttpd:v0.2-2
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD ["/bin/httpd" "-f" "-h ${WEB_DOC_ROOT}"]"
],
[root@node1 Dockerfile]# docker run --name tinyweb1 --rm -P tinyhttpd:v0.2-2
httpd: can't change directory to ' ${WEB_DOC_ROOT}': No such file or directory
报错
由于此时默认进程不是shell 而${WEB_DOC_ROOT}是shell的环境变量,既然shell没有运行 则无法使用。
修改为绝对路径即可
12、ENTRYPOINT
类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行执行的参数覆盖,而且这些命令行参数会被当作参数传递给ENTRYPOINT指定的指定程序(不过 docker run --entrypoint参数可以覆盖ENTRYPOINT指定的指定程序)
-
语法
CMD["<参数1>","<参数2>"]
ENTRYPOINT
CMD所给的内容会被当作ENTRYPOINT的参数传递给ENTRYPOINT
可以理解为 优先级排序:
1、docker run --enrtrypoint
2、ENTRYPOINT
3、docker run
4、CMD
问:为什么需要有CMD 和ENTRYPOINT
1、多数情况ENTRYPOINT用来指定作为父进程的程序 命令行中的参数会当作参数来传参
2、容器接受配置要靠环境变量,
测试:
[root@node1 Dockerfile2]# vim Dockerfile
FROM busybox
ENV WEB_DOC_ROOT="/data/web/html"
RUN mkdir -p $WEB_DOC_ROOT &&
echo 'command run test' >${WEB_DOC_ROOT}/index.html
#CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
#CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
ENTRYPOINT /bin/httpd -f -h ${WEB_DOC_ROOT}
#
[root@node1 Dockerfile2]# docker build -t tinyhttpd:v0.2-3 ./
Sending build context to Docker daemon 2.048kB
Step 1/5 : FROM busybox
---> 59788edf1f3e
Step 2/5 :
---> Using cache
---> 9a816e188f25
Step 3/5 : ENV WEB_DOC_ROOT="/data/web/html"
---> Using cache
---> 80c2fd145b0b
Step 4/5 : RUN mkdir -p $WEB_DOC_ROOT && echo 'command run test' >${WEB_DOC_ROOT}/index.html
---> Using cache
---> b1fdaf6afdbb
Step 5/5 : ENTRYPOINT /bin/httpd -f -h ${WEB_DOC_ROOT}
---> Running in 7e04a3956e12
Removing intermediate container 7e04a3956e12
---> 863429a29ee3
Successfully built 863429a29ee3
Successfully tagged tinyhttpd:v0.2-3
#验证
[root@node1 Dockerfile]# docker run --name tinyweb2 --rm -P tinyhttpd:v0.2-3
[root@node1 ~]# docker inspect tinyweb2
"IPAddress": "172.16.1.2",
[root@node1 ~]# curl 172.16.1.2
command run test
#如果 docker run --name tinyweb2 -it --rm -P tinyhttpd:v0.2-3 ls /data ,执行该命令的时候由于使用的是ENTRYPOINT 所以 ls /data会被当作是 httpd -f -h /data/web/html 后的参数 即:httpd -f -h /data/web/html ls /data,除非使用 --entrypoing ls /data来执行,此时执行的结果是 ls /data httpd -f -h /data/web/html
#测试测试ENTRYPOINT
[root@node1 Dockerfile2]# cd ..
[root@node1 ~]# mkdir Dockerfile3
[root@node1 ~]# cd Dockerfile3/
[root@node1 Dockerfile3]# vim Dockerfile
FROM nginx:1.14.1-alpine
LABEL maintainer "white <2466236198@qq.com>"
ENV NGX_DOC_ROOT="/data/web/html"
ADD index.html ${NGX_DOC_ROOT}/
ADD entrypoint.sh /bin/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
#其中
[root@node1 Dockerfile3]# 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:-/usr/share/nginx/html};
}
EOF
#把CMD后面的所有命令当作参数的传递到ENTRYPOINT,且替换当前进程
exec "$@"
[root@node1 Dockerfile3]# chmod +x entrypoint.sh
[root@node1 Dockerfile3]# docker build -t myweb:v0.3-1 ./
13、USER
用于指定运行 Dockerfile时或运行Dockdile中任何RUN CMD ENTRYPOINT指令指定的程序时候的用户名或UID
默认情况下,container的运行身份为root
-
语法
USER
需要注意的是 可以是任意数字,但是实践中其必须为/etc/passwd中某用户的有效UID 否则 docker run会失败
14、HEALTHCKECK
通过容器运行与否无法判断真正的服务是否正常,所以引入健康检查,定义一个CMD command 用来检查主进程工作状态健康如否,
-
语法
HEALTHCHECK [OPTIONS] CMD command
--interval= 默认30s 间隔时间 s m h
--timeout= 默认30s 服务器反应超时时间 s m h
--start-period= 默认0s,初始化等待时间,刚开启容器等待容器初始化得时间 s m h
--reties= 默认3次 ,重试次数 ,超过该次数认证为非健康 times
CMD命令检查健康状态的返回值
0:success 成功 容器健康可以使用
1:unhealthy 失败 容器运行不正常
2:reserved 无意义
举例
HEALTHYCHECK --interval=5m --timeout=3s
CMD curl -f http:/loclahost || exit 1
如果不需要健康检查 可以使用HEALTHCHECK NONE来关闭所有健康检查
测试:
[root@node1 Dockerfile3]# vim Dockerfile
ENV NGX_DOC_ROOT="/data/web/html"
ADD index.html ${NGX_DOC_ROOT}/
ADD entrypoint.sh /bin/
EXPOSE 80/tcp
HEALTHCHECK --interval=40s --timeout=30s
--start-period=5s --retries=3
CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
#
[root@node1 Dockerfile3]# echo "healthy check test" >index.html
[root@node1 Dockerfile3]# docker build -t myweb:v0.3-3 ./
Sending build context to Docker daemon 4.096kB
Step 1/9 : FROM nginx:1.14.1-alpine
---> 77bae8d00654
Step 2/9 : LABEL maintainer "white <2466236198@qq.com>"
---> Using cache
---> 0bb45a975d25
Step 3/9 : ENV NGX_DOC_ROOT="/data/web/html"
---> Using cache
---> b1a6e20bd862
Step 4/9 : ADD index.html ${NGX_DOC_ROOT}/
---> 91a1327ac8c2
Step 5/9 : ADD entrypoint.sh /bin/
---> 8b80361ca7d4
Step 6/9 : EXPOSE 80/tcp
---> Running in e0d28e40e001
Removing intermediate container e0d28e40e001
---> 5e02dade60ae
Step 7/9 : HEALTHCHECK --interval=40s --timeout=30s --start-period=5s --retries=3 CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/
---> Running in 6c440b190808
Removing intermediate container 6c440b190808
---> 925872e74af1
Step 8/9 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in 2da2fa1c14cf
Removing intermediate container 2da2fa1c14cf
---> ce5c8c7cc8dd
Step 9/9 : ENTRYPOINT ["/bin/entrypoint.sh"]
---> Running in c1fbe4fe1e9e
Removing intermediate container c1fbe4fe1e9e
---> b271d2811c6b
Successfully built b271d2811c6b
Successfully tagged myweb:v0.3-3
#验证
[root@node1 Dockerfile]# docker run --name myweb1 --rm -P -e "PORT=8080" myweb:v0.3-3
127.0.0.1 - - [09/Dec/2018:11:22:04 +0000] "GET / HTTP/1.1" 200 19 "-" "Wget" "-"
127.0.0.1 - - [09/Dec/2018:11:22:44 +0000] "GET / HTTP/1.1" 200 19 "-" "Wget" "-"
127.0.0.1 - - [09/Dec/2018:11:23:25 +0000] "GET / HTTP/1.1" 200 19 "-" "Wget" "-"
##健康检查已经开始
#测试健康检查失败情况 ,HEALTHCHECK部分修改如下
[root@node1 Dockerfile3]# docker build -t myweb:v0.3-4 ./
Sending build context to Docker daemon 4.096kB
Step 1/9 : FROM nginx:1.14.1-alpine
---> 77bae8d00654
Step 2/9 : LABEL maintainer "white <2466236198@qq.com>"
---> Using cache
---> 0bb45a975d25
Step 3/9 : ENV NGX_DOC_ROOT="/data/web/html"
---> Using cache
---> b1a6e20bd862
Step 4/9 : ADD index.html ${NGX_DOC_ROOT}/
---> Using cache
---> 91a1327ac8c2
Step 5/9 : ADD entrypoint.sh /bin/
---> Using cache
---> 8b80361ca7d4
Step 6/9 : EXPOSE 80/tcp
---> Using cache
---> 5e02dade60ae
Step 7/9 : HEALTHCHECK --interval=40s --timeout=30s --start-period=5s --retries=3 CMD wget -O - -q http://${IP:-0.0.0.0}:12345/
---> Running in e0d0b0128ea2
Removing intermediate container e0d0b0128ea2
---> 349fe139044c
Step 8/9 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in fb34d3f2b359
Removing intermediate container fb34d3f2b359
---> 700608bbf6f6
Step 9/9 : ENTRYPOINT ["/bin/entrypoint.sh"]
---> Running in 009744406bf9
Removing intermediate container 009744406bf9
---> ee3b3c1ad8b2
Successfully built ee3b3c1ad8b2
Successfully tagged myweb:v0.3-4
#等待结果,等待时间是次数*timeout
[root@node1 Dockerfile]# docker run --name myweb1 --rm -P -e "PORT=8080" myweb:v0.3-4
15、SHELL
定义运行程序默认要适用的shell程序, LINUX 默认是["/bin/sh","-c"] windows默认是["cmd","/S","/C"]
SHELL在Dockerfile内格式必须是JSON格式
SHELL可以在一个Dockerfile内出现多次
16、STOPSIGNAL
进程号为1的进程可以直接接受docker stop命令从而停止主机名,来停止容器
默认情况 docker stop 传递的是 -15 docker kill 传递的是-9
17、ARG
参数,和ENV类似 ,区别:ARG定义的变量可以在docker build过程中使用 --build-arg =标签来 ENV不能在build的时候定义变量 ,只能在docker run的过程传递变量
控制定义的变量只在docker build过程生效
测试:
[root@node1 ~/Dockerfile3]# vim Dockerfile
FROM nginx:1.14.1-alpine
ARG auth="white <2466236198@qq.com>"
LABEL maintainer "$auth"
ENV NGX_DOC_ROOT="/data/web/html"
ADD index.html ${NGX_DOC_ROOT}/
ADD entrypoint.sh /bin/
EXPOSE 80/tcp
HEALTHCHECK --interval=40s --timeout=30s
--start-period=5s --retries=3
CMD wget -O - -q http://${IP:-0.0.0.0}:12345/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
#
[root@node1 ~/Dockerfile3]# docker build -t myweb:v0.3-5 ./
Sending build context to Docker daemon 4.096kB
Step 1/10 : FROM nginx:1.14.1-alpine
---> 77bae8d00654
Step 2/10 : ARG auth="white <2466236198@qq.com>"
---> Running in 2ed17d634507
Removing intermediate container 2ed17d634507
---> 316c718ecaa0
Step 3/10 : LABEL maintainer "$auth"
---> Running in 14490be791a4
Removing intermediate container 14490be791a4
---> 76aa29538a16
Step 4/10 : ENV NGX_DOC_ROOT="/data/web/html"
---> Running in 087658d3afdf
Removing intermediate container 087658d3afdf
---> b72aa46ad75e
Step 5/10 : ADD index.html ${NGX_DOC_ROOT}/
---> 074c94b85f50
Step 6/10 : ADD entrypoint.sh /bin/
---> 53a8e7ab029a
Step 7/10 : EXPOSE 80/tcp
---> Running in 2847b2d8849e
Removing intermediate container 2847b2d8849e
---> d7cc415c0da3
Step 8/10 : HEALTHCHECK --interval=40s --timeout=30s --start-period=5s --retries=3 CMD wget -O - -q http://${IP:-0.0.0.0}:12345/
---> Running in 7ee17b2899a4
Removing intermediate container 7ee17b2899a4
---> 9b5fee4cd750
Step 9/10 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in 681c4dce05b9
Removing intermediate container 681c4dce05b9
---> 0f8884fadf24
Step 10/10 : ENTRYPOINT ["/bin/entrypoint.sh"]
---> Running in 5862e4322b01
Removing intermediate container 5862e4322b01
---> 886e69981b3f
Successfully built 886e69981b3f
Successfully tagged myweb:v0.3-5
#验证
[root@node1 Dockerfile]# docker Dockerfile inspect myweb:v0.3-5
"Labels": {
"maintainer": "white <2466236198@qq.com>"
},
#验证--build-arg
[root@node1 ~/Dockerfile3]# docker build --build-arg auth="white <white@test.com>" -t myweb:v0.3-6 ./
Sending build context to Docker daemon 4.096kB
Step 1/10 : FROM nginx:1.14.1-alpine
---> 77bae8d00654
Step 2/10 : ARG auth="white <2466236198@qq.com>"
---> Using cache
---> 316c718ecaa0
Step 3/10 : LABEL maintainer "$auth"
---> Running in 746c249968ec
Removing intermediate container 746c249968ec
---> d903ad31734c
Step 4/10 : ENV NGX_DOC_ROOT="/data/web/html"
---> Running in fab0b51ae852
Removing intermediate container fab0b51ae852
---> b84e2b3c8b5f
Step 5/10 : ADD index.html ${NGX_DOC_ROOT}/
---> bf6990335b96
Step 6/10 : ADD entrypoint.sh /bin/
---> 47d564c825a9
Step 7/10 : EXPOSE 80/tcp
---> Running in d64e47b8b5c5
Removing intermediate container d64e47b8b5c5
---> d73abae36814
Step 8/10 : HEALTHCHECK --interval=40s --timeout=30s --start-period=5s --retries=3 CMD wget -O - -q http://${IP:-0.0.0.0}:12345/
---> Running in 95485a51d070
Removing intermediate container 95485a51d070
---> 1e54a1c73ecf
Step 9/10 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in 9ae84426fe2b
Removing intermediate container 9ae84426fe2b
---> 48e5a8f22618
Step 10/10 : ENTRYPOINT ["/bin/entrypoint.sh"]
---> Running in e373d1a1da2b
Removing intermediate container e373d1a1da2b
---> 58852bdd8525
Successfully built 58852bdd8525
Successfully tagged myweb:v0.3-6
#验证
[root@node1 Dockerfile]# docker Dockerfile inspect myweb:v0.3-6
"Labels": {
"maintainer": "white <white@test.com>"
},
18、ONBUILD
用于在Dockerfile中定义一个触发器
Dockerfile用于build映像文件,此映像文件也可以作为base Dockerfile被另外一个Dockerfile用作FROM指令的参数,并用来构建新的映像文件,在后面的这个Dockerfile文件中的FROM指令在build过程中被执行的时候,将会触发创建其base Dockerfile的Dockerfile文件中的ONBUILD指令定义的触发器。
-
语法
ONBUILD
1、尽管任何指令都可以称为触发器指令,但是ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令。
2、使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊标签。比如 ruby:v2.0-onbuild
3、在ONBUILD指令正使用ADD和COPY指令应该格外小心,因为新构建过程的上下文缺失指定的源文件时会失败
测试:
[root@node1 ~/Dockerfile3]# vim Dockerfile
FROM nginx:1.14.1-alpine
ARG auth="white <2466236198@qq.com>"
LABEL maintainer "$auth"
ENV NGX_DOC_ROOT="/data/web/html"
ADD index.html ${NGX_DOC_ROOT}/
ADD entrypoint.sh /bin/
ONBUILD ADD http://mirrors.aliyun.com/repo/Centos-7.repo /usr/local
EXPOSE 80/tcp
#在ONBUILD指令正使用ADD和COPY指令应该格外小心,因为新构建过程的上下文缺失指定的源文件时会失败
HEALTHCHECK --interval=40s --timeout=30s
--start-period=5s --retries=3
CMD wget -O - -q http://${IP:-0.0.0.0}:12345/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
#
[root@node1 ~/Dockerfile3]# docker build -t myweb:v0.3-6 ./
Sending build context to Docker daemon 4.608kB
Step 1/11 : FROM nginx:1.14.1-alpine
---> 77bae8d00654
Step 2/11 : ARG auth="white <2466236198@qq.com>"
---> Using cache
---> 316c718ecaa0
Step 3/11 : LABEL maintainer "$auth"
---> Using cache
---> 76aa29538a16
Step 4/11 : ENV NGX_DOC_ROOT="/data/web/html"
---> Using cache
---> b72aa46ad75e
Step 5/11 : ADD index.html ${NGX_DOC_ROOT}/
---> Using cache
---> 074c94b85f50
Step 6/11 : ADD entrypoint.sh /bin/
---> Using cache
---> 53a8e7ab029a
Step 7/11 : ONBUILD ADD http://mirrors.aliyun.com/repo/Centos-7.repo /usr/local
---> Running in 848291e7328a
Removing intermediate container 848291e7328a
---> 18abb66067e7
Step 8/11 : EXPOSE 80/tcp
---> Running in e5e995d06269
Removing intermediate container e5e995d06269
---> fb1db1855b71
Step 9/11 : HEALTHCHECK --interval=40s --timeout=30s --start-period=5s --retries=3 CMD wget -O - -q http://${IP:-0.0.0.0}:12345/
---> Running in fd65814435e9
Removing intermediate container fd65814435e9
---> 596f21f56aeb
Step 10/11 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in bce544ab1f5a
Removing intermediate container bce544ab1f5a
---> 9502ad88c6c5
Step 11/11 : ENTRYPOINT ["/bin/entrypoint.sh"]
---> Running in 0eda01915320
Removing intermediate container 0eda01915320
---> 247a222547bf
Successfully built 247a222547bf
Successfully tagged myweb:v0.3-6
#查看可知ONBUILD后的命令在build过程未执行
#利用刚制作的myweb:v0.3-13镜像为基础制作镜像,只是验证ONBUILD
[root@node1 ~/Dockerfile3]# cd ..
[root@node1 ~]# mkdir Dockerfile4
[root@node1 ~]# cd Dockerfile4
[root@node1 Dockerfile4]# vim Dockerfile
[root@node1 Dockerfile4]# vim Dockerfile
FROM myweb:v0.3-6
RUN mkdir /tmp/tes
#
[root@node1 Dockerfile4]# docker build -t test:v0.1-1 ./
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM myweb:v0.3-6
# Executing 1 build trigger
Downloading 2.523kB/2.523kB
---> ffc46fea5ab2
Step 2/2 : RUN mkdir /tmp/tes
---> Running in 9e2e9a2e1c12
Removing intermediate container 9e2e9a2e1c12
---> d48446f29c68
Successfully built d48446f29c68
Successfully tagged test:v0.1-1
#验证成功