使用Docker Build构建镜像
使用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
举个
FROM python:3.10-bullseye
WORKDIR /workspace
COPY ./myproject /workspace/myproject
ARG PYPI_INDEX_URL https://pypi.org/simple
RUN pip config set global.index-url $PYPI_INDEX_URL && \
pip3 install -r ./myproject/requirements.txt
CMD ["python3", "./myproject/main.py"]
使用ARG
指定pypi源的路径,方便在构建时指定国内源来加速构建过程