Docker 可以通过读取来自 Dockerfile。Dockerfile 是一个文本文档,其中包含用户可以在命令行上调用以组装镜像的所有命令。使用 docker build
用户可以创建一个连续执行多个命令行指令的自动构建。
1
2
|
# -f 指定 Dockerfile 路径 -t 打 tag 最后一个 . 是上下文路径
docker build -f Dockerfile -t ynthm/myapp .
|
CMD 与 ENTRYPOINT 命令区别
CMD指令和ENTRYPOINT指令的作用都是为镜像指定容器启动后的命令。
- CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖,ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
- CMD与ENTRYPOINT同时存在时,CMD指令可以为ENTRYPOINT指令设置默认参数,而且CMD可以被docker run指定的参数覆盖;
CMD
1
2
3
4
5
6
|
# 使用 exec 执行,推荐方式;
CMD ["executable","param1","param2"]
# shell中执行 ( /bin/sh ),提供给需要交互的应用;
CMD command param1 param2
# 注: 当Dockerfile内有ENTRYPOINT命令时,CMD命令会变成参数追加到ENTRYPOINT命令后;
CMD ["param1","param2"]
|
指定启动容器时执行的命令,每个 Dockerfile只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
ENTRYPOINT
1
2
3
4
|
# 使用 exec 执行,推荐方式;
ENTRYPOINT ["executable", "param1", "param2"]
# shell中执行 ( /bin/sh )
ENTRYPOINT command param1 param2
|
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。
BuildKit
从版本 18.09 开始,Docker 支持一个新的后端来执行由moby/buildkit 项目提供的构建。
Spring Boot 2.3.0 构建分层 Docker 镜像
Spring Boot 默认使用 org.springframework.boot:spring-boot-maven-plugin
Maven 插件把项目编译成jar包。默认编译的jar包是一个整体,通过java -jar命令可直接启动,这导致在结合docker打包的情况下,每次docker push都会上传全量的jar包。最近 Spring Boot 2.3.0发布,更新包含了支持分层打包。
在 Spring Boot maven 插件中加入配置支持分层打包
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
</plugins>
</build>
|
1
2
3
4
5
6
|
# 打包
mvn clean package
# 分层打包编译的jar包结构
java -Djarmode=layertools -jar target/springboot-layers-1.0.0.jar list
# 提取 jar 包的分层内容
java -Djarmode=layertools -jar app.jar extract
|
使用分层工具提取 jar 的内容后生成的文件夹,其中各个文件夹作用是:
- dependencies: 存储项目正常依赖 jar 的文件夹。
- snapshot-dependencies: 存储项目快照依赖 jar 的文件夹。
- resources: 用于存储静态资源的文件夹。
- application: 用于存储应用程序类相关文件的文件夹。
可以看到layertools识别出jar包内将依赖打包到不同文件夹中,接下来我们改造下原有的dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
FROM openjdk:8-jre as builder
WORKDIR application
ADD ./target/*.jar ./app.jar
RUN java -Djarmode=layertools -jar app.jar extract
FROM openjdk:8-jre
MAINTAINER ynthm.w@gmail.com
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
EXPOSE 36665
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
|
这个 dockerfile 表示先进行一次临时镜像构建标记为 builder,并加载一次全量 jar 包,然后执行 java -Djarmode=layertools -jar app.jar extract
命令将 jar 包分解为分层打包目录,再次构建一个新镜像,按照 list 的目录顺序分批将分层目录加载到 docker 镜像中。
1
2
3
4
|
# 构建 docker 镜像
docker build . -t hub.docker.ynthm.com:5000/springboot-layers:2.0.0
# 分析 docker 镜像层级
docker inspect hub.docker.ynthm.com.com:5000/springboot-layers:2.0.0
|
1
2
|
# dive 可以查看分层详情
brew install dive
|
附录