[Docker学习笔记补充] dockerfile编写

个人觉得Dockerfile文件的编写很重要,在Docker学习笔记一文中受限于篇幅问题(文章已经很长很长了,再多拓展下去阅读起来会非常难受)没有进行更加详细的讲解,想了想出个单篇来详细介绍一下Dockerfile文件的编写。

使用 docker commit 来扩展一个镜像比较简单,但是不方便在一个团队中分享。

Dockerfile的简单应用

我们可以使用 docker build 来创建一个新的镜像。为此,首先需要创建一个 Dockerfile,包含一些如何创建镜像的指令。
新建一个目录和一个 Dockerfile

mkdir nmap
cd nmap
touch Dockerfile

Dockerfile 中每一条指令都创建镜像的一层,例如:

# I want to use nmap to scan~
FROM ubuntu:18.04
MAINTAINER Xiaoyesec <2245998470@qq.com>
RUN apt-get -qq update
RUN apt-get -qqy install nmap

Dockerfile 基本的语法是:

  • 使用 # 来注释
  • FROM 指令告诉 Docker 使用哪个镜像作为基础镜像
  • MAINTAINER 注明维护者的信息
  • RUN 开头的命令会在创建中运行,比如安装一个软件包,在这里使用apt-get来安装了nmap

查看一下我们编写好的Dockerfile文件:

编写完成 Dockerfile 后可以运行 docker build 来生成镜像:docker build -t="ubuntu/nmap" .
其中 -t 标记来添加 tag,指定新的镜像的用户信息, “.” 是 Dockerfile 所在的路径(当前目录)不可省略,也可以替换为一个具体的 Dockerfile 的路径。

可以看到 build 进程在执行操作。它要做的第一件事情就是上传这个 Dockerfile 内容,因为所有的操作都要依据 Dockerfile 来进行。
然后,Dockfile 中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改(就跟之前介绍过的 docker commit 一样)。
当所有的指令都执行完毕之后,返回了最终的镜像 id。所有的中间步骤所产生的容器都被删除和清理了。

注意:一个镜像不能超过 127 层

Dockerfile常用命令

FROM

格式为FROM imageFROM image:tag,并且Dockerfile中第一条指令必须是FROM指令,且在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令。

MAINTAINER

格式为MAINTAINER user_name user_email,指定维护者信息

RUN

格式为RUN commandRUN ["EXECUTABLE","PARAM1","PARAM2".....]
前者在shell终端中运行命令,/bin/sh -c command,例如:/bin/sh -c "echo hello"
后者使用exec执行,指定其他运行终端使用RUN["/bin/bash","-c","echo hello"]
每条RUN指令将当前的镜像基础上执行指令,并提交为新的镜像,命令较长的时候可以使用\来换行。

CMD

支持三种格式:
CMD ["executable","param1","param2"],使用exec执行,这是推荐的方式。
CMD command param1 param2 在/bin/sh中执行。
CMD ["param1","param2"] 提供给ENTERYPOINT的默认参数。
CMD用于指定容器启动时执行的命令,每个Dockerfile只能有一个CMD命令,多个CMD命令只执行最后一个。若容器启动时指定了运行的命令,则会覆盖掉CMD中指定的命令。

EXPOSE

格式为 EXPOSE port [port2,port3,...],例如EXPOSE 80这条指令告诉Docker服务器暴露80端口,供容器外部连接使用。
在启动容器的使用使用-P,Docker会自动分配一个端口和转发指定的端口,使用-p可以具体指定使用哪个本地的端口来映射对外开放的端口。

ENV

格式为:EVN key value 。用于指定环境变量,这些环境变量,后续可以被RUN指令使用,容器运行起来之后,也可以在容器中获取这些环境变量。
例如
ENV word hello
RUN echo $word

ADD

格式:ADD src dest
该命令将复制指定本地src目录中的文件到容器中的dest中,原路径可以是是一个绝对路径,也可以是一个URL或一个tar文件,tar文件会自动解压为目录。

  • (1)如果源路径是个文件,且目标路径是以 / 结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下。
    如果目标路径不存在,则会自动创建目标路径。
  • (2)如果源路径是个文件,且目标路径是不是以 / 结尾,则docker会把目标路径当作一个文件。
    如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件;
    如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。
    如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。
  • (3)如果源路径是个目录,且目标路径不存在,则docker会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。
    如果目标路径是个已经存在的目录,则docker会把源路径目录下的文件拷贝到该目录下。
  • (4)如果源文件是个归档文件(压缩文件,比如 .tar文件),则docker会自动帮解压。但是.tar.gz文件是不会自动解压的。

COPY

格式为:COPY src dest
复制本地主机src目录或文件到容器的dest目录,dest不存在时会自动创建。
COPY指令只能从执行docker build所在的主机上读取资源并复制到镜像中,而ADD指令还支持通过URL从远程服务器读取资源并复制到镜像中。
COPY指令不会自动解压归档文件(压缩文件)。

ENTRYPOINT

格式有两种:
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1,param2 会在shell中执行。
用于配置容器启动后执行的命令,这些命令不能被docker run提供的参数覆盖。和CMD一样,每个Dockerfile中只能有一个ENTRYPOINT,当有多个时最后一个生效。

VOLUME

格式为 VOLUME ["/data"]
作用是创建在本地主机或其他容器可以挂载的数据卷,用来存放数据。

USER

格式为:USER username
指定容器运行时的用户名或UID,后续的RUN也会使用指定的用户。要临时使用管理员权限可以使用sudo。在USER命令之前可以使用RUN命令创建需要的用户。
例如:RUN groupadd -r docker && useradd -r -g docker docker

WORKDIR

格式: WORKDIR /path
为后续的RUN CMD ENTRYPOINT指定配置工作目录,可以使用多个WORKDIR指令,若后续指令用得是相对路径,则会基于之前的命令指定路径。

ONBUILD

格式ONBUILD [INSTRUCTION]
该配置指定当所创建的镜像作为其他新建镜像的基础镜像时所执行的指令。
例如下面的Dockerfile创建了镜像A:
ONBUILD ADD . /app
ONBUILD RUN python app.py
则基于镜像A创建新的镜像时,新的Dockerfile中使用from A 指定基镜像时,会自动执行ONBBUILD指令内容,等价于在新的要构建镜像的Dockerfile中增加了两条指令:
FROM A
ADD ./app
RUN python app.py

posted @ 2021-07-21 01:56  Ye'sBlog  阅读(205)  评论(0编辑  收藏  举报