Dockerfile指令

原文发表于cu2016-06-01html

参考文档: docker

  1. 官方文档: https://docs.docker.com/engine/reference/builder/
  2. 官方最佳实践:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
  3. http://seanlook.com/2014/11/17/dockerfile-introduction/
  4. CMD与ENTRYPOINT的区别:http://www.cnblogs.com/programfish/p/4101884.html

 Dockefile建立image是被推荐的方式,不一样于"docker build"须要手动commit与rm中间层镜像,dockerfile是自动化的建立image(二者原理均是使用基础镜像启动容器后commit)。shell

一.Dockerfile构建image的优化建议

如下优化建议仅为我的观点。vim

1. 精简程序

在构建image时,不须要安装没必要要的程序,这样能够保证构建出的image轻小,依赖性小且构建速度快。centos

2. 1个容器运行1个服务

大多数状况下,建议1个容器运行1个服务便可,这样能够减小服务的耦合性,充分发挥容器复用及快速横向扩展的优点。缓存

3. 合理控制镜像层数

1条dockerfile指令会生成1层新的镜像,镜像层越多,image越大,容器启动速度越慢;建议尽量减小image层数,但同时须要注意dockerfile的可读性,即合理控制image层数。bash

4. Dockerfile指令参数排序

对指令参数的排序主要是为了dockerfile的可读性与确保不会重复输入参数。如:ssh

RUN yum install -y \
Git \
net-tools \
openssh-server

5. 使用缓存

前面讲到1条dockerfile指令会生成1层新的镜像,下一条指令会基于上一步生成的镜像构建新的镜像层,若是一个镜像存在相同的父镜像与指令("ADD"指令除外),默认docker会使用缓存的镜像,而不是从新执行dockerfile指令。ide

因此在修改Dockerfile时,为了有效利用镜像,能够尽可能不动Dockerfile的前面几行。优化

例如"MAINTAINER"通常在第二行,若是修改此处,那后续的"RUN"指令会所有执行,而不是使用缓存的镜像层。

二.Dockerfile主要指令及语法

1. FROM

 Dockerfile第一条指令,此指令指定dockerfile构建image的基础镜像,若是宿主机仓库没有指定的基础镜像,则从远端仓库pull。

 语法:FROM <image>:<tag>

2. MAINTAINER

指明image做者,方便联系。

语法:MAINTAINER <author name> (author information, email and so on)

3. RUN

在当前镜像生成的容器的外层(可读写层)执行命令,并commit成1个新的镜像层,接下来的指令会在这个新的镜像层生成的容器里执行。

语法(2种):

  1. RUN <command>

    #shell form:在shell环境下执行,调用"/bin/sh –c"

  2. RUN ["executable", "param1", "param2"]

    #exec form:不会触发shell,因此环境变量没法调用,但能够在没有bash的image中执行

4. ADD

复制文件,有两个参数<source>和<destination>。

注意:

  1. destination是容器内的绝对路径,若是路径不存在则自动建立;source能够是文件/文件夹/URL,若是是文件/文件夹,必须是Dockerfile所在目录的一个相对路径,且不能含"../path/";
  2. ADD支持自动解压tar文件,解压以后再copy到容器内。

语法:ADD <source> <destination> 

5. COPY

基本与ADD相同,但不支持远程URL(source),与自动解压的功能。

注意:官方最佳实践中建议尽可能使用copy,使用RUN与COPY的组合代替ADD,由于COPY处理更透明。

6. ENTRYPOINT

配置给容器一个可执行的命令,相似将容器变为1个可执行文件/命令。

意味着在每次使用镜像建立容器时,一个特定的应用程序能够被设置为默认程序;同时也意味着该镜像每次被调用时仅能运行指定的应用。

注意:

  1. 多个ENTRYPOINT指令只有最后一个生效(后面覆盖前面);
  2. exec格式时,"docker run <image>"的全部参数会追加到ENTRYPOINT以后,即"docker run <image>"的参数能够传递给ENTRYPOINT,不会被覆盖,但"docker run <image>"的参数会覆盖CMD指令;
  3. exec格式时,由于CMD能够为ENTRYPOINT提供参数,ENTRYPOINT自己也能够包含参数,且"docker run <image>"的参数能够覆盖CMD指令,因此能够把那些可能须要变更的参数写到CMD里,而把那些不须要变更的参数写到ENTRYPOINT里面。
  4. exec格式时,在启动容器时使用--entrypoint参数会覆盖dockerfile里的ENTRYPOINT;
  5. shell form格式会屏蔽掉docker run启动容器后面带的命令参数或者CMD里的参数;

语法(2种):

  1. ENTRYPOINT ["executable", "param1","param2"]

    #exec form:推荐使用的格式

  2. ENTRYPOINT command param1 param2

    #shell form:会屏蔽掉docker run时后面加的命令参数与CMD里的参数

7. CMD

指定制做出的image在启动成容器时运行的默认命令或参数。

注意:

  1. 1个dockerfile只有1个CMD指令,若是使用多个CMD指令,只有最后1个指令生效;
  2. docker run命令若是指定容器运行参数,会把CMD里的参数覆盖;
  3. RUN指令是在构建image时执行,将命令固化在image中;而CMD指令在构建image时并不执行,而是在容器启动时执行(切记docker run指定的容器参数会覆盖CMD指令)。
  4. 若是CMD提供的是默认参数,执行命令须要提早在ENTRYPORINT中指定。

语法(3种):

  1. CMD ["executable","param1","param2"]

    #exec form:推荐使用的格式,可执行文件+参数

  2. CMD ["param1","param2"]

    #传递到ENTRYPOINT,做为ENTRYPOINT的参数

  3. CMD command param1 param2

    #shell form:做为"/bin/sh –c"的参数

8. EXPOSE

指定容器运行时须要监听的端口,用在多容器之间通讯使用。

语法:EXPOSE <port> 

9. ENV

设置环境变量,增长运行程序的灵活性,使用键值对格式。

若是须要更改镜像生成容器时改变环境变量,可在运行"docker run"是带"-env <key>=<value>"参数修改既定环境变量。

语法:ENV <key> <value> 

10. ONBUILD

指令用来设置一些触发的指令,用于在当该镜像被做为基础镜像来建立其余镜像时执行一些操做,ONBUILD中定义的指令会在用于生成其余镜像的Dockerfile文件的FROM指令以后被执行,能够用来执行一些由于环境而变化的操做,使镜像更加通用,dockerfile全部指令均可以用于ONBUILD指令

注意:

  1. ONBUILD定义的指令在生成当前image的"docker build"中不会执行;
  2. 经过查看docker inspect <image>命令执行结果的OnBuild键来查看某个镜像ONBUILD指令定义的内容;
  3. ONBUILD中定义的指令会当作引用该镜像的Dockerfile文件的FROM指令的一部分来执行,执行顺序会按ONBUILD定义的前后顺序执行,若是ONBUILD中定义的任何一个指令运行失败,则会使FROM指令中断并致使整个build失败,当全部的ONBUILD中定义的指令成功完成后,会按正常顺序继续执行build;
  4. ONBUILD中定义的指令不会继承到当前引用的镜像中,即当引用ONBUILD的镜像建立完成后将会清除全部引用的ONBUILD指令;
  5. ONBUILD指令不容许嵌套;
  6. ONBUILD指令不会执行其定义的FROM或MAINTAINER指令。

11. USER

镜像正在运行时或接下来的RUN指令设定用户名或UID。

语法:USER <uid> 

12. WORKDIR

指定RUN、CMD与ENTRYPOINT命令的工做目录,默认为"/"目录。

可在dockerfile中屡次出现,若是使用相对路径,后一次的相对路径是上一次WORKDIR的值。

语法:WORKDIR /path/to/workdir 

13. VOLUME

指定挂载点,能够用来让其余容器挂载以实现数据共享或对容器数据的备份、恢复或迁移。

语法:VOLUME ["path"] 

三.Dockerfile示例

1. Dockerfile

#使用Dockerfile构建1个可ssh的image
[root@localhost ~]# touch Dockerfile

#注意"Dockerfile"首字母大写;
#此示例将RUN须要执行的指令合并为1条指令,可减小image层数;
#yum安装程序是按字母顺序排列的(非强制要求)
[root@localhost ~]# vim Dockerfile

# Get a base image.
FROM centos:latest

# Author
MAINTAINER Netonline "xxxxx@gmail.com"

# Install some CLI tools.
RUN yum install -y \
net-tools \
openssh-clients \
openssh-server && \
sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config && \

# Modify root password.
echo "root:123456" | chpasswd && \

# Generate keys for sshd.
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

# Open sshd port and execute service.
EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]

2. 构建image

#"docker build"执行时使用同目录的"Dockerfile"文件;另外"centos:ssh"为构建的image名,注意命令最后带的"."
[root@localhost ~]# docker build -t centos:ssh . 

 

3. 验证

[root@localhost ~]# docker images

相关文章
相关标签/搜索