您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Dockerfile 指令详解

在上一节的 Dockerfile 例子中,我们用到了几个指令,比如:FROM, MAINTAINER,RUN,EXPOSE等等,Dockerfile 构建镜像需要用到的指令当然不止这些,下面是我们将介绍常用的构建指令 。

FROM <基础镜像:版本>

示例:

FROM alpine:latest

写上这一行指令后,我们的 Dockerfile 就可以构建镜像了,构建出的镜像就是未做任何、没有执行任何命令的 alpine:latest

在 Docker 官方仓库里有很多高质量的服务镜像如 redis、mongo、、httpd、、tomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 node、openjdk、python、ruby、golang 等。我们可以在其中寻找最符合我们最终目标的镜像为基础镜像进行定制。如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如 ubuntu、debian、centos、fedora、alpine 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。尽可能使用当前官方仓库作为构建镜像的基础。

给镜像来镜像信息,每个一行。

:

LABEL <>=<描述>

示例:

LABEL MYLABEL="First Test"

MAINTAINER <NAME>

示例:

MAINTAINER nickname@domain.com

这是一种语义化的表达方式,也可以用LABEL来

LABEL maintainer="nickname@domain.com"

RUN <命令>

示例:

RUN echo 'text' > test.txt

为了保持 Dockerfile 的可读性,以及可维护性,建议将长的或复杂的RUN指令用反斜杠\分割成多行。

例如:

RUN apt update && apt install -y \
      vim \
      emacs

这里需要注意关于软件源更新安装软件的问题。

如果我们需要更新软件源并安装软件源中的软件vim,在Linux环境中我们一般会执行这个的命令:

apt update
apt install -y vim

如果需要在镜像中安装软件,我们会想当然地在 Dockerfile 写成这样

RUN apt update
RUN apt install -y vim

Dockerfile 构建一次之后,apt update 构建的镜像层就会缓存到本地,无论后面这个 Dockerfile 如何更新 apt install 的,apt update 镜像缓存也不会更新,这会导致安装的始终是第一次 Dockerfile构建时的软件源版本,除非你手动这些缓存镜像层。

的很简单,用 RUN apt-get update && apt-get install -y 可以确保 Dockerfiles 每次安装的都是包的最新的版本。

建议:

CMD ["可执行命令", "参数1", "参数2"...]

示例:

CMD ["echo" "hello"]

docker run 没有指定其他命令时,CMD 指令会在容器执行。Dockerfile 中 CMD 只能有,如果写了多个 CMD,则以最后为准。

Tips:ENTRYPOINT 与 CMD 类似,但不会被 docker run 指定的命令覆盖。

EXPOSE 端口号

示例:

EXPOSE 8080

启动容器时,如果我们使用映射 -P--net=host 宿主机网络模式,容器中 EXPOSE 暴露的端口与宿主机网络会建立关联。

如果没有指定 EXPOSE,使用 -p 手动指定端口映射参数也可以访问到容器内提供服务的端口。

EXPOSE 显式地标明镜像开放端口,一定程度上提供了操作的便利,也提高了 Dockerfile 的可读性和可维护性。

ENV 环境变量名 环境变量值

示例:

ENV PATH /usr/local//bin:$PATH

Tips:

:

COPY <宿主机路径> <镜像路径>

示例:

COPY app.py  /web/

除了指定完整的名外,COPY 命令还 Go 风格的符,比如:

# * 是任意字符的占位符,匹配 test11 test22
COPY test* /tmp
# ? 是单个字符的占位符,匹配 test1.txt test2.txt
COPY test?.txt /tmp

对于目录而言,COPY 只复制目录中的而不包含目录自身。 如下目录结构:

testdir/
├── file1
└── file2
COPY testdir /tmp

镜像的 /tmp 目录下,将得到这样的结构:

tmp/
├── file1
└── file2

如果要带目录拷贝到镜像中,需要使用:

COPY testdir /tmp/testdir

ADDCOPY类似,一般优先使用 COPY。COPY 只简单将本地到容器中,而 ADD 还有从压缩包中的,如:

# 宿主机压缩包test.tar 解压到 镜像/tmp中
ADD test.tar /tmp

为了防止运行时忘记将需要保存数据的目录挂载为卷,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果不指定挂载,其应用也不会向容器存储层写入大量数据。

VOLUME ["<路径1>", "<路径2>"...] 

示例:

VOLUME ["/data"]

这里的 /data 目录就会在运行时挂载为匿名卷,容器运行时使用 -v mydata:/data 可以覆盖这个挂载设置。

USER <user>[:<group>]USER <UID>[:<GID>]

示例:

USER www

当容器中运行的服务不需要权限时,可以先建立特定的和组,为它分配必要的权限,然后通过该命令,使用 USER 切换到这个。

Tips:

我们可以在docker run中使用-u参数指定执行命令,来替代认设定,如果为了精确控制的id,也可以传入uid。

docker run -i -t -u 1001 busy@R_439_2@ sh

WORKDIR中需要使用,如果镜像中对应的路径不存在,会创建此目录。

我们使用 WORKDIR 来替代 RUN cd <path> && <do something>的这类切换目录进行操作的指令。

WORKDIR指令对ADD COPY等指令也生效,如下操作会将宿主机的test.txt 复制到 镜像的/tmp/test.txt。

WORKDIR /tmp
COPY test.txt .

ONBUILD <其他指令>

示例:

ONBUILD COPY . /tmp/

ONBUILD 是特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等。

FROM alpine:latest
ONBUILD RUN mkdir /app
ONBUILD COPY . /app/
CMD [ "echo", "hello" ]

使用上面 Dockerfile 在构建基础镜像的时候,这两行 ONBUILD 并不会被执行。它的等价于:

FROM alpine:latest
CMD [ "echo", "hello" ]

构建出来的镜像作为基础镜像,在其他 Dockerfile 的 FROM 指令中被引用,去构建新镜像的时候,ONBUILD 后的指令会执行。

本节介绍了我们使用 Dockerfile 构建镜像的过程中经常会用到的指令,这些指令大多简单易懂的。但本节中也提到,其中有些指令的比较特殊,在某些看似“理所当然”的使用下,可能会出现"bug",请大家一定要留意。后面也有实战章节,帮助大家加深理解。


联系我
置顶