Dockerイメージを小さくするため一時ファイルはCOPYではなくローカルサーバーから取得する


ロケールとタイムゾーンを変更し、フィーチャーを追加したLibertyイメージをオフライン環境でビルドする必要があり、イメージサイズを小さくするため、一時的に必要なファイルについて、COPYコマンドではなくローカルサーバーから取得するようにしてみたメモ。

前提としてもともとイメージにwget等が入っている必要があり、ない場合は一時的に入れることもできるが、使える状況は限られるかもしれない。

オンライン環境でのイメージのビルド

普通にオンライン環境でビルドするとしたら次のようになる。

Dockerfile
FROM websphere-liberty:18.0.0.4-javaee8
USER 0
RUN apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y \
    language-pack-ja \
    tzdata \
  && rm -rf /var/lib/apt/lists/* \
  && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && dpkg-reconfigure -f noninteractive tzdata
USER 1001
RUN /opt/ibm/wlp/bin/installUtility install wmqJmsClient-2.0 --acceptLicense
ENV LANG ja_JP.UTF-8
ENV TZ Asia/Tokyo
docker build -t liberty-test:online .

オフライン環境でのイメージのビルド

オフラインでのビルドに必要なファイルの取得

ビルドに必要なファイルを取得するため、オンライン環境で、-uでrootユーザーを指定し、カレントディレクトリーをマウントしてLibertyコンテナを起動して中に入る。

docker run --rm -it -u 0 -v $PWD:/work websphere-liberty:18.0.0.4-javaee8 bash

必要なUbuntuのパッケージをダウンロードオンリーモードで取得する。

apt-get update
apt-get install -y -d language-pack-ja
apt-get install -y -d tzdata

/var/cache/apt/archivesにダウンロードしたファイルがあるので、マウントしたディレクトリーにコピーする。

cp /var/cache/apt/archives/*.deb /work

Libertyフィーチャーをダウンロードする。

mkdir /tmp/wmqJmsClient-2.0
/opt/ibm/wlp/bin/installUtility download wmqJmsClient-2.0 --location=/tmp/wmqJmsClient-2.0

ダウンロードしたファイルを、マウントしたディレクトリーにアーカイブして保存する。

cd /tmp
tar czvf /work/wmqJmsClient-2.0.tar.gz wmqJmsClient-2.0

コンテナをexitする。

オフライン環境でCOPYを使ってビルド

COPY命令を使う場合は以下のようになる。

Dockerfile
FROM websphere-liberty:18.0.0.4-javaee8
USER 0
COPY *.deb /tmp/
RUN DEBIAN_FRONTEND=noninteractive dpkg -i \
    /tmp/language-pack-ja-base_1%3a16.04+20160627_all.deb \
    /tmp/language-pack-ja_1%3a16.04+20171210_all.deb \
    /tmp/locales_2.23-0ubuntu10_all.deb \
    /tmp/tzdata_2018i-0ubuntu0.16.04_all.deb \
  && rm -rf /tmp/* \
  && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && dpkg-reconfigure -f noninteractive tzdata
USER 1001
COPY --chown=1001:0 wmqJmsClient-2.0.tar.gz /tmp/
RUN tar xzvf /tmp/wmqJmsClient-2.0.tar.gz -C /tmp \
  && /opt/ibm/wlp/bin/installUtility install wmqJmsClient-2.0 \
    --acceptLicense --from=/tmp/wmqJmsClient-2.0 \
  && rm -rf /tmp/*
ENV LANG ja_JP.UTF-8
ENV TZ Asia/Tokyo
.
├── Dockerfile
├── language-pack-ja-base_1%3a16.04+20160627_all.deb
├── language-pack-ja_1%3a16.04+20171210_all.deb
├── locales_2.23-0ubuntu10_all.deb
├── tzdata_2018i-0ubuntu0.16.04_all.deb
└── wmqJmsClient-2.0.tar.gz
docker build -t liberty-test:offline-copy .

COPYした時点でレイヤーができているため、一時ファイルを削除したとしてもイメージサイズが増えている。

$ docker images | grep liberty-test
liberty-test                          offline-copy           39df53382b2e        3 seconds ago       630MB
liberty-test                          online                 5040739eb1d2        24 seconds ago      611MB
$

オフライン環境でローカルサーバーを使ってビルド

pythonを使ってローカルで簡易Webサーバーを起動する。カレントディレクトリが公開されるので公開したいファイルがあるディレクトリで実行する。

Python3の場合
python3 -m http.server
Python2の場合
python -m SimpleHTTPServer

ポート番号を指定したい場合はpython3 -m http.server 8888のように指定できる。

Webサーバーを起動すると以下のようにHTTPサーバー経由でアクセスできる。

このサーバーを使いwgetで一時ファイルを取得し、一時ファイルを削除するところまでを一つのRUNコマンドに書く。

注意点として、localhostではビルド時にアクセスできないため、Webサーバーを起動しているマシンの実IPを指定する必要がある。

また、ローカルにあるファイル名と、Webサーバーに公開したときのURLと、wgetでsaveしたときのファイル名がURLエンコードされたりデコードされたりでちょっとずつ変わってくるので注意が必要。

Dockerfile
FROM websphere-liberty:18.0.0.4-javaee8
USER 0
RUN wget -P /tmp http://9.237.53.92:8000/language-pack-ja-base_1%253a16.04%2B20160627_all.deb \
  && wget -P /tmp http://9.237.53.92:8000/language-pack-ja_1%253a16.04%2B20171210_all.deb \
  && wget -P /tmp http://9.237.53.92:8000/locales_2.23-0ubuntu10_all.deb \
  && wget -P /tmp http://9.237.53.92:8000/tzdata_2018i-0ubuntu0.16.04_all.deb \
  && DEBIAN_FRONTEND=noninteractive dpkg -i \
    /tmp/language-pack-ja-base_1:16.04+20160627_all.deb \
    /tmp/language-pack-ja_1:16.04+20171210_all.deb \
    /tmp/locales_2.23-0ubuntu10_all.deb \
    /tmp/tzdata_2018i-0ubuntu0.16.04_all.deb \
  && rm -rf /tmp/* \
  && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && dpkg-reconfigure -f noninteractive tzdata
USER 1001
RUN wget -P /tmp http://9.237.53.92:8000/wmqJmsClient-2.0.tar.gz \
  && tar xzvf /tmp/wmqJmsClient-2.0.tar.gz -C /tmp \
  && /opt/ibm/wlp/bin/installUtility install wmqJmsClient-2.0 \
    --acceptLicense --from=/tmp/wmqJmsClient-2.0 \
  && rm -rf /tmp/*
ENV LANG ja_JP.UTF-8
ENV TZ Asia/Tokyo
docker build -t liberty-test:offline-local-server .

イメージサイズを比較してみる。オンラインでビルドしたときと同じサイズになった。

$ docker images | grep liberty-test
liberty-test                          offline-local-server   aa609cfad56f        4 seconds ago        611MB
liberty-test                          offline-copy           39df53382b2e        About a minute ago   630MB
liberty-test                          online                 5040739eb1d2        About a minute ago   611MB
$ 

ビルド手順が複雑でDockerfileもわかりにくいものになってしまうため、わざわざここまですることはあまりなさそう。

参考リンク