🐳

zstd圧縮を使用したコンテナイメージの軽量化

2022/12/25に公開

概要

AWSのブログでコンテナイメージの圧縮をgzipからzstdに変更することで高い圧縮率と高い解凍速度を得られるとあったので、圧縮部分を確認してみました。
(解凍速度は見ていません。)
https://aws.amazon.com/jp/blogs/news/reducing-aws-fargate-startup-times-with-zstd-compressed-container-images/

環境

  • Amazon ECR
  • Docker Desktop for Mac v4.15.0
  • aws cli 2.7.31

Dockerfile

以下を参考にCloudWatchエージェントをインストールしたDockerイメージを作るDockerfileを用意します。
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ContainerInsights-build-docker-image.html

FROM debian:11.6 as build

RUN apt-get update &&  \
    apt-get install -y --no-install-recommends ca-certificates curl && \
    rm -rf /var/lib/apt/lists/*

RUN curl -O https://s3.amazonaws.com/amazoncloudwatch-agent/debian/amd64/latest/amazon-cloudwatch-agent.deb && \
    dpkg -i -E amazon-cloudwatch-agent.deb && \
    rm -rf /tmp/* && \
    rm -rf /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard && \
    rm -rf /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl && \
    rm -rf /opt/aws/amazon-cloudwatch-agent/bin/config-downloader

FROM scratch

COPY --from=build /tmp /tmp

COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

COPY --from=build /opt/aws/amazon-cloudwatch-agent /opt/aws/amazon-cloudwatch-agent

ENV RUN_IN_CONTAINER="True"
ENTRYPOINT ["/opt/aws/amazon-cloudwatch-agent/bin/start-amazon-cloudwatch-agent"]

ECRの事前準備

リポジトリの作成

ECRにgzip圧縮したコンテナを登録するcloudwatchリポジトリとzstd圧縮したコンテナを登録するcloudwatch-zstdリポジトリを作成しています。

% aws ecr describe-repositories | grep repositoryName
            "repositoryName": "cloudwatch",
            "repositoryName": "cloudwatch-zstd",

ECRの認証

AWS CLIを使用して認証し、作成したDockerイメージをリポジトリに登録できるようにします。

% export account_id=123456789012 #AWSのアカウントID
% aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${account_id}.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded

gzip圧縮した場合の確認

Docker Desktopをデフォルトのまま使用してDockerイメージを作るとgzip圧縮されます。

コンテナイメージの作成

zstdの場合となるべく合わせて、buildxを使用してコンテナイメージを作成します。

% docker buildx build --file Dockerfile --output type=image,name=${account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/cloudwatch:1,push=true .

作成したイメージの圧縮アルゴリズム確認

mediaTypeでgzip圧縮されていることを確認できました。

% docker buildx imagetools inspect --raw ${account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/cloudwatch:1 | grep mediaType
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "mediaType": "application/vnd.docker.container.image.v1+json",
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",

イメージのサイズは33,619,130バイトでした。

% aws ecr describe-images --repository-name=cloudwatch | grep -e repositoryName -e imageSizeInBytes
            "repositoryName": "cloudwatch",
            "imageSizeInBytes": 33619130,

Docker Desktopの設定変更

Docker DesktopデフォルトのDocker Engineはまだzstd圧縮に対応していません。
zstd圧縮を使用するためにDocker Desktopでcontainerdを使用するように設定します。

Docker DesktopのPreferences - Features in development - Beta featuresでUse containerd for pulling and storing imagesにチェックを入れます。
Apply & restartをクリックし、containerdを使用するようにします。

zstd圧縮した場合の確認

コンテナイメージの作成

% docker buildx build --file Dockerfile --output type=image,name=${account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/cloudwatch-zstd:1,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true,push=true .

作成したイメージの圧縮アルゴリズム確認

mediaTypeがzstdとなっていることを確認できました。

% docker buildx imagetools inspect --raw ${account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/cloudwatch-zstd:1 | grep mediaType
   "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "mediaType": "application/vnd.oci.image.config.v1+json",
         "mediaType": "application/vnd.oci.image.layer.v1.tar+zstd",
         "mediaType": "application/vnd.oci.image.layer.v1.tar+zstd",
         "mediaType": "application/vnd.oci.image.layer.v1.tar+zstd",

サイズは32,249,116バイトで、gzipの場合の95.9%でした。

% aws ecr describe-images --repository-name=cloudwatch-zstd | grep -e repositoryName -e imageSizeInBytes
            "repositoryName": "cloudwatch-zstd",
            "imageSizeInBytes": 32249116,

Discussion