[TOC] # 简介 Dockerfile 使用准则 1. 大: 首字母必须大写D 2. 空: 尽量将Dockerfile放在空目录中。 3. 单: 每个容器尽量只有一个功能。 4. 少: 执行的命令越少越好。 Dockerfile文件内容: 首行注释信息 指令(大写) 参数 Dockerfile使用命令: ~~~ #构建镜像命令格式: docker build -t [镜像名]:[版本号][Dockerfile所在目录] #构建样例: docker build -t nginx:v0.2 /opt/dockerfile/nginx/ #参数详解: -t 指定构建后的镜像信息, /opt/dockerfile/nginx/ 则代表Dockerfile存放位置,如果是当前目录,则用 .(点)表示 ~~~ # 基础指令 ## FROM ~~~ #格式: FROM <image> FROM <image>:<tag> #解释: #FROM 是 Dockerfile 里的第一条而且只能是除了首行注释之外的第一条指令 #可以有多个FROM语句,来创建多个image #FROM 后面是有效的镜像名称,如果该镜像没有在你的本地仓库,那么就会从远程仓库Pull取,如果远程也 没有,就报错失败 #下面所有的 系统可执行指令 在 FROM 的镜像中执行。 ~~~ ## MAINTAINER ~~~ MAINTAINER #格式: MAINTAINER <name> #解释: #指定该dockerfile文件的维护者信息。类似我们在docker commit 时候使用-a参数指定的信息 ~~~ ## RUN ~~~ RUN #格式: RUN <command> (shell模式) RUN["executable", "param1", "param2"] (exec 模式) #解释: #表示当前镜像构建时候运行的命令,如果有确认输入的话,一定要在命令中添加 -y #如果命令较长,那么可以在命令结尾使用 \ 来换行 #生产中,推荐使用上面数组的格式 #注释: #shell模式:类似于 /bin/bash -c command #举例: RUN echo hello #exec模式:类似于 RUN["/bin/bash", "-c", "command"] #举例: RUN["echo", "hello"] ~~~ ## EXPOSE ~~~ EXPOSE #格式: EXPOSE <port> [<port>...] #解释: 设置Docker容器对外暴露的端口号,Docker为了安全,不会自动对外打开端口,如果需要外部提供访问, 还需要启动容器时增加-p或者-P参数对容器的端口进行分配 ~~~ # 运行时指令 ## CMD ~~~ #格式: CMD ["executable","param1","param2"] (exec 模式)推荐 CMD command param1 param2 (shell模式) CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数; #解释: #CMD指定容器启动时默认执行的命令 #每个Dockerfile只能有一条CMD命令,如果指定了多条,只有最后一条会被执行 #如果你在启动容器的时候使用docker run 指定的运行命令,那么会覆盖CMD命令。 #举例: CMD ["/usr/sbin/nginx","-g","daemon off;"] #CMD指令实践: #修改Dockerfile文件内容: #在上一个Dockerfile文件内容基础上,末尾增加下面一句话: CMD ["/usr/sbin/nginx","-g","daemon off;"] #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.3 . #根据镜像创建容器,创建时候,不添加执行命令 :~/docker/images/nginx$ docker run --name nginx-1 -itd ubuntu-nginx:v0.3 #根据镜像创建容器,创建时候,添加执行命令/bin/bash :~/docker/images/nginx$ docker run --name nginx-2 -itd ubuntu-nginx:v0.3 /bin/bash docker ps #发现两个容器的命令行是不一样的 itcast@itcast-virtual-machine:~/docker/images/nginx$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED 921d00c3689f ubuntu-nginx:v0.3 "/bin/bash" 5 seconds ago e6c39be8e696 ubuntu-nginx:v0.3 "/usr/sbin/nginx -g ..." 14 seconds ago #查看两个容器详细ip itcast@itcast-virtual-machine:~/docker/images/nginx$ docker inspect 921d00c3689f "IPAddress": "192.168.110.65", itcast@itcast-virtual-machine:~/docker/images/nginx$ docker inspect NAMES nginx- nginx- 2 1 e6c39be8e696 CMD "IPAddress": "192.168.110.64", #格式: CMD ["executable","param1","param2"] (exec 模式)推荐 CMD command param1 param2 (shell模式) CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数; #解释: #CMD指定容器启动时默认执行的命令 #每个Dockerfile只能有一条CMD命令,如果指定了多条,只有最后一条会被执行 #如果你在启动容器的时候使用docker run 指定的运行命令,那么会覆盖CMD命令。 #举例: CMD ["/usr/sbin/nginx","-g","daemon off;"] #CMD指令实践: #修改Dockerfile文件内容: #在上一个Dockerfile文件内容基础上,末尾增加下面一句话: CMD ["/usr/sbin/nginx","-g","daemon off;"] #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.3 . #根据镜像创建容器,创建时候,不添加执行命令 :~/docker/images/nginx$ docker run --name nginx-1 -itd ubuntu-nginx:v0.3 #根据镜像创建容器,创建时候,添加执行命令/bin/bash :~/docker/images/nginx$ docker run --name nginx-2 -itd ubuntu-nginx:v0.3 /bin/bash docker ps ~~~ ## ENTRYPOINT ~~~ #格式: ENTRYPOINT ["executable", "param1","param2"] (exec 模式) ENTRYPOINT command param1 param2 (shell 模式) #解释: #和CMD 类似都是配置容器启动后执行的命令,并且不会被docker run 提供的参数覆盖。 #每个Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。 #生产中我们可以同时使用ENTRYPOINT 和CMD, #想要在docker run 时被覆盖,可以使用"docker run --entrypoint" #ENTRYPOINT指令实践: #修改Dockerfile文件内容: #在上一个Dockerfile 文件内容基础上,修改末尾的CMD 为ENTRYPOINT: ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"] #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.4 . #根据镜像创建容器,创建时候,不添加执行命令 :~/docker/images/nginx$ docker run --name nginx-3 -itd ubuntu-nginx:v0.4 #根据镜像创建容器,创建时候,添加执行命令/bin/bash :~/docker/images/nginx$ docker run --name nginx-4 -itd ubuntu-nginx:v0.4 /bin/bash #查看ENTRYPOINT是否被覆盖 :~/docker/images/nginx$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED NAMES e7a2f0d0924e ubuntu-nginx:v0.4 "/usr/sbin/nginx -g ..." 59 seconds ago nginx-4 c92b2505e28e ubuntu-nginx:v0.4 "/usr/sbin/nginx -g ..." About a minute ago nginx-3 #根据镜像创建容器,创建时候,使用--entrypoint参数,添加执行命令/bin/bash docker run --entrypoint "/bin/bash" --name nginx-5 -itd ubuntu-nginx:v0.4 #查看ENTRYPOINT是否被覆盖 :~/docker/images/nginx$ docker ps CONTAINER ID IMAGE COMMAND NAMES 6c54726b2d96 ubuntu-nginx:v0.4 "/bin/bash" nginx-5 ~~~ ## CMD ENTRYPOINT 综合使用实践 ~~~ CMD ENTRYPOINT 综合使用实践 #修改Dockerfile文件内容: # 在上一个Dockerfile文件内容基础上,修改末尾的ENTRYPOINT :~/docker/images/nginx$ vim Dockerfile ENTRYPOINT ["/usr/sbin/nginx"] CMD ["-g"] #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.5 . #根据镜像创建容器,创建时候,不添加执行命令 :~/docker/images/nginx$ docker run --name nginx-6 -d ubuntu-nginx:v0.5 #查看效果 :~/docker/images/nginx$ docker ps -a CONTAINER ID IMAGE NAMES e28875d281eb ubuntu-nginx:v0.5 nginx-6 COMMAND "/usr/sbin/nginx -g" CREATED 9 seconds ago #根据镜像创建容器,创建时候,不添加执行命令,覆盖cmd的参数 -g "daemon off;" :~/docker/images/nginx$ docker run --name nginx-7 -d ubuntu-nginx:v0.5 -g "daemon off;" #查看效果 itcast@itcast-virtual-machine:~/docker/images/nginx$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED e5addad86ef5 ubuntu-nginx:v0.5 "/usr/sbin/nginx -g ..." 5 seconds ago 7 #注释: #任何docker run设置的命令参数或者CMD指令的命令,都将作为ENTRYPOINT 指令的命令参数,追加到 ENTRYPOINT指令之后 ~~~ # 文件编辑指令 ## ADD ~~~ #ADD #格式: ADD <src>... <dest> ADD ["<src>",... "<dest>"] #解释: #将指定的<src> 文件复制到容器文件系统中的<dest> #src 指的是宿主机,dest 指的是容器 #所有拷贝到container 中的文件和文件夹权限为0755,uid 和gid 为0 #如果文件是可识别的压缩格式,则docker 会帮忙解压缩 #注意: #1、如果源路径是个文件,且目标路径是以/ 结尾, 则docker 会把目标路径当作一个目录,会把源文件 拷贝到该目录下; #如果目标路径不存在,则会自动创建目标路径。 #2、如果源路径是个文件,且目标路径是不是以/ 结尾,则docker 会把目标路径当作一个文件。 #如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件; #如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。 #如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。注意,这种情况下,最好显示的以/ 结尾,以 避免混淆。 #3、如果源路径是个目录,且目标路径不存在,则docker 会自动以目标路径创建一个目录,把源路径目录 下的文件拷贝进来。 #如果目标路径是个已经存在的目录,则docker 会把源路径目录下的文件拷贝到该目录下。 #4、如果源文件是个压缩文件,则docker 会自动帮解压到指定的容器目录中。 #ADD实践: #拷贝普通文件 :~/docker/images/nginx$ vim Dockerfile #Dockerfile文件内容 # 构建一个基于ubuntu的docker定制镜像 # 基础镜像 FROM ubuntu # 镜像作者 MAINTAINER panda kstwoak47@163.com # 执行命令 ADD ["sources.list","/etc/apt/sources.list"] RUN apt-get clean RUN apt-get update RUN apt-get install nginx -y # 对外端口 EXPOSE 80 #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.6 . #根据镜像创建容器,创建时候,不添加执行命令进入容器查看效果 docker run --name nginx-8 -it ubuntu-nginx:v0.6 #拷贝压缩文件 tar zcvf this.tar.gz ./* #Dockerfile文件内容 ... # 执行命令 ... # 增加文件 ADD ["linshi.tar.gz","/nihao/"] ... #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.7 . #根据镜像创建容器,创建时候,不添加执行命令进入容器查看效果 docker run --name nginx-9 -it ubuntu-nginx:v0.7 :~/docker/images/nginx$ docker run --name nginx-9 -it ubuntu-nginx:v0.7 ~~~ ## COPY ~~~ #COPY #格式: COPY <src>... <dest> COPY ["<src>",... "<dest>"] #解释: #COPY 指令和ADD 指令功能和使用方式类似。只是COPY 指令不会做自动解压工作。 #单纯复制文件场景,Docker 推荐使用COPY #COPY实践 #修改Dockerfile文件内容: # 构建一个基于ubuntu的docker定制镜像 # 基础镜像 FROM ubuntu # 镜像作者 MAINTAINER panda kstwoak47@163.com # 执行命令 ADD ["sources.list","/etc/apt/sources.list"] RUN apt-get clean RUN apt-get update RUN apt-get install nginx -y COPY ["index.html","/var/www/html/"] # 对外端口 EXPOSE 80 #运行时默认命令 ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"] index.html 文件内容: <h1>hello world </h1> <h1>hello docker </h1> <h1>hello nginx</h1> #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.8 . #根据镜像创建容器,创建时候,不添加执行命令 :~/docker/images/nginx$ docker run \--name nginx-10 \-itd ubuntu-nginx:v0.8 #查看nginx-10信息 :~/docker/images/nginx$docker inspect nginx-10 #浏览器访问nginx查看效果 ~~~ ## VOLUME ~~~ #VOLUME #格式: VOLUME ["/data"] #解释: #VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点 #通过VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。 #举例: VOLUME ["/var/lib/tomcat7/webapps/"] ~~~ # 环境指令 ## ENV ~~~ #ENV #格式: ENV <key> <value> (一次设置一个环节变量) ENV <key>=<value> ... (一次设置一个或多个环节变量) #解释: #设置环境变量,可以在RUN 之前使用,然后RUN 命令时调用,容器启动时这些环境变量都会被指定 ~~~ ## ENV实践 ~~~ #ENV实践: #命令行创建ENV的容器 :~$ docker run -e NIHAO="helloworld" -itd --name ubuntu-111 ubuntu /bin/bash #进入容器ubuntu-111 :~$ docker exec -it ubuntu-111 /bin/bash :/# echo $NIHAO #修改Dockerfile文件内容: #在上一个Dockerfile 文件内容基础上,在RUN 下面增加一个ENV ENV NIHAO=helloworld ... #构建镜像 docker build -t ubuntu-nginx:v0.10 . #根据镜像创建容器,创建时候,不添加执行命令 docker run --name nginx-12 -itd ubuntu-nginx:v0.10 docker exec -it nginx-12 /bin/bash echo $NIHAO ~~~ ## WORKDIR ~~~ #WORKDIR #格式: WORKDIR /path/to/workdir (shell 模式) #解释: #切换目录,为后续的RUN、CMD、ENTRYPOINT 指令配置工作目录。相当于cd #可以多次切换(相当于cd 命令), #也可以使用多个WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如 #举例: WORKDIR /a WORKDIR b WORKDIR c RUN pwd #则最终路径为/a/b/c ~~~ **实践** ~~~ #WORKDIR实践: #修改Dockerfile文件内容: # 在上一个Dockerfile 文件内容基础上,在RUN 下面增加一个WORKDIR WORKDIR /nihao/itcast/ RUN ["touch","itcast1.txt"] WORKDIR /nihao RUN ["touch","itcast2.txt"] WORKDIR itcast RUN ["touch","itcast3.txt"] ... #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.11 . #根据镜像创建容器,创建时候,不添加执行命令 docker run --name nginx-13 -itd ubuntu-nginx:v0.11 #进入镜像 docker exec -it nginx-13 /bin/bash ~~~ ## USER与ARG ~~~ #USER #格式: USER daemon #解释: #指定运行容器时的用户名和UID,后续的RUN 指令也会使用这里指定的用户。 #如果不输入任何信息,表示默认使用root 用户 #ARG #格式: ARG <name>[=<default value>] #解释: #ARG 指定了一个变量在docker build 的时候使用,可以使用\--build-arg =来 指定参数的值,不过 #如果构建的时候不指定就会报错。 ~~~ # 触发器 ~~~ ONBUILD #格式: ONBUILD [command] #解释: #当一个镜像A被作为其他镜像B的基础镜像时,这个触发器才会被执行, #新镜像B在构建的时候,会插入触发器中的指令。 #使用场景对于版本控制和方便传输,适用于其他用户。 ~~~ **实践** ~~~ #编辑Dockerfile :~/docker/images/nginx$ vim Dockerfile #内容如下: # 构建一个基于ubuntu的docker定制镜像 # 基础镜像 FROM ubuntu # 镜像作者 MAINTAINER panda kstwoak47@163.com # 执行命令 ADD ["sources.list","/etc/apt/sources.list"] RUN apt-get clean RUN apt-get update RUN apt-get install nginx -y #触发器 ONBUILD COPY ["index.html","/var/www/html/"] # 对外端口 EXPOSE 80 #运行时默认命令 ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"] #构建镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.12 . #根据镜像创建容器, :~/docker/images/nginx$docker run -p 80 --name nginx-14 -itd ubuntu-nginx:v0.12 :~/docker/images/nginx$docker ps #查看镜像信息 :~/docker/images/nginx$ docker inspect ubuntu-nginx:v0.12 #访问容器页面,是否被更改 :~/docker/images/nginx$ docker inspect nginx-14 #构建子镜像Dockerfile文件 FROM ubuntu-nginx:v0.12 MAINTAINER panda kstwoak47@163.com EXPOSE 80 ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"] #构建子镜像 :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.13 . #根据镜像创建容器, docker run -p 80 --name nginx-15 -itd ubuntu-nginx:v0.13 #查看镜像信息 :~/docker/images/nginx$ docker inspect ubuntu-nginx:v0.13 docker ps #访问容器页面,是否被更改 ~~~ # 构建缓存 第一次构建很慢,之后的构建都会很快,因为他们用到了构建的缓存 ~~~ #取消缓存: docker build --no-cache -t [镜像名]:[镜像版本][Dockerfile位置] ~~~