本文会陆续更新Dockerfile的一些知识。
什么是Dockerfile?
Dockerfile可以理解为一个具备组装一个docker镜像的所有指令的文本文件。即docker可以通过Dockerfile来新建一个镜像(Image)。
Dockerfile中可使用的指令
注释
Dockerfile中通过#来写注释,如# 这是一行注释
大小写不敏感以及惯例
Dockerfile中是大小写不敏感的,即from指令相当于FROM指令。但惯例是指令为大写,参数为小写,如FROM nginx:1.24.0
ARG
ARG是唯一一个会出现在FROM指令前面的指令,并且其出现在第一个FROM指令之前,用来定义一些变量。其作用主要是用来接收构建时期命令行所传递过来的变量,如
ARG NGINX_VERSION=1.24.0
ARG OTHER_VARIABLE=variable
FROM nginx:${NGINX_VERSION}
这里当我们新建镜像的是时候就会以nginx:1.24.0为基础镜像。
但假如我们想在构建时期指定nginx版本。可以使用如下命令
此时NGINX_VERSION的值就变成了stable-alpine3.17-slim,如图
ARG定义的变量是处于构建阶段之外(即默认情况下,不能在FROM指令之外使用)。要在构建阶段内使用这些变量,需要使用不带值的ARG指令
如
ARG NGINX_VERSION=1.24.0
ARG OTHER_VARIABLE=variable
FROM nginx:${NGINX_VERSION}
ARG OTHER_VARIABLE
RUN echo $OTHER_VARIABLE > other_variable
的输出为
而
ARG NGINX_VERSION=1.24.0
ARG OTHER_VARIABLE=variable
FROM nginx:${NGINX_VERSION}
RUN echo $OTHER_VARIABLE > other_variable
的输出为
FROM
FROM指令用来指定一个新的构建阶段,语法如下
FROM [--platform=<platform>] <image> [AS <name>]
Or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
Or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
其中[]包裹的都为可选部分。<image>为镜像名。
-
如果省略
tag,则tag默认为lastest。 -
AS为该构建阶段命名,一个Dockerfile允许有多个FROM指令来表示多个构建阶段,一个新的构建阶段会清除其他构建阶段的状态,我们可以通过“构建阶段名”为引用构建阶段的状态。
如下
- 我们为第一阶段命名为builder,意味着打包阶段,一般情况下打包都会产出一个名为
dist的目录(这里指的是前端项目)。 - 在nginx构建阶段,我们想要复制该文件夹,需要在
COPY指令的--from参数加上第一阶段的构建名。
FROM node:18.16.0 AS builder
WORKDIR /app
COPY . .
RUN npm run build
FROM NGINX:stable-alpine
COPY --from=builder /app/dist/. /etc/nginx/html/
COPY
COPY 用来复制docker构建上下文(一般指docker build的根路径)的文件到容器中,其语法如下
COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]
其中src为源文件路径,dest为容器中的目标文件路径。当文件或目录为相对路径时,相对的是docker构建上下文。
COPY例子
- 添加所有以hom开头的文件到容器的/mydir/目录 COPY hom* /mydir/
- 假如想要复制hom开头,并且第四个字母为任意字符的任意文件时,可以使用以下命令
COPY home? /mydir/
3. 目标文件路径除了可以指定绝对路径在nginx为以/开头的路径,也可以指定相对路径,相对路径为相对WORKDIR的路径,如
COPY test.txt relativeDir/
WORKDIR
WORKDIR指令用来为出现在其后面的RUN,CMD,ENTRYPOINT,COPY,ADD指令指定工作目录,可以简单理解为为出现在其后的上述指令指定当前目录(如未指定过,默认值为linux系统的根目录/)。如果WORKDIR指定的目录不存在,甚至在后续没有指令用到该目录,系统也会自动创建该目录。如
ENV
可通过ENV指令添加环境变量。而可以通过$variable_name或者${variable_name}来获取定义的环境变量,两种获取变量的方式为等效的,如。
ENV指令允许同时添加多个,通过docker inspect可以查看某个镜像中环境变量的值,如
在运行该容器时,也可以通过docker run --env <key>=<value>选项进行修改
环境变量会存在于运行时期,因此可能造成一些意外的影响
如DEBIAN_FRONTEND=noninteractive变量会影响到apt-get的行为。因此涉及到可能会影响到操作系统的系统变量时候,可以使用RUN指令或者运行时变量ARG。如
RUN
RUN指令可以用来执行一些命令,并且会在当前的镜像中创建一个新的层,被添加的层会在Dockerfile的下一步被使用。简单来说可以使用RUN指令来执行一些构建阶段需要执行的脚本。
RUN语法
RUN指令可以通过两种exec格式或者shell格式运行(常用),如
RUN ["executable","param1","param2"](exec form)RUN command param1 param2(shell form)
RUN执行可通过转义符或"heredocs"来实现一个RUN执行执行多行
其中 <<EOF EOF 格式即为"heredocs"格式
RUN指令允许在构建阶段挂载文件,其用法为
RUN --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]
默认的type为bind。表示挂载到构建阶段的文件对构建容器来说是只读的。其选在有
-
target
绑定到容器的目标地址
-
source
源文件路径。默认是源镜像的根目录。
-
from
构建阶段或源的镜像名称。默认为构建上下文。
-
rw/readwrite
允许在挂载上进行写操作。写入的数据将被丢弃。
例子
RUN --mount=type=bind,source=./node_modules,target=./node_modules
表示将本地node_modules文件挂载到构建阶段当前工作路径(WORKDIR)的node_modules文件夹下