Docker进阶之Dockerfile
Docker进阶之Dockerfile
Dockerfile
是一个文本格式的配置文件,我们可以使用Dockerfile来快速创建自定义的镜像。Dockerfile
内部包含了一条条的指令,每一条指令构建一层,因此每一条指令应当描述该层如何构建。层越多,效率越低,因此,创建镜像,层越少越好
Dockerfile
结构大致分为四个部分:
- 基础镜像信息
- 维护者信息
- 构建镜像的指令信息
- 容器启动时执行指令信息
1.Dockerfile常用指令
Dockerfile
指令通常是以大写形式书写
1.1 FROM
使用Dockerfile定制镜像,那么一定需要以一个镜像为基础,在其上进行定制,因此我们需要指定一个基础镜像,而FROM
指令就是指定基础镜像,并且该指令必须是Dockerfile
的第一条指令。
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM ubuntu:latest AS my-ubuntu
FROM
可以在Dockerfile
中出现多次,以创建多个镜像,或者将一个构建阶段用作是另一个构建阶段的依赖项。AS <name>
指定的名称可以在后续构建阶段使用,例如COPY --from=<name>
。在默认情况下,--platform
使用的当前构建请求的平台。
1.2 RUN
RUN <command>
command为shell命令
RUN ["executable", "param1", "param2"]
executable为可执行程序,param1,param2分别为参数
RUN apt-get update
RUN ["apt-get","update"]
RUN
指令会在当前镜像创建一个新层,并且将执行结果提交.
1.3 CMD
CMD ["executable","param1","param2"]
(首选形式)
CMD ["param1","param2"]
(作为ENTRYPOINT的默认参数)
CMD command param1 param2
(shell命令形式)在
Dockerfile
中,只能有一条CMD
指令,如果出现多个CMD
命令,则只有最后一个命令会生效。我们使用CMD
指令指定容器运行时要执行的命令以及提供默认参数。如果我们指定Docker运行时的参数,CMD
指令中默认参数可以被覆盖。
注意:CMD指令在镜像构建时不会执行任何操作。
1.4 LABEL
LABEL <key>=<value> <key>=<value> <key>=<value>
LABEL
指令可以为镜像添加元数据。我们可以使用LABEL
指令来添加镜像的作者信息等
1.5 EXPOSE
EXPOSE <port> [<port>/<protocol>...]
EXPOSE 8080
EXPOSE 8080/TCP
EXPOSE
指令通知Docker容器在运行时监听指定的网络端口,可以指定端口的协议(TCP/UDP),如果不指定默认为TCP协议
1.6 ENV
ENV <key>=<value> ...
ENV version=1.0 name=test
ENV
指令可以设置环境变量,设置的环境变量可以在后续的构建阶段中使用
1.7 ADD
ADD [--chown=<user>:<group>] <src>... <dest>
ADD test.txt /mydir/
ADD test/ /mydir/
ADD
指令可以从<src>
将文件、文件夹、远程文件地址复制并添加到镜像文件系统的指定位置<dest>
。
- 如果
<src>
是一个文件,则该文件必须是在构建上下文中,因为docker
构建的第一步就是讲上下文目录以及子目录
发送到docker守护进程中,docker默认会在上下文目录的根目录去找Dockerfile
文件。如果是一个可识别的压缩文件
,复制之后将会被自动解压
。 - 如果
<src>
是一个url且末尾不带/
,则会将文件下载并复制到<dest>
路径下。 - 如果
<src>
是一个url且末尾带/
,则会推断文件名并将文件下载并复制到<dest>/<filename>
路径下。 - 如果
<src>
是一个文件夹,该目录下所有的文件将会被复制(不包括文件夹
) <dest>
可以是相对路径、绝对路径,如果不存在,将会默认创建- 如果
<dest>
末尾不带/
,其将会被视为一个常规文件,<src>
的内容将会被复制并写入<dest>
。例如:COPY a.txt b.txt
1.8 COPY
COPY [--chown=<user>:<group>] <src>... <dest>
# 复制文件到镜像中相对路径
COPY test.txt relativeDir/
# 复制文件到镜像中绝对路径
COPY test.txt /absoluteDir/
注意:COPY
指令可以使用--from<name>
参数,该参数将使用上一构建阶段,例如FROM ubuntu:latest AS my-ubuntu
- 如果
<src>
是一个文件,则该文件必须是在构建上下文中,因为docker
构建的第一步就是讲上下文目录以及子目录
发送到docker daemon中,docker默认会在上下文目录的根目录去找Dockerfile
文件。 <dest>
可以是相对路径、绝对路径,如果不存在,将会默认创建。- 如果
<dest>
末尾不带/
,其将会被视为一个常规文件,<src>
的内容将会被复制并写入<dest>
。例如:COPY a.txt b.txt
1.9 ENTRYPOINT
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
Docker运行时,可以使用--entrypoint
来覆盖ENTRYPOINT
指令。Dockerfile中如果出现多个ENTRYPOINT
指令,则只有最后一个生效。如果不使用--entrypoint
参数,Docker运行时,由ENTRYPOINT
启动的程序不会被docker run命令指定的参数所覆盖,而是将这些参数传递给由ENTRYPOINT
启动的程序。
1.10 VOLUME
VOLUME ["/data"]
Docker运行会在宿主机生成数据卷并挂载VOLUME
指令指定的位置。
1.11 WORKDIR
WORKDIR /path/to/workdir
WORKDIR
指令为任意的RUN、CMD、ENTRYPOINT、ADD、COPY
指令设置工作目录
。如果指定的目录不存在,将会被默认创建。
-
WORKDIR
指令在Dockerfile中可以多次使用,如果使用了相对路径,则后续路径会上一条的路径相对,例如:WORKDIR /aa WORKDIR bb WORKDIR cc RUN pwd # pwd命令的输出路径将为/aa/bb/cc
-
WORKDIR
指令,可以使用Dockerfile中显示设置的环境变量ENV DIRPATH=/path WORKDIR $DIRPATH/$DIRPATH2 RUN pwd #pwd输出的路径为/path/$DIRPATH2,因为$DIRPATH2无法被识别
1.12 ARG
ARG <name>[=<default value>]
ARG
指令定义了一个变量,构建镜像时,可以使用--build-arg <varname>=<value>
将该变量传递给构建器。
2.使用Dockerfile构建项目镜像
上下文目录
:发出docker build
指令所在目录就是上下文目录。默认情况下,docker会在当前目录中寻找Dockerfile
文件,我们也可以使用-f
参数来指定Dockerfile的位置。无论Dockerfile
处于什么位置,上下文目录以及子目录的所有内容都会被发送到Docker daemon中。
-
我们创建一个SpringBoot应用
-
在pom.xml中配置
Spring Boot Maven Plugin
插件,并开启分层<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layers> <enabled>true</enabled> </layers> </configuration> </plugin> </plugins> </build>
-
使用分层特性创建优化的Docker Image
-
使用配置好的Dockerfile进行构建,假设Dockerfile在当前文件夹下,使用
docker build .
进行构建。
Dockerfile如下:
# 指定基础镜像,这是分阶段构建的前期阶段
FROM openjdk:11-jre as builder
# 执行命令的工作目录
WORKDIR apps
# 配置参数
ARG JAR_FILE=target/*.jar
# 将编译构建得到的jar文件复制到镜像空间中
COPY ${JAR_FILE} application.jar
# 通过工具spring-boot-jarmode-layertools从application.jar中提取拆分后的构建结果
RUN java -Djarmode=layertools -jar application.jar extract
# 正式构建镜像
FROM openjdk:11-jre
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
WORKDIR apps
# 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer
COPY --from=builder apps/dependencies/ ./
COPY --from=builder apps/spring-boot-loader/ ./
COPY --from=builder apps/snapshot-dependencies/ ./
COPY --from=builder apps/application/ ./
ENTRYPOINT java ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher
参考链接:https://docs.spring.io/spring-boot/docs/current/reference/html/container-images.html#container-images
更多推荐
所有评论(0)