Docker
Build/Ship/Run
Links
プラクティス
apt-get
コピペ用
code:apt-get
RUN apt-get update \
&& apt-get -y install --no-install-recommends \
bzip2 \
ca-certificates \
...
&& apt-get clean \
&& rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/*
更新防ぐ
前段で入れた apt モジュールを更新されたくない時
apt-mark hold PACKAGE で固定できる、解除は unhold、一覧は showhold
tar 解凍して特定ディレクトリに置く
code:mkdir-wget-tar
RUN mkdir -p /hoge
ENV PATH=/hoge
ディレクトリ作る、wget で tar へパイプする、特定ディレクトリへ向けて解凍する、tar 内の親ディレクトリは省く、パスを通す
docker history IMAGE
ビルドステップ見れる
docker stats
コンテナごとの CPU やメモリ使用率、ネットワーク & ディスク IO をみれる
$ docker exec -it {container} /bin/bash
$ docker-compose exec {service} /bin/bash とかで中を見に行ける
compose のときはコンテナ ID 調べなくてよい
build で複数のタグを付ける
$ docker build -t project/app:$SHA1 -t project/app:latest のようにすると revision 指定と最新同時につくれるね
--squash
docker build --squash でレイヤまとめられる
init
pid 1 になってしまう問題のやつ
今はオプションや docker-compose.yml でできる
multi stage
FROM hoge AS stage_name
COPY --from=builder で取ってくる
$ docker build --target stage_name
ARG flavor=a で変数化して FROM hoge:$flavor AS release など参照できる
Buildkit
$ DOCKER_BUILDKIT=1 docker build .
yarn のキャッシュディレクトリをコピーする
イメージに入って yarn cache dir とかで確認する
COPY --from=deps /usr/local/share/.cache/yarn/v6 /usr/local/share/.cache/yarn/v6
root user 避ける
USER nobody
docker create & start & wait
create でコンテナだけ作って(まだ動かさない)、cp でコンテナ内へファイルを移して start できる
wait でコンテナ終了を待って成果物を取り出したりする
code:sh
CONTAINER_ID=$(docker create $IMAGE_NAME)
docker cp ./config.json $CONTAINER_ID:/path-to-config/
docker start --attach $CONTAINER_ID
docker wait $CONTAINER_ID
...
docker cp $CONTAINER_ID/dest:./dest
最後に終了したコンテナから取り出す
$ docker cp $(docker ps -q -l --filter status=exited):/dir/file .
終了したコンテナに入る
$ docker container start $CONTAINER_ID
$ docker container exec -it $CONTAINER_ID /bin/bash # (など)
ビルド失敗したイメージ調査
docker ps -a でビルドに失敗したゴミが残ってるので、image を指定して docker run --rm -it $IMAGE /bin/bash で失敗した step を再度実行する
docker run --rm -it $(docker ps -l --filter status=exited --format={{.Image}}) /bin/bash
最後のステップもう一度実行したくないなら失敗したコンテナをイメージ化して入る docker commit $CONTAINER
docker で 0.0.0.0 で listen する理由
サーバにおいては、0.0.0.0は「ローカルマシン上の全てのIPv4アドレス」を意味する。ホストに192.168.1.1と10.1.2.1の2つのIPアドレスがあり、そのホストで実行されているサーバが0.0.0.0で待ち受けするように構成されている場合、どちらのIPアドレスに対しても到達可能になる。
かな?
証明書エラー回避テク
さまざまな理由により、コンテナ内から証明書エラーが出る場合
-v /etc/ssl/certs:/etc/ssl/certs:ro などで、ホストの証明書を渡して回避する
Image の Created ちゃんと見せて
3 month ago みたいな相対表記で時刻が分からなくてダルい、format で整形して見るしか無い
$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}"
ENTRYPOINT と CMD
ENTRYPOINT はプロセスを起動するコマンド(基本的に書き換えない)
CMD はデフォルトの引数にするのが基本(都度指定しうるもの)
code:Dockerfile
ENTRYPOINT: /usr/bin/git
のとき
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
$ docker run myimage のように単に IMAGE だけ指定すると /usr/bin/git status を実行
$ docker run myimage diff なら CMD が上書きされ /usr/bin/git diff が実行される
--entrypoint=/bin/ls などで起動するコマンドを上書きできる
ENTRYPOINT がないなら CMD が実行される
気持ち
"コマンド" を提供する気持ちのイメージなら ENTRYPOINT を指定
"環境" を提供する気持ちのイメージなら ENTRYPOINT, CMD なしにする or /bin/bash などのシェルにする
standard_init_linux.go:211: exec user process caused "exec format error"
ENTRYPOINT や CMD が shell を経由して実行される前提で親シェルがない場合おこられる(多分)
シェルスクリプトなら shebang を指定する、java -jar {jarfile} などで回避
java の docker image
Dockerhub にめっちゃある
ビルドしないなら jre でいい
slim が小さいやつ
apk add --vertual
-t, --virtual NAME Instead of adding all the packages to 'world', create a new virtual package with the listed dependencies and add that to 'world'; the actions of the command are easily reverted by deleting the virtual package
apk add --virtual .hoge-deps && ... && apk del .hoge-deps
docker run へ pipe や redirect する
思考停止で -it しがちだけど、interactiveだけつける、tty はつけない
cat schema.sql | docker run --rm -i --net=host mysql -h127.0.0.1 -uroot mydatabase
pull する際のサイズ・圧縮状態のサイズを得る
$ docker manifest inspect してレイヤーサイズを足し合わせる
$ docker manifest inspect gcr.io/pokutuna-playground/curl | jq '[.layers[].size] | add'
69285060
69MB
docker images だと展開後の 1.2GB
gcr.io/pokutuna-playground/curl latest 86a3a5ae247b 2 weeks ago 1.2GB
$ ... | numfmt --to=iec
とすると readable になる
volume
-v /hoge 匿名ボリュームがコンテナ内の /hoge にマウントされる
-v hoge:/fuga hoge ボリュームが作られコンテナ内の /fuga にマウントされる
-v /host:/container ホストの /host ディレクトリがコンテナ内の /container にマウントされる
↑これよく使うけどキャッシュ用のディレクトリならホスト側に要らないよ
named pipe 知らねえ
権限に一生困り続けてるな
バインドマウントなら USER 渡して entrypoint で user 作るなどの手間が必要
Dockerfile で VOLUME 宣言しておいて USER に chown していれば大体よい?
/etc/passwd をマウントするテクもあるのか...
compose の依存で権限書き換えるアイディアおもしろいし、たまに出番がありそう