本文介绍Dockerfile相关的知识。
一、概述
Dockerfile是构建docker镜像的文件,该文件描述了如何构建docker镜像。有其的语法和使用方式,注释使用“#”。
在实际使用中,可以基于官方或其它镜像,再进行创建。
Dockerfile分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
例如:
1 | #这里说明基础镜像信息 |
大部分Dockerfile都有这几部分组成。Dockerfile学习起来不容易,但也不困难,在了解基本概念后,最好的方法是阅读官方的Dockerfile文件。列举几个如下:
1 | busybox:https://github.com/docker-library/busybox/blob/4b11c30f87d3033b2abd446c9bc1ef12f96abaa0/uclibc/Dockerfile (仅三行,可从此入手实践) |
笔者也积累了一些,有兴趣可以参考:https://github.com/latelee/dockerfile。
二、指令说明
指令的一般格式为<指令> <参数>
,指令包括FROM、MAITNTAINER、RUN等,简列如下:
1 | FROM 指定所创建镜像的基础镜像 |
下面分别进行介绍。
FROM
功能为指定基础镜像,并且必须是第一条指令。如果本地镜像不存在或者镜像仓库中不存在,则回去DockerHub下载指定镜像。 如果在同一个Dockerfile中创建多个镜像,可以使用多个FROM指令(每个镜像一次)。
语法:
1 | FROM <image> |
三种写法,其中
RUN
功能为运行指定的命令。
语法:
1 | RUN <command> |
第一种后边直接跟shell命令,在linux操作系统上默认为/bin/sh –c
。
第二种是类似于函数调用。可将executable理解成为可执行文件,后面就是两个参数。
示例:
1 | RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME |
注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层。
多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。
RUN命令较长书写较长时可以使用换行符\
。示例:
1 | RUN apt-get update \ |
CMD
功能为容器启动时要运行的命令。
语法:
1 | CMD ["executable","param1","param2"] |
每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。用户在启动容器时手动指定了运行的命令,则会覆盖CMD指定的命令。
示例:
1 | CMD [ "sh", "-c", "echo $HOME" |
补充细节:这里边包括参数的一定要用双引号,就是”,不能是单引号。千万不能写成单引号。
LABEL
功能是为镜像指定生成镜像的元数据标签信息。
语法:
1 | LABEL <key>=<value> <key>=<value> <key>=<value> ... |
示例:
1 | LABEL "com.example.vendor"="ACME Incorporated" |
说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖。
MAINTAINER
功能指定作者
语法:
1 | MAINTAINER <name> |
示例:
1 | MAINTAINER "li@latelee.org" |
该信息会写入生成镜像的Author属性域中。
EXPOSE
功能为暴漏容器运行时的监听端口给外部。
语法:
1 | EXPOSE <PORT> [<PORT>…] |
示例:
1 | EXPOSE 22 80 443 |
注意,该指令只是起到声明作用,并不会自动完成端口映射,需要在启动容器时加-p。
ENV
功能为设置环境变量
语法:
1 | ENV <key> <value> |
示例:
1 | ENV PATH /usr/local/bin:$PATH |
ADD
功能把文件复制到镜像中。
如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用。
语法:
1 | ADD <src>... <dest> |
<dest>
路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径<src>
可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
如果把<src>
写成一个url,那么ADD就类似于wget命令
示例:
1 | ADD test relativeDir/ |
尽量不要把<scr>
写成一个文件夹,如果<src>
是一个文件夹了,复制整个目录的内容,包括文件系统元数据
COPY
功能把文件复制到镜像中。
语法:
1 | COPY <src>... <dest> |
与ADD的区别,COPY的<src>
只能是本地文件,其他用法一致
ENTRYPOINT
功能是启动时的默认入口命令。该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。
语法:
1 | ENTRYPOINT ["executable", "param1", "param2"] |
只能写一条,如果写了多条,那么只有最后一条生效。
VOLUME
功能可以将文件夹或者其他容器中的文件夹挂在到这个容器中。
语法:
1 | VOLUME ["/data"] |
说明:["/data"]
可以是一个JsonArray ,也可以是多个值。
例如:
1 | VOLUME ["/var/log/"] |
一般的使用场景为需要持久化存储数据时,当数据需要持久化时用这个命令。
USER
功能设置启动容器的用户,可以是用户名或UID。
语法:
1 | USER daemo |
注意:如果设置了容器以daemon用户去运行,那么RUN、CMD和ENTRYPOINT都会以这个用户去运行
WORKDIR
功能为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。
语法:
1 | WORKDIR /path/to/workdir |
如果不存在则会创建,也可以设置多次。
示例:
1 | WORKDIR /a |
pwd执行的结果是/a/b/c
WORKDIR也可以解析环境变量。
示例:
1 | ENV DIRPATH /path |
pwd的执行结果是/path/$DIRNAME
ARG
功能指定镜像内使用的参数(版本号信息等)。
语法:
1 | ARG <name>[=<default value>] |
设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value>
来指定参数。
示例:
1 | FROM busybox |
三、创建镜像
编写完成Dockerfile之后,可以通过docker build
命令来创建镜像。
语法:
1 | docker build [OPTIONS] PATH | URL | - |
示例:
1 | #docker build –t ubuntu:v1 . |
注意:命令后面的点号表示当前路径,默认文件名称为Dockerfile,如果不是这个名称,需要手动指定,但一般都用默认的。