基本上,一个Dockerfile包含以下的内容:
引用
# version 0.0.1-snapshot
# 从一个基础镜像centos:6.8开始构建
FROM centos:6.8
# 维护者信息
MAINTAINER hylexus "[email protected]"
# 将Dockerfile上下文中的nginx.repo复制到容器中的yum源位置
COPY ./nginx.repo /etc/yum.repos.d/nginx.repo
RUN yum makecache
# 安装nginx
RUN yum install -y nginx
# 修改nginx首页信息
RUN echo "home page of container niginx server" > /usr/share/nginx/html/index.html
# 暴露80端口
EXPOSE 80
# 从一个基础镜像centos:6.8开始构建
FROM centos:6.8
# 维护者信息
MAINTAINER hylexus "[email protected]"
# 将Dockerfile上下文中的nginx.repo复制到容器中的yum源位置
COPY ./nginx.repo /etc/yum.repos.d/nginx.repo
RUN yum makecache
# 安装nginx
RUN yum install -y nginx
# 修改nginx首页信息
RUN echo "home page of container niginx server" > /usr/share/nginx/html/index.html
# 暴露80端口
EXPOSE 80
2. Dockerfile 基本指令介绍
2.1. FROM
用法:FROM <image>
说明:第一个指令必须是FROM了,其指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的latest标签,可以出现多次,如果需要在一个Dockerfile中构建多个镜像。
例如:FROM centos:6.8
2.2. MAINTAINER
用法:MAINTAINER <name> <email>
说明:描述镜像的创建者,名称和邮箱
例如:
引用
MAINTAINER hylexus "[email protected]"
2.3. RUN
用法:RUN "command" "param1" "param2"
说明:RUN命令是一个常用的命令,执行完成之后会成为一个新的镜像,这里也是指镜像的分层构建。一句RUN就是一层,也相当于一个版本。这就是之前说的缓存的原理。我们知道docker是镜像层是只读的,所以你如果第一句安装了软件,用完在后面一句删除是不可能的。所以这种情况要在一句RUN命令中完成,可以通过&符号连接多个RUN语句。RUN后面的必须是双引号不能是单引号(没引号貌似也不要紧),command是不会调用shell的,所以也不会继承相应变量,要查看输入RUN "sh" "-c" "echo" "$HOME",而不是RUN "echo" "$HOME"。一个dockerfile可以有多个RUN,但是要记住每行的RUN都表示在一个新的镜像上面执行。
例如:如果要在同一个镜像上执行多段命令,需要用&&连接命令,如:
引用
RUN /bin/sh -c 'cd /usr/share/nginx/html/ && npm install'
这段RUN由两段命令组成,第一段是cd到一个指定文件夹下,第二段是在该文件夹下安装npm工具。但是如果写成了下面这样:
引用
RUN cd /usr/share/ngnix/html
RUN npm install
RUN npm install
表示先在一个镜像上cd到一个指定文件夹,然后又到新的镜像上的根目录安装了npm
2.4. CMD
用法:CMD command param1 param2
说明:CMD在Dockerfile中只能出现一次,如果有多个,只有最后一个会有效。其作用是在启动容器的时候提供一个默认的命令项。如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令。没提供就会使用构建时的命令。
例如:当我们dockerfile生成了一个叫做test/ubuntu的镜像,我们要run这个镜像并且进入到这个test_ubuntu里面,我们平时需要执行:
Docker run -I -t -name testserver test/Ubuntu /bin/bash
如下段命令添加在了dockerfile中。
CMD ["/bin/bash"]
启动了容器后进入系统,我们就不需要写 /bin/bash了。或者我们run docker容器的时候,我们可以放其他命令,就可以覆盖/bin/bash这个CMD命令。
2.5. EXPOSE
用法:EXPOSE <port> [<port>...]
说明:告诉Docker服务器容器对外映射的容器端口号,在docker run -p的时候生效。可以有多个EXPOSE
例如:
引用
EXPOSE 80
2.6. EVN
用法:EVN <key> <value> 一行只能设置一个
EVN <key>=<value>允许一行一次设置多个
说明:设置容器的环境变量,可以让其后面的RUN命令使用,容器运行的时候这个变量也会保留。
例如:
引用
RUN set -ex && apt-get update && apt-get install -y iputils-ping
ENV PATH /usr/local/bin:$PATH
ENV LANG C.UTF-8
ENV TERM xterm
ENV PYTHON_VERSION 3.5.3
ENV name1=ping name2=on_ip
CMD $name1 $name2
ENV PATH /usr/local/bin:$PATH
ENV LANG C.UTF-8
ENV TERM xterm
ENV PYTHON_VERSION 3.5.3
ENV name1=ping name2=on_ip
CMD $name1 $name2
由于镜像的层次文件系统,ENV定义的环境变量在后续层次中才能够被应用,示例如下:
引用
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
ENV abc=bye def=$abc
ENV ghi=$abc
上述定义的结果中,def=hello,ghi=bye
2.7. ADD
用法:ADD <src> <dest>
说明:复制本机文件或目录或远程文件,添加到指定的容器目录,支持GO的正则模糊匹配。路径是绝对路径,不存在会自动创建。如果源是一个目录,只会复制目录下的内容,目录本身不会复制。ADD命令会将复制的压缩文件夹自动解压,这也是与COPY命令最大的不同。事实上,当要读取URL远程资源的时候,并不推荐使用ADD指令,而是建议使用RUN指令,在RUN指令中执行wget或curl命令。
例如:
引用
#test
FROM ubuntu
MAINTAINER hello
ADD test1.txt test1.txt
ADD test1.txt test1.txt.bak
ADD test1.txt /mydir/
ADD data1 data1
ADD data2 data2
ADD zip.tar /myzip
FROM ubuntu
MAINTAINER hello
ADD test1.txt test1.txt
ADD test1.txt test1.txt.bak
ADD test1.txt /mydir/
ADD data1 data1
ADD data2 data2
ADD zip.tar /myzip
有如下注意事项:
1. 如果源路径是个文件,且目标路径是以 / 结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下。如果目标路径不存在,则会自动创建目标路径。
2. 如果源路径是个文件,且目标路径是不是以 / 结尾,则docker会把目标路径当作一个文件。
如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件;
如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。
如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。
3. 如果源路径是个目录,且目标路径不存在,则docker会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。
如果目标路径是个已经存在的目录,则docker会把源路径目录下的文件拷贝到该目录下。
4. 如果源文件是个归档文件(压缩文件),则docker会自动帮解压。
2.8. COPY
用法:COPY <src> <dest>
说明:COPY除了不能自动解压,也不能复制网络文件。其它功能和ADD相同。
因为有ADD的强大,对COPY不做更多说明。
2.9. ENTRYPOINT
用法:ENTRYPOINT "command" "param1" "param2"
说明:这个命令和CMD命令一样,唯一的区别是不能被docker run命令的执行命令覆盖,如果要覆盖需要带上选项--entrypoint,如果有多个选项,只有最后一个会生效。
因为不会被run覆盖,ENTRYPOINT可以配合docker run来使用。Docker run后面跟的参数作为ENTRYPOINT的参数来使用
例如:
引用
FROM centos
MAINTAINER allocator
RUN yum install -y nginx
RUN echo 'hello world' > /usr/share/nginx/html/index.html
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]
MAINTAINER allocator
RUN yum install -y nginx
RUN echo 'hello world' > /usr/share/nginx/html/index.html
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]
当我们启动镜像的时候不给参数
docker run --name test -p 5000:80 -it test_nginx
系统会用CMD指定的参数-h来运行ENTRYPOINT的命令。
当我们启动镜像的时候加了参数
docker run --name test -p 5000:80 -it test_nginx -g "daemon off"
系统会替换到CMD的参数用 -g "daemon off"来运行ENTRYPOINT的命令
2.10. VOLUME
用法:VOLUME ["path"]
说明:在主机上创建一个挂载,挂载到容器的指定路径。docker run -v命令也能完成这个操作,而且更强大。这个命令不能指定主机的需要挂载到容器的文件夹路径。但docker run -v可以,而且其还可以挂载数据容器。
2.11. USER
用法: USER <user>[:<group>] or
USER <UID>[:<GID>]
说明:指定运行容器时的用户名或UID,后续的RUN、CMD、ENTRYPOINT也会使用指定的用户运行命令。
2.12. WORKDIR
用法:WORKDIR path
说明:为RUN、CMD、ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续参数如果是相对路径,则会基于之前的命令指定的路径。
例如:WORKDIR /home WORKDIR test 。最终的路径就是/home/test。path路径也可以是环境变量,比如有环境变量HOME=/home,WORKDIR $HOME/test也就是/home/test。
2.13. ONBUILD
用法:ONBUILD [INSTRUCTION]
说明:配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。意思就是,这个镜像创建后,如果其它镜像以这个镜像为基础,会先执行这个镜像的ONBUILD命令。