docker学习笔记4-dockerfile
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker学习笔记4-dockerfile相关的知识,希望对你有一定的参考价值。
dockerfile
自制镜像:
基于容器,
解决1,如nginx,若环境有m个(开发|测试|生产),功能不同即配置文件不同(web|静态资源|反向代理),这就需要m*n个镜像,不妥当;
解决2,使用模板方式,启动容器时传递到容器中的变量;
用dockerfile;
dockerfile format,2种:
# Comment #1注释
INSTRUCTION arguments #2指令,the instruction is not case-sensitive,however,convention is for them to be UPPERCASE to distingush them from arguments more easily,docker runs instructions in a dockerfile in order; the first instruction must be FROM in order to specify the base image from which you are building
#echo $NAME:-tom #NAME变量若没设置,显示此处默认值
#NAME=jerry
#echo $NAME:-tom
#echo $NAME:+tom #用于判断变量是否设置了,如果设置显示tom,没设置显示空
dockerfile instruction
FROM #是最重要的一个且必须为dockerfile文件的第一行,第一个非注释行,用于为镜像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境;实践中,基准镜像可以是任何可用镜像文件,默认docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从docker hub registry上拉取所需的镜像文件,如果找不到镜像文件docker build会返回错误信息
语法:
FROM <repository>[:<tag>]或
FROM <repository>@<digest> #repository指定base image;tag为base image的标签,可选,省略时默认为latest;digest为自己指定的hash码,对应不上则不会用,更安全
MAINTAINER "<authors detail>" #deprecated,用于让docker制作者提供本人的详细信息,dockerfile并不限制此指令出现的位置,建议在FROM指令后;authors detail可以是任何文本信息,但约定使用作者名称及邮件地址
LABEL <key1>=<value1> <key2>=<value2>... #同MAINTAINER
COPY <src>... <dest>或
COPY ["<src>",..."<dest>"] #src要复制的源文件或目录,支持通配符;dest,目标路径,即正在创建的Image的文件系统路径,建议dest使用绝对路径,否则COPY指定规则以WORKDIR为起始路径;若在路径中有空白字符时使用第2种格式;
文件复制准则:
src必须是build上下文中的路径(相对路径),不能是其父目录中的文件;
如果src是目录,则其内部文件或子目录会被递归复制,但src目录自身不会被复制;
如果指定了多个src,或在src中使用了通配符,则dest必须是一个目录,且必须以/结尾;
如果dest事先不存在,它将会被自动创建,这包括其父目录路径;
ADD <src>...<dest>或
ADD ["<src>",..."<dest>"] #类似COPY,ADD支持使用tar文件和url路径;
准则:
如果src为url且dest不以/结尾,则src指定的文件将被下载并直接被创建了dest;如果dest以/结尾,则文件名url指定的文件将被直接下载并保存为dest/filename;
如果src是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于tar -xf,而通过url获取到的tar文件将不会自动展开;
如果src有多个,或间接或直接使用了通配符,则dest必须是一个以/结尾的目录路径,如果dest不以/结尾,则被视作一个普通文件,src的内容将直接写入到dest;
WORKDIR <dirpath> #用于为Dockfile中所有的RUN|CMD|ENTRYPOINT|COPY|ADD指定设定工作目录;在Dockfile文件中,WORKDIR指令可出现多次,其路径也可为相对路径,不过其是相对此前一个WORKDIR指令指定的路径;另外WORKDIR也可调用由ENV指定定义的变量
WORKDIR /var/log
WORKDIR $STATEPATH
VOLUME <mountpoint>或
VOLUME ["<mountpoint>"] #用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷;如果挂载点目录路径下此前的文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
EXPOSE <port>[/<protocol>][<port>][/<protocol>]... #protocol用于指定传输层协议,可为tcp或udp,默认为tcp;此项并不是真暴露,要暴露出去在启动容器时加-P
EXPOSE 11211/udp 11211/tcp #EXPOSE指令可一次指定多个端口
ENV <key> <value>或 #这种格式,key之后的所有内容均被视作value的组成部分,因此只能设置1个变量
ENV <key>=<value>... #用于镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令,如ENV|ADD|COPY等所调用,调用格式为$variable_name或$variable_name;这种格式可一次设置多个变量,如果value中包含空格,可用\\转义,也可通过对value加引号进行标识,\\也可用于续行;建议使用此种格式,以便在同一层中完成所有功能
docker run --name tinyweb1 --rm -P -e WEB_SERVER_PACKAGE="nginx-1.15.1" tinyhttpd:v0.1-7 printenv
docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-7 printenv #输出环境变量,
注:
2个阶段,docker build制作目标镜像(在基础镜像上操作),docker run启动镜像为容器;
RUN <COMMAND1>或
RUN ["<executable>","<param1>","<param2>"] #在docker build阶段执行的,常用于编译安装软件;RUN如果有多个会依次运行,而CMD只运行最后一个
第1种格式<command>通常是一个shell命令,且以/bin/sh -c来运行它,这意味着此进程在容器中的PID不为1,不能接收unix信号,因此当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号(15);
第2种格式中的参数是一个json格式的数组,其中executable为要运行的命令,后面的paramN为传递给命令的选项或参数,然而此种格式的命令不会以/bin/sh -c来发起,因此常见的shell操作(如变量替换及通配符替换不会进行),不过,如果要运行的命令依赖于shell特性的话,可将其替换为RUN ["/bin/bash","-c","<executable>","<param1>"]
CMD <command>或
CMD ["<executable>","<param1>","param2">]或
CMD ["<param1>","<param2>"] #类似RUN也可用于运行任何命令或应用程序,不过二者的运行时间点不同,RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动1个容器时;CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止,不过CMD中的命令可以被docker run的命令行选项覆盖;在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效;
前2种语法意义同RUN;
第3种用于为ENTRYPOINT指令提供默认参数,前提CMD和ENTRYPOINT都定义了;
注:
#command #占据当前shell终端,shell的子进程
#command & #依赖父进程(启动它的shell),若父进程退出此命令运行的程序也会退出
#nohup command & #直接推到init进程下
#exec command #exec会取代init,当前shell退出
ENTRYPOINT <command>或
ENTRYPOINT ["<executable","<param1>","<param2>"] #类似CMD,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序;与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,且这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
docker run传入的命令参数会覆盖CMD指令的内容,且附加到ENTRYPOINT命令最后作为其参数使用;
Dockerfile文件中也可存在多个ENTRYPOINT指令,但仅有最后一个会生效;
json数组中要使用双引号;
USER <UID>|<UserName> #指定运行镜像时的或运行Dockerfile中任何RUN|CMD|ENTRYPOINT指定的程序时的用户名或UID,默认容器的运行身份是root,注意UID可以是任意数字,但实践中必须为/etc/passwd中某用户的有效UID,否则docker run命令将运行失败
HEALTHCHECK NONE #disable any healthcheck inherited from the base image
HEALTHCHECK [OPTIONS] CMD command #check container health by running a command inside the container
options:
--interval=DURATION #default:30s
--timeout=DURATION #default:30s
--start-period=DURATION #default:0s
--reties=N #default:3
0 #success
1 #unhealthy
2 #reserved
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
SHELL ["executable","parameters"] #the default shell on Linux is ["/bin/sh","-c"],仅在用的不是/bin/sh才需要改
STOPSIGNAL signal #默认15,可改为9
ARG <name>[=<default>] #在docker build时传变量;区别于ENV,ENV定义的变量在build时只能使用Dockerfile中定义的,不能在命令行下用build传入
docker build --build-arg author="" -t myweb1 ./
ONBUILD <INSTRUCTION> #用于在Dockerfile中定义一个触发器
Dockerfile用于build镜像文件,此镜像文件也可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的镜像文件;在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会触发创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器;
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令;
使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,如ruby:2.0-onbuild;
在ONBUILD指令中使用ADD或COPY(局域网中的文件或url中的文件)时应格外小心,因为新构建过程的上下文中在缺少指定的源文件时会失败;
例:
mkdir img1
cd img1
vim DockerFile #定义此文件要惜字如金,因为每1条命令都会有新的层次,层次太多影响性能
#Description: test image
FROM busybox:latest
MAINTAINER "Magedu <magedu@mageduc.om"
# LABEL maintainer=""
ENV DOC_ROOT=/data/web/html/ \\
WEB_SERVER_PACKAGE="nginx-1.15.2"
COPY index.html $DOC_ROOT:-/data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
# ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/
WORKDIR /usr/local/
#ADD nginx-1.15.2.tar.gz /usr/local/src/
ADD $WEB_SERVER_PACKAGE.tar.gz ./src/
#ADD nginx-1.15.2.tar.gz ./src/
VOLUME /data/mysql/
EXPOSE 80/tcp
RUN cd /usr/local/src && \\
tar xf nginx-1.15.2.tar.gz
docker build -t tinyhttpd:v0.1-1 ./ #docker build -t tinyhttpd:v0.1-2 ./
docker image ls
docker run --name tinyweb1 --rm tinyhttpd:v0.1-1 cat /data/web/html/index.html #验证,执行完后会退出并删除容器;
ls /etc/yum.repos.d/;
ls /usr/local/src/;
mount;sleep 60;docker inspect tinyweb1查看Mounts ;
cp -r /etc/yum.repos.d/ ./ #当前目录在img1/
docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-6 /bin/httpd -f -h /data/web/html/ #不加-P不会暴露端口给宿主机
docker port tinyweb1
例:
mkdir img2
cd img2/
vim Dockerfile
FROM busybox
LABEL maintainer="Magedu <magedu@magedu.com>" app="httpd"
ENV WEB_DOC_ROOT="/data/web/html/"
RUN mkdir $WEB_DOC_ROOT && \\
echo busybox httpd server > $WEB_DIOC_ROOT/index.html
#CMD /bin/httpd -f -h $WEB_DOC_ROOT
#CMD ["/bin/httpd","-f","-h $WEB_DOC_ROOT"]
#CMD [“/bin/bash”,"-c","/bin/httpd","-f","-h $WEB_DOC_ROOT"]
#CMD [“/bin/bash”,"-c","/bin/httpd","-f","-h /data/web/html/"]
#ENTRYPOINT /bin/httpd -f -h $WEB_DOC_ROOT #docker run中的ls /data/web/html被当作参数放到/bin/httpd -f -h $WEB_DOC_ROOT的后面
CMD ["/bin/httpd","-f","-h $WEB_DOC_ROOT"]
ENTRYPOINT ["/bin/sh","-c"] #docker run中的"ls /data"会覆盖CMD中的
docker build -t tinyhttpd:v0.2-1 ./ #v0.2-2|v0.2-3
docker image inspect tinyhttpd:v0.2-1 #Cmd段
docker run --name tinyweb2 --it --rm -P tinyhttpd:v0.2-1 #加-it没用,默认运行的是httpd -f -h
docker exec -it tinyweb2 /bin/sh #httpd的PID为1,可接收unix信号,可用docker stop停掉
printenv
例:
docker image ls
cd img3
vim Dockerfile
FROM nginx:1.14-alpine
ARG author="magedu <magedu@magedu.com>"
LABEL maintainer=$author
ENV NGX_DOC_ROOT="/data/web/html"
ADD index.html $NGX_DOC_ROOT #vim index.html
ADD entrypoint.sh /bin/
EXPOSE 80/tcp
HEALTHCHECK --start-period=5s CMD wget -O - -q http://IP:-0.0.0.0:$PORT:-80
ONBUILD ADD http://test.com/index.html /usr/local/src/
CMD ["/usr/sbin/nginx","-g","daemon off;"] #-g表示global,docker run --name nginx1 -it --rm nginx:1.14-alpine /bin/sh,which nginx
ENTRYPOINT ["/bin/entrypoint.sh"]
vim entrypoint.sh #chmod +x 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
exec "$@" #$@表示脚本的所有参数,exec表示替换当前进程为init
docker build -t myweb:v0.3-1 ./
docker run --name myweb1 --rm -P myweb:v0.3-1
docker exec -it myweb1 /bin/sh
cat /etc/nginx/conf.d/www.conf
netstat -tnl
wget -O - -q 89443f2d6adf
docker run --name myweb1 --rm -P -e "PORT=8080" myweb:v0.3-6
docker build --build-arg author="pony pony@qq.com" -t myweb:v0.3-10 ./
docker image inspect myweb:v0.3-10 #查看Label
以上是关于docker学习笔记4-dockerfile的主要内容,如果未能解决你的问题,请参考以下文章