目录

Dockerfile

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

附录