Dockerfile命令大全

为何要写这一篇呢?其实在之前的文章docker 学习笔记中没有展开讲,我们都知道使用docker build命令或使用Docker Hub的自动构建功能构建Docker镜像时,都需要一个Dockerfile文件。Dockerfile文件是一个由一系列构建指令组成的文本文件,docker build命令会根据这些构建指令完成Docker镜像的构建。

目录

1. FROM

2. RUN

3. CMD

4. ENTRYPOINT

5. LABEL

6. EXPOSE

7. ENV

8. ADD

9. COPY

10. VOLUME

11. USER

12. WORKDIR

13. ARG

14. ONBUILD

15. STOPSIGNAL

16. SHELL


构建上下文

docker build命令会根据Dockerfile文件及上下文构建新Docker镜像。

构建上下文是指Dockerfile所在的本地路径或一个URLGit仓库地址)。构建上下文环境会被递归处理,所以,构建所指定的路径还包括了子目录,而URL还包括了其中指定的子模块。

构建镜像的运行环境

构建会在Docker后台守护进程(daemon)中执行,而不是CLI中。

构建前,构建进程会将全部内容(递归)发送到守护进程。大多情况下,应该将一个空目录作为构建上下文环境,并将Dockerfile文件放在该目录下。

在构建上下文中使用的Dockerfile文件,是一个构建指令文件。为了提高构建性能,可以通过.dockerignore文件排除上下文目录下,不需要的文件和目录。

后台守护进程首先会对Dockerfile进行语法检查,有语法错误时会返回,通过后才会执行!

缓存

Docker 守护进程会一条一条的执行Dockerfile中的指令,而且会在每一步提交并生成一个新镜像,最后会输出最终镜像的ID。生成完成后,Docker 守护进程会自动清理你发送的上下文。

Dockerfile文件中的每条指令会被独立执行,并会创建一个新镜像,RUN cd /tmp等命令不会对下条指令产生影响。Docker 会重用已生成的中间镜像,以加速docker build的构建速度。

构建缓存仅会使用本地父生成链上的镜像。如果不想使用本地缓存的镜像,也可以通过--cache-from指定缓存。指定后将再不使用本地生成的镜像链,而是从镜像仓库中下载。

以下是一个使用了缓存镜像的执行过程(Using cache):

$ docker build -t svendowideit/ambassador .
Sending build context to Docker daemon 15.36 kB
Step 1/4 : FROM alpine:3.2
 ---> 31f630c65071
Step 2/4 : MAINTAINER [email protected]
 ---> Using cache
 ---> 2a1c91448f5f
Step 3/4 : RUN apk update &&      apk add socat &&        rm -r /var/cache/
 ---> Using cache
 ---> 21ed6e7fbb73
Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh
 ---> Using cache
 ---> 7ea8aef582cc
Successfully built 7ea8aef582cc

Dockerfile文件格式

  • Dockerfile文件中指令不区分大小写,但为了更易区分,约定使用大写形式
  • 由于指令会依次执行,文件中的第一条指令必须是FROMFROM指令用于指定一个基础镜像
  • #开头的行,Docker会认为是注释。但#出现在指令参数中时,则不是注释。

# 注释
指令 参数

# Comment
RUN echo 'we are running some # of cool things'

下面将开始介绍本文的重点内容,Dockerfile中使用指令。

1. FROM

FROM指令用于指定其后构建新镜像所使用的基础镜像。FROM指令必是Dockerfile文件中的首条命令,启动构建流程后,Docker将会基于该镜像构建新镜像,FROM后的命令也会基于这个基础镜像。

FROM
FROM :
FROM :

tagdigest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像

2. RUN

RUN用于在镜像容器中执行命令,RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。其有以下两种命令执行方式:

  • shell执行,在这种方式会在shell中执行命令,Linux下默认使用/bin/sh -c,Windows下使用cmd /S /C。格式:RUN
  • exec执行,格式:RUN ["executable", "param1", "param2"]

也可以在同一行中,通过分号分隔命令:

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

3. CMD

CMD用于指定在容器启动时所要执行的命令。CMD在Dockerfile文件中仅可指定一次,指定多次时,会覆盖前的指令。

另外,如果docker run运行容器时,使用了Dockerfile中CMD相同的命令,就会覆盖Dockerfile中的CMD命令。比如:Dockerfile文件中使用CMD ["/bin/bash"],运行时指令$sudo docker run -i -t itbilu/test 就会发生覆盖。

如果不想使用CMD中指定的命令,就可以在docker run命令的结尾指定所要运行的命令:$sudo docker run -i -t itbilu/test /bin/ps,这时,docker run结尾指定的/bin/ps命令覆盖了Dockerfile的CMD中指定的命令。

CMD有以下三种格式:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

CMD和RUN

CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。但功能实现上也有相似之处:

docker run -t -i itbilu/static_web_server /bin/true
等价于:
cmd ["/bin/true"]

4. ENTRYPOINT

ENTRYPOINT用于给容器配置一个可执行程序。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。也就是说,每次使用镜像创建容器时,通过ENTRYPOINT指定的程序都会被设置为默认程序。ENTRYPOINT有以下两种形式:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

ENTRYPOINTCMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINTdocker run运行容器时指定的参数都会被传递给ENTRYPOINT,且会覆盖CMD命令指定的参数。如,执行docker run -d时,-d参数将被传递给入口点。也可以通过docker run --entrypoint重写ENTRYPOINT入口点。比如:Dockerfile中有ENTRYPOINT ["/usr/bin/nginx"],运行时$sudo docker run -i -t  itbilu/test -g "daemon off;",最终在容器中执行的命令为/usr/sbin/nginx -g "daemon off;"

5. LABEL

LABEL用于为镜像添加元数据,元数以键值对的形式指定,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔:LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"

推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

注:Dockerfile中还有个MAINTAINER命令,该命令用于指定镜像作者。但MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者。如:LABEL maintainer="itbilu.com"

6. EXPOSE

EXPOSE用于指定容器在运行时监听的端口:EXPOSE [...] 。EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口。

7. ENV

ENV用于设置环境变量,其有以下两种设置形式:

ENV
ENV = ...

这些环境变量不仅可以构建镜像过程(在ENV命令之后)使用,使用该镜像创建的容器中也可以使用。

ENV ITBILU_PATH /home/itbilu/
WORKERDIR $ITBILU_PATH
$ docker run -i -t  itbilu/test 
root@196ca123c0c3:/# cd $ITBILU_PATH
root@196ca123c0c3:/home/itbilu# 

8. ADD

ADD用于复制构建环境中的文件或目录到镜像中。是源文件位置可以是一个构建上下文中的文件或目录,也可以是一个URL,但不能访问构建上下文之外的文件或目录,来指定目标位置。其有以下两种使用方式:

ADD ...
ADD ["",... ""]

ADD http://wordpress.org/latest.zip $ITBILU_PATH,$ITBILU_PATH是我们使用ENV指定的一个环境变量。

9. COPY

COPY同样用于复制构建环境中的文件或目录到镜像中。COPY指令非常类似于ADD,不同点在于COPY只会复制构建目录下的文件,不能使用URL也不会进行解压操作。其有以下两种使用方式:

COPY ...
COPY ["",... ""]

10. VOLUME

VOLUME用于创建挂载点,即向基于所构建镜像创始的容器添加卷:VOLUME ["/data"]。一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

  • 卷可以容器间共享和重用
  • 容器并不一定要和其它容器共享卷
  • 修改卷后会立即生效
  • 对卷的修改不会对镜像产生影响
  • 卷会一直存在,直到没有任何容器在使用它

VOLUME让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。运行容器时,需-v参将能本地目录绑定到容器的卷(挂载点)上,以使容器可以访问宿主机的数据。

ENV ITBILU_PATH /home/itbilu/
VOLUME [$ITBILU_PATH]
$ sudo docker run -i -t -v ~/code/itbilu:/home/itbilu/  itbilu/test 
root@31b0fac536c4:/# cd /home/itbilu/
root@31b0fac536c4:/home/itbilu# ls

11. USER

USER用于指定运行镜像所使用的用户,用户可以使用用户名、UIDGID,或是两者的组合。

使用USER指定用户后,Dockerfile中其后的命令RUNCMDENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

12. WORKDIR

WORKDIR用于在容器内设置一个工作目录,通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUNCMDENTRYPOINTADDCOPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

pwd最终将会在/a/b/c目录中执行

13. ARG

ARG用于指定传递给构建运行时的变量,

ARG site
ARG build_user=IT笔录
$sudo docker build --build-arg site=itiblu.com -t itbilu/test .

以上我们指定了sitebuild_user两个变量,其中build_user指定了默认值。在使用docker build构建镜像时,可以通过--build-arg =参数来指定或重设置这些变量的值

14. ONBUILD

ONBUILD用于设置镜像触发器,当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发。

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

15. STOPSIGNAL

STOPSIGNAL用于设置停止容器所要发送的系统调用信号:STOPSIGNAL signal。所使用的信号必须是内核系统调用表中的合法的值,如:9SIGKILL

16. SHELL

SHELL用于设置执行命令(shell式)所使用的的默认shell类型:SHELL ["executable", "parameters"]SHELL在Windows环境下比较有用,Windows下通常会有cmdpowershell两种shell,可能还会有sh。这时就可以通过SHELL来指定所使用的shell类型:

FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello

总结

Dockerfile是由一系列命令参数组成的一个文件。其中,每条件命令都要大写(如:FROM),且其后都要跟一个参数(如:ubuntu:16.04)。构建镜像时,Dockerfile中的命令会按顺序从上到下执行,在编写Dockerfile文件时应注意各条命令的顺序安排。Dockerfile文件中的每条命令,都会创建一个新的镜像层并会提交镜像。

你可能感兴趣的:(#,docker,k8s)