文档章节

Docker之Dockerfile详解

408582708
 408582708
发布于 2017/05/18 12:31
字数 2846
阅读 115
收藏 1

Dockerfile的指令是忽略大小写的,建议使用大写,使用#作为注释,每一行只支持一条指令,每条指令可以携带多个参数。

Dockerfile的指令根据作用可以分为两种:构建指令和设置指令。构建指令用于构建image,其指定的操作不会在运行image的容器上执行;设置指令用于设置image的属性,其指定的操作将在运行image的容器中执行。

1)FROM

说明:指定基础image

构建指令,必须指定且需要在Dockerfile其他指令的前面。后续的指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库。

FROM <image>[:<tag>]

说明:无 [:<tag>] 表示指定基础image为该image的最后修改的版本。

2)MAINTAINER

说明:用来指定镜像创建者信息

构建指令,用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。格式:

MAINTAINER <name>

3)RUN

说明:容器中执行命令,然后把执行后的改变提交到当前镜像,提交后的镜像(作为一层文件)会被用于Dockerfile中定义的下一步操作,RUN中定义的命令会按顺序执行并提交,这正是Docker廉价的提交和可以基于镜像的任何一个历史点创建容器的好处,就像版本控制工具一样。

构建指令,RUN可以运行任何被基础image支持的命令。如基础image选择了centos,那么软件管理部分只能使用centos的命令。该指令有两种格式:

# the command is run in a shell - `/bin/sh -c`
RUN <command> 

# 调用exec执行,以避免有些时候shell方式执行时的传递参数问题,而且有些基础镜像可能不包含/bin/sh
RUN ["executable", "param1", "param2" ... ] 

尽量使用 && 和 \ 将所有的指令都压缩为了一行,这里有两个原因:

  1. RUN 指令不会保存上一条指令的工作路径,每条 RUN 指令都只会将工作目录指定为 / 目录

  2. 一条 Dockerfile 中的指令就会产生一次镜像的提交,换言之,减少 Dockerfile 中的指令就可以提高镜像的复用水平

4)CMD

说明:设置容器启动时执行的操作。

设置指令,用于container启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条。该指令有三种格式:

# like an exec, this is the preferred form. 命令必须为绝对路径
CMD ["executable","param1","param2"]

# 将会调用 /bin/sh -c command
CMD command [param1,param2]

当Dockerfile指定了ENTRYPOINT,CMD中定义的内容会作为ENTRYPOINT指令的默认参数,也就是说可以使用CMD指令给ENTRYPOINT传递参数。当Docker run command的命令匹配到CMD command时,会替换CMD执行的命令。

# as default parameters to ENTRYPOINT
CMD ["param1","param2"]

例如:

FROM ubuntu:14.10  

# 把可能需要变动的参数写到CMD里面。
# 然后你可以在docker run image command params,这样CMD里的参数(这里是-c)就会被 params 覆盖掉而ENTRYPOINT里的参数 -a 不被覆盖。
# 比如:docker run image ls -a -l

ENTRYPOINT ["ls", "-a"]   
CMD ["-c"] 


5)ENTRYPOINT

说明:设置容器启动时执行的操作

ENTRYPOINT指定的是一个可执行的脚本或者程序的路径,该指定的脚本或者程序将会以param1和param2作为参数执行。所以如果CMD指令使用上面的形式(作为参数),那么Dockerfile中必须要有配套的ENTRYPOINT。

container启动时执行的命令,但是一个Dockerfile中只能有一条ENTRYPOINT命令,如果多条,则只执行最后一条。ENTRYPOINT没有CMD的可替换特性。该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用。

# as a shell
ENTRYPOINT command param1 param2

# like an exec, the preferred form
ENTRYPOINT ["executable", "param1", "param2"]

1) 当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效

# CMD指令将不会被执行,只有ENTRYPOINT指令被执行;
...
CMD echo "Hello, World!"
​​​​​​​ENTRYPOINT ls -l

2) 和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分;ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数

FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]

6)USER

说明:设置容器的用户,默认是root用户。​​​​​​​​​​​​​​

# 指定memcached的运行用户;

ENTRYPOINT ["memcached"]

USER daemon

ENTRYPOINT ["memcached", "-u", "daemon"]

7)EXPOSE

说明:指定容器需要映射到宿主机器的端口
该指令会将容器中的端口映射成宿主机器中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项。格式:

EXPOSE <port> [<port>...]

# 映射一个端口;
EXPOSE port1

# 相应的运行容器使用的命令;
docker run -p port1 image


# 映射多个端口;
EXPOSE port1 port2 port3

# 相应的运行容器使用的命令;
docker run -p port1 -p port2 -p port3 image

# 还可以指定需要映射到宿主机器上的某个端口号;
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image

端口映射是docker比较重要的一个功能,原因在于我们每次运行容器的时候容器的IP地址不能指定而是在桥接网卡的地址范围内随机生成的。宿主机器的IP地址是固定的,我们可以将容器的端口的映射到宿主机器上的一个端口,免去每次访问容器中的某个服务时都要查看容器的IP的地址。对于一个运行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID来查看该端口号在宿主机器上的映射端口。

8)ENV

说明:用于设置环境变量

构建指令,在image中设置一个环境变量。格式:

ENV <key> <value>

假如你安装了JAVA程序,需要设置JAVA_HOME,那么可以在Dockerfile中这样写:设置了后,后续的RUN命令都可以使用,container启动后,可以通过docker inspect查看这个环境变量,也可以通过在docker run –env key=value时设置或修改环境变量。

ENV JAVA_HOME /path/to/java/dirent

9)ADD

说明:从src复制文件到container的dest路径

构建指令,所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0;

如果是一个目录,那么会将该目录下的所有文件添加到container中,不包括目录;
如果文件是可识别的压缩格式,则docker会帮忙解压缩(注意压缩格式);
如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>;
如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。

格式:

ADD <src> <dest>

<dest>:是container中的绝对路径。<src>:是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url。

10)VOLUME

说明:指定挂载点

设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。

格式:

VOLUME ["mountpoint"]


样例:

FROM base

VOLUME ["/tmp/data"]

运行通过该Dockerfile生成image的容器,/tmp/data目录中的数据在容器关闭后,里面的数据还存在。例如第二个容器也有持久化数据的需求,且想使用上面容器共享的/tmp/data目录,那么可以运行下面的命令启动一个容器:

# container1为第一个容器的ID,image2为第二个容器运行image的名字。
# 实现目标:image2 生成的 container2 将共享 container1 的 /tmp/data 目录
$ docker run -t -i -rm --volumes-from container1 image2 bash

11)WORKDIR

说明:切换目录(cd)

用于设置Dockerfile中的RUN、CMD和ENTRYPOINT指令执行命令的工作目录(默认为/目录),该指令在Dockerfile文件中可以出现多次,如果使用相对路径则为相对于WORKDIR上一次的值,例如WORKDIR /data,WORKDIR logs,RUN pwd最终输出的当前目录是/data/logs。

格式:

WORKDIR /path/to/workdir

样例:

# 在/p1/p2下执行vim a.txt;

WORKDIR /p1 
WORKDIR p2 
RUN vim a.txt

12)ONBUILD

说明:在子镜像中执行

ONBUILD <Dockerfile关键字>

ONBUILD指令用来设置一些触发的指令,用于在当该镜像被作为基础镜像创建其他镜像时(也就是Dockerfile中的FROM为当前镜像时)执行一些操作,ONBUILD中定义的指令会在用于生成其他镜像的Dockerfile文件的FROM指令之后被执行,上述介绍的任何一个指令都可以用于ONBUILD指令,可以用来执行一些因为环境而变化的操作,使镜像更加通用。


注意:
①ONBUILD中定义的指令在当前镜像的build中不会被执行。
②可以通过查看docker inspeat <image>命令执行结果的OnBuild键来查看某个镜像ONBUILD指令定义的内容。
③ONBUILD中定义的指令会当做引用该镜像的Dockerfile文件的FROM指令的一部分来执行,执行顺序会按ONBUILD定义的先后顺序执行,如果ONBUILD中定义的任何一个指令运行失败,则会使FROM指令中断并导致整个build失败,当所有的ONBUILD中定义的指令成功完成后,会按正常顺序继续执行build。
 ④ONBUILD中定义的指令不会继承到当前引用的镜像中,也就是当引用ONBUILD的镜像创建完成后将会清除所有引用的ONBUILD指令。
⑤ONBUILD指令不允许嵌套,例如ONBUILD ONBUILD ADD . /data是不允许的。
⑥ONBUILD指令不会执行其定义的FROM或MAINTAINER指令。

 

本文转载自:https://www.server110.com/docker/201411/11103.html

408582708
粉丝 0
博文 111
码字总数 70938
作品 0
朝阳
程序员
私信 提问
使用 Dockerfile定制Java Web镜像

一、前言 对使用 Docker 搭建 Java Web 运行环境(利用 commit 理解镜像构成 来源:黄勇 )博文的归纳: 1、启动容器: docker run <相关参数> <镜像 ID> <初始命令> -i:表示以“交互模式”运...

吴伟祥
2018/11/16
808
0
IntelliJ IDEA快速实现Docker镜像部署

一、Docker开启远程访问 二、IntelliJ IDEA安装Docker插件 三、启用Docker 四、Spring Boot服务docker部署 1、新建一个Spring Boot工程,在工程里写一个REST接口,如下,简单返回一个字符串。...

吴伟祥
2018/11/09
4.3K
2
Dockerfile 的详解

Dockerfile 的详解 使用Docker技术构建自己的镜像是最常见的应用场景,目前为止Docker官方也提供两种构建镜像的方法。一种是使用 指令将当前的容器状态保存为一个镜像,另外一种则是编写Doc...

Allocator
2017/04/06
0
0
Dockerfile指令详解

Dockerfile指令详解 Docker可以从Dockerfile中一步一步的读取指令来自动的创建镜像,常使用Dockerfile来创建用户自定义的镜像。格式如下: # CommentINSTRUCTION arguments 虽然前面的指令大...

双鱼座小龙
2017/08/23
0
0
『中级篇』Dockerfile实战CMD和ENTRTYPOINT的配合(21)

本节主要讲解下压力测试工具stress在docker上的应用 环境搭建 stress命令 创建对应stress对应的Dockerfile 发现问题了,run执行的效果和刚在才容器内部执行stress很一样。其实说白了就是没增...

IT人故事会
2018/06/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

c语言实现Sqlite3的创建db和增删改查db操作

SQLite,是一款轻型的数据库,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中使用广泛,现在准备学习一下sqlite3的使用方法并写一个测试demo,后面在项目智能...

jorin_zou
12分钟前
2
0
【2019年8月版本】OCP 071认证考试最新版本的考试原题-第2题

choose three Which three are true about the CREATE TABLE command? A) It can include the CREATE...INDEX statement for creating an index to enforce the primary key constraint. B) ......

oschina_5359
15分钟前
3
0
如何在二维码中循环批量插入图片

现在二维码种类比较多,为了突出二维码的个性及吸引客户,很多朋友都喜欢在二维码上插入图片。想要每个二维码都与众不同,但是有的时候需要批量插入图片数量有限,如果制作的二维码比较多的话...

中琅软件
16分钟前
4
0
LTR那点事—AUC及其与线上点击率的关联详解

LTR(Learning To Rank)学习排序是一种监督学习(SupervisedLearning)的排序方法,现已经广泛应用于信息索引,内容推荐,自然语言处理等多个领域。以推荐系统为例,推荐一般使用多个子策略...

达观数据
17分钟前
3
0
IntelliJ 如何显示代码的代码 docs

希望能够在 IntelliJ 代码上面显示方法的 docs。 如何进行显示? 你可以使用 Ctrl + Q 这个快捷键来查看方法的 Docs。 https://blog.ossez.com/archives/3061...

honeymoose
20分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部