
我们除了通过 commit 的方式来构建 docker 镜像外,Dockerfile
是另一种构建镜像的方式。Dockerfile
是一个文本文件,里面包含了打包 docker 镜像所需要用到的所有命令,这样,docker 就可以通过读取 Dockerfile
里面的命令来自动化地构建 docker 镜像。相比于 commit,使用Dockerfile
的好处在于其生成镜像的方式更加透明,我们可以一目了然地知道这个镜像是如何一步步生成的,同时构建的镜像也相对较小,文本的形式也方便镜像的管理与复用。
使用 DockerFile 创建镜像
先来复习下,之前我们是如何通过docker commit
生成一个新镜像的:
具体过程见:我的 Docker 笔记
Step 1:首先,我们需要启动一个容器,当我们运行镜像并生成容器时,会在基础镜像的顶部添加新的可写层「容器层」;
Step 2:我们会对容器执行一些操作(比如安装软件)。我们对容器所做的所有更改都将写入此可写容器层,每一个操作都会在上面累加一层,每一层都是前一层变化的增量;
Step 3:执行 docker commit
来基于已有的容器创建一个新的镜像。

DockerFile
其实执行的是相同的步骤。第一步,我们需要使用FROM
命令指定一个基础镜像生成一个容器,然后用一些「镜像操作指令」对容器做一些修改。最后用docker build
命令来生成镜像。
Dockerfile常用指令
类型 | 命令 |
---|
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操作指令 |
RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器启动时执行指令 | CMD、ENTRYPOINT |
最简单的Dockerfile
比如这样:
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
意思就是,使用FROM
命令先从 ubuntu:18.04 基础镜像创建一个容器,接着用COPY
命令向容器中的/app
文件夹拷贝宿主机当前目录的文件,使用RUN
命令,执行make
安装软件。CMD
命令指定容器启动时需要执行的命令。
创建完 DockerFile,我们就可以使用docker build
来创建镜像了。
docker build -t test:v1.0 .
执行命令后,控制台会逐层输出构建内容,直到输出两个 Successfully 即为构建成功。
Successfully built 93a111d8c6e5
Successfully tagged test:v1.0
常用 Dockerfile 指令详解
FROM
指定创建镜像时的基础镜像。
FROM <image> [AS <name>
]
或者
FROM <image>[:<tag>] [AS <name>]
或者
FROM <image>@<digest> [AS <name>]
Dockerfile
的第一条命令必须为FROM
指令,其中 [AS ]
为指定一个名称。
RUN
RUN
指令用于执行命令(比如安装软件),每一次RUN
都会在之前的基础上产生新的一层,并把执行后的结果提交。因此,我们在使用 RUN
时应该尽可能的把要执行的命令一次写完,以减少最后生成的镜像层数,避免镜像过于臃肿。
RUN <command>
或者
RUN ["executable","param1","param2"]
为了把所有需要的命令写到一个RUN
中,我们通常需要用到换行符\
:
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
file \
git \
libapparmor1 \
libcurl4-openssl-dev \
libedit2 \
libssl-dev \
lsb-release \
multiarch-support \
psmisc \
procps \
python-setuptools \
sudo \
wget \
libclang-dev \
&& wget -O libssl1.0.0.deb http://ftp.debian.org/debian/pool/main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u8_amd64.deb \
&& dpkg -i libssl1.0.0.deb \
&& rm libssl1.0.0.deb \
&& if [ -z "$RSTUDIO_VERSION" ]; then RSTUDIO_URL="https://www.rstudio.org/download/latest/stable/server/debian9_64/rstudio-server-latest-amd64.deb"; else RSTUDIO_URL="http://download2.rstudio.org/rstudio-server-${RSTUDIO_VERSION}-amd64.deb"; fi \
&& wget -q $RSTUDIO_URL \
&& dpkg -i rstudio-server-*-amd64.deb \
ADD
ADD
可以复制新文件,目录,远程文件到容器中。其中
可以为文件(要复制的文件必须和Dockerfile
位于同一目录下),目录,URL;
可以是镜像内绝对路径,或者相对于工作目录的相对路径。
ADD <src>... <dest>
COPY
COPY
与 ADD
的功能十分类似,但 COPY
只支持本地的文件以及目录的复制,不像 ADD
指令可以远程获取文件并解压。
COPY <src> <dest>
CMD
指定启动容器时默认执行的命令。
CMD command param1 param2
或者
CMD ["executable","param1","param2"]
每个Dockerfile
中只能有一条CMD
命令,如果指定了多条命令,只有最后一条被执行,如果用户启动容器时手动指定了运行的命令,则会覆盖掉CMD
指定的命令。比如设置在容器启动时进入 bash。
CMD /bin/bash
# 或者
CMD ["/bin/bash"]
MAINTAINER
MAINTAINER
用于指定作者。
MAINTAINER <name>
<email>
EXPOSE
EXPOSE
指令用于告诉 Docker 容器监听的特殊端口,但是此时端口还没有暴露给宿主机,只有在运行容器用参数-p
时才会暴露端口。
EXPOSE <port> [<port>/<protocol>...]
WORKDIR
WORKDIR
命令用于设置 RUN
, CMD
, ENTRYPOINT
, COPY
, ADD
等指令的工作目录,类似cd
的意思,进入目录。
WORKDIR /path/to/workdir
ENTRYPOINT
ENTRYPOINT
的作用和CMD
一样,但这个命令会在启动容器时作为根命令执行,不会被覆盖。
ENTRYPOINT command param1 param2
ENTRYPOINT ["executable","param1","param2"]
LABEL
用于为镜像指定标签,可用 docker inspect
命令查看,用来镜像以后被搜索的时候用。
LABEL <key>=<value> <key>=<value> ...
VOLUME
VOLUME
指令用于为容器创建一个挂载点,这个挂载点可以用来挂载 本地文件/文件夹
也可以用来挂载 数据卷
。其中若在启动一个新容器时没有指定挂载目录,则会自动创建一个数据卷,当容器被销毁时,数据卷如果没有被其它容器引用则会被删除。
VOLUME ["/data1","/data2"]
USER
指定运行容器的用户以及用户组。默认为 root
用户,所以当服务不需要管理员权限时,可以通过该命令指定运行用户。
USER [:]
ENV
ENV
指令用于设定环境变量,容器运行的时候这个变量也会保留。
ENV <key> <value> 或 ENV <key>=
<value> ...
这些环境变量可以在运行时被docker run --env =
覆盖掉。
ARG
定义创建镜像过程中使用的变量。
ARG [=<default value>]
在执行docker build
时,也可以通过-duild-arg[=]
来为变量赋值;镜像编译成功之后,ARG
指定的变量不再存在(ENV
指定的仍然在镜像中保留)。
参考
号外:(南京、南宁见!)全国巡讲第17-18站(生信入门课加量不加价)