简化Docker镜像

通过对Dockerfile进行改进,使Docker镜像变得更加轻量化

最近、Dockerを使い始めました。まずはDockerfileをゴリゴリ書いていたんですが、書いているうちに軽量化のテクニックを知っているかどうかで最終的にできるDockerイメージのサイズが劇的に変わることがわかったので、ここにそのテクニックをまとめてみようと思います。

顺便提一下,当Docker镜像的大小变小时,会有以下优点。

    • ホストのディスク容量を圧迫しない

 

    イメージの配布が効率的に行える

请用中文重新表达以下内容(仅需提供一种选择):

这个问题

这次我们将为受欢迎的沙盒游戏 Minecraft 开发一个用于 Spigot 开源服务器的 Docker 镜像。

请放心,本文旨在介绍创建Docker镜像时常用的技巧,即使对Minecraft完全不感兴趣的读者也可阅读。

Spigotのビルド方法は以下を参考にしています。

构建工具 | SpigotMC

注意:Spigotは権利関係の事情により、ビルド済み実行ファイルを配布することができません。(詳しい経緯は以下が参考になるかと思います。)Dockerイメージでの配布も同様に問題になると考えられるため、Docker Hub等で公開しません。

DMCA(数字千年版权法)- Bukkit Spigot 日本维基百科

首先,根据想法立即开始制作。

とりあえず、一番単純なDockerfileを書いてみたら、どれぐらいのイメージサイズになるのか確認してみます。

以下のDockerfileをビルドすると、イメージサイズは1.24GBになりました。かなり大きいですね。

FROM openjdk:8-jdk

ENV SPIGOT_VER 1.12.2

WORKDIR /minecraft
RUN wget "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O BuildTools.jar
RUN java -jar BuildTools.jar –rev $SPIGOT_VER

WORKDIR /data
RUN echo "eula=true" > ./eula.txt

EXPOSE 25565
ENTRYPOINT java -jar /minecraft/spigot-${SPIGOT_VER}.jar nogui

使用轻量级映像

openjdk:8-jdk镜像基于Debian构建,但如果只需要运行Java,则不需要Debian附带的许多软件。因此,我们使用基于最小功能的轻量级操作系统镜像。通常在这个用途上使用Alpine Linux,并且openjdk的Alpine Linux版本镜像也在Docker Hub上公开,所以这次我们将使用它。

如果需要,您需要随时安装git等软件,因为Alpine Linux中没有这些软件。在Alpine Linux中,我们主要使用名为apk的软件包管理器来安装软件。

利用 Alpine Linux 版的 openjdk 镜像重写 Dockerfile,并进行构建后,镜像大小变为 734MB。

FROM openjdk:8-jdk-alpine

ENV SPIGOT_VER 1.12.2

WORKDIR /minecraft
RUN apk --no-cache add git
RUN wget "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O BuildTools.jar
RUN java -jar BuildTools.jar –rev $SPIGOT_VER

WORKDIR /data
RUN echo "eula=true" > ./eula.txt

EXPOSE 25565
ENTRYPOINT java -jar /minecraft/spigot-${SPIGOT_VER}.jar nogui

整合RUN.

在使用docker build命令时,每次执行RUN,COPY和ADD指令都会创建一个镜像层,并将其缓存起来以便以后使用。换句话说,随着这些命令的增加,镜像内的层数也会增加,导致镜像的大小变得更大。但是,通过将每个命令使用&&连接起来,可以将它们压缩在一个RUN语句中,从而防止创建额外的镜像层。

我本来以为这样会有效果,但是我尝试用这种方法重写了 Dockerfile 并构建了镜像,结果镜像的大小和之前的方法一样,都是734MB。可能只有在更复杂的构建步骤下才会有一定的效果。

FROM openjdk:8-jdk-alpine

ENV SPIGOT_VER 1.12.2

WORKDIR /minecraft
RUN apk --no-cache add git && \
  wget "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O BuildTools.jar && \
  java -jar BuildTools.jar –rev $SPIGOT_VER && \
  mkdir /data && \
  echo "eula=true" > /data/eula.txt

WORKDIR /data

EXPOSE 25565
ENTRYPOINT java -jar /minecraft/spigot-${SPIGOT_VER}.jar nogui

使用多阶段构建

如果要像这次一样构建Java软件,那么在构建时需要使用JDK,但在执行镜像中只需要安装JRE即可。也就是说,只需将构建的成果物复制到已安装JRE的容器中即可。而使用Docker 17.05新增的多阶段构建功能,可以轻松实现这一目标。

顺便提一下,如果使用多阶段构建的话,无论在构建容器中创建了多少层,最终结果都不会受到影响,因此不需要使用之前提到的将RUN合并的技巧。

我试着使用多阶段构建重新编写了Dockerfile并构建了镜像,结果镜像大小变成了126MB。多阶段构建太厉害了!

FROM openjdk:8-jdk-alpine AS build-env

ENV SPIGOT_VER 1.12.2

WORKDIR /build
RUN apk --no-cache add git
RUN wget "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O BuildTools.jar
RUN java -jar BuildTools.jar –rev $SPIGOT_VER
RUN mkdir minecraft
RUN cp spigot-${SPIGOT_VER}.jar minecraft/spigot.jar
RUN mkdir data
RUN echo "eula=true" > data/eula.txt


FROM openjdk:8-jre-alpine

WORKDIR /data
COPY --from=build-env /build/minecraft /minecraft
COPY --from=build-env /build/data /data

EXPOSE 25565
ENTRYPOINT java -jar /minecraft/spigot.jar nogui

总结

我们成功地将Docker镜像的大小从1.24GB缩小到了126MB,可以说是大幅度的减小。即使是具有相似功能的Docker镜像,只要稍加改进,也可以大幅度地降低其重量。请务必参考这些小技巧。

广告
将在 10 秒后关闭
bannerAds