使用Docker Build构建镜像

发布时间 2024-01-11 17:57:16作者: biiigwang

使用Docker Build构建镜像

使用Docker Build工具可以按照自己的需求构建镜像,可以方便的部署应用程序。

环境

  • 命令行工具:docker build​,该工具随docker一起安装

语法

详细的语法可以阅读官方文档菜鸟教程,以上文档均有详细教程,我将对其中的常用语法进行介绍,同时讲一讲运行时可能遇见的坑

总览

指令详解

Dockerfile 指令 说明
FROM 指定基础镜像,用于后续的指令构建。
MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 在构建过程中在镜像中执行命令。
CMD 指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL复制到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

格式

docker file文件有要求,需要命名为Dockerfile​,文件中命令大小写不敏感,习惯上用大写书写命令

上下文路径

我们需要理解上下文路径的概念,引用菜鸟RUNOOB的介绍

上一节中,有提到指令最后一个.​ 是上下文路径,那么什么是上下文路径呢?

$ docker build -t nginx:v3 .

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

FROM

FROM <镜像名>

该命令为文件的首行内容,表示我们的镜像基于什么镜像进行构建

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

格式:

WORKDIR /path/to/workdir

// 设置工作路径为/workspace

WORKDIR /workspace

COPY

相似的命令为ADD

使用该命令需要理解build命令中的上下文路径概念,我们

格式:

// 复制文件

// 举例:将main.py拷贝至/workspace/
COPY main.py /workspace/


//复制文件夹

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[--chown=<user>:<group>] :可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径> :源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径> :容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

⚠️注意:

再是复制路径时,比如./dir​文件夹,文件夹中存在file1​,file2​文件,文件结构如下所示:

dir/
├── file1
└── file2

我们使用COPY ./dir /workspace/​后,他不会复制最顶级的目录,最终效果为:

/workspace/
├── file1
└── file2

如果希望保留文件结构,需要在命令中的目标路径中多添加一级顶级目录``COPY ./dir /workspace/dir/`​

ARG

构建参数,与 ENV ​作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

// 格式
ARG <参数名>[=<默认值>]


// Dockerfile
...
ARG HTTPS_PROXY=http://proxy-server-url:port
...

// Terminal
Docker build -t . --build-arg=http://other-proxy-server-url:port

RUN

RUN:用于执行后面跟着的命令行命令。有以下俩种格式:

shell 格式:

RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

⚠️注意:

构建中每多一句RUN就会在镜像中多加入一层操作,为了防止最后构建的镜像过于臃肿,我们可以尽可能的将多行命令使用&&​符号将多条命令连接,比如:

RUN pip config set global.index-url $PYPI_INDEX_URL && \
    pip3 install -r ./iMaoTai-reserve/requirements.txt

CMD

相似的命令为ENTRYPOINT

用于指定启动具体的容器时,默认执行的命令,可以在docker run​时指定command​时覆盖

ENTRYPOINT​指定的命令无法被覆盖,可以在docker run​时指定--entrypoint​来覆盖

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 

1、不传参运行

$ docker run  nginx:test

容器内会默认运行以下命令,启动主进程。

nginx -c /etc/nginx/nginx.conf

2、传参运行

$ docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

nginx -c /etc/nginx/new.conf