はじめに
私はまだdockerのイメージ管理の仕組みをよく理解しておらず、試行錯誤して対処療法的にスクリプト書いてみただけですので、あまり期待せずに読んでください。
最速Docker研究会(DockerのTipsを20個上げていくぜ編) - Happy New Worldの「3. docker build時には必ずタグを付ける。」を実践していると、試行錯誤中に何度も同じタグでイメージをビルドするので、古いイメージはタグが外れた状態になっています。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
hnakamur/nginx-lua latest 79e74886d6a9 31 hours ago 527.6 MB
<none> <none> 64b4fa0cdd27 32 hours ago 525 MB
<none> <none> 5a2b9b2294c3 32 hours ago 525 MB
<none> <none> a12c2c15bbfd 32 hours ago 525 MB
(…略…)
タグのついてないイメージをまとめて消したいなーと思って調べてみたところ、Dockerで不要になったコンテナやイメージを削除する - @znz blogという記事を見つけました。(←注:blogまでをリンクにしたいのですがエスケープ方法がわからず)
でも実際やってみると
$ docker rmi $(docker images | awk '/^<none>/ { print $3 }')
Error: image_delete: Conflict, 64b4fa0cdd27 wasn't deleted
Error: image_delete: Conflict, 5a2b9b2294c3 wasn't deleted
(…略…)
2014/03/08 18:26:04 Error: failed to remove one or more images
となって1つも消えませんでした。
先にコンテナを消す必要がある
ググってみるとdocker rmi
doesn't remove image · Issue #3549 · dotcloud/dockerというコメントを発見。イメージを使用中のコンテナがあるから消せない、使用中のコンテナを調べるにはdocker ps -a
を使えば良いということが判りました。
docker ps -a
の出力はこんな感じです。2列目にイメージIDがあって1列目がコンテナIDになっています。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d3142ccc6b65 e359b0142e7c /bin/sh -c #(nop) AD 32 hours ago Exit 0 loving_mclean
cfc1c1e8865c 7088bb60ddab /bin/sh -c #(nop) CM 32 hours ago Exit 0 focused_newton
bd4a1d1d5d21 b4488990d8fb /bin/sh -c #(nop) EX 32 hours ago Exit 0 insane_fermi
(…略…)
そこでこんなbashスクリプトを作ってみました。
#!/bin/bash
untagged_images=`docker images | awk '/^<none>/ { print $3 }'`
for image in $untagged_images; do
containers=`docker ps -a | awk '$2 == "'$image'" { print $1 }'`
if [ -n "$containers" ]; then
docker rm $containers
fi
docker rmi $image
done
しかしイマイチ問題あり
喜び勇んで試してみました。
$ ~/bin/docker_rm_containers_for_images_without_tags.sh
5430335f83e2
Deleted: 64b4fa0cdd27371ab83af797658b52b8d1bce792c51bff59eb567440ecc33b47
9adc1e994683
Deleted: 5a2b9b2294c3c81338c5b3d2e35f7e950aa74837b28264fd62b869a09c3d32bd
599543770f46
Deleted: a12c2c15bbfd950b9173c6c7af9735063fc4531e6f7527288cd996bfbe1a5682
(…略…)
お、順調に消されてるねと思い、実行も正常に終了したので、再度docker imagesを実行してみると、まだまだ残っているではありませんか。何個か減って入るのですが、上でDeletedと出た数よりはかなり少ないです。
上のスクリプトを実行してはdocker imagesで確認すると少しずつ減って行き、最後にはTAGが<none>
のイメージは無くなりました。
ということでdocker imagesでTAGが<none>
のイメージがある場合は繰り返し実行するようにしてみました。
#!/bin/bash
while :; do
untagged_images=`docker images | awk '/^<none>/ { print $3 }'`
if [ -z "$untagged_images" ]; then
exit 0
fi
for image in $untagged_images; do
containers=`docker ps -a | awk '$2 == "'$image'" { print $1 }'`
if [ -n "$containers" ]; then
docker rm $containers
fi
docker rmi $image
done
done
とりあえずの目的は達したので、一旦これでよしとします。ライセンスはMITです。
別のエラーも出たけど再現できず
この記事を書きながら試していると以下の様なエラーが出た時が一度だけありました。
Error: container_delete: Impossible to remove a running container, please stop it first
2014/03/08 19:20:29 Error: failed to remove one or more containers
Error: image_delete: Conflict, 79e74886d6a9 wasn't deleted
2014/03/08 19:20:29 Error: failed to remove one or more images
Error: container_delete: Impossible to remove a running container, please stop it first
2014/03/08 19:20:28 Error: failed to remove one or more containers
Error: image_delete: Conflict, 79e74886d6a9 wasn't deleted
2014/03/08 19:20:28 Error: failed to remove one or more images
(…略…)
docker runしたまま同じタグのイメージを何回か作ってdocker_rm_containers_for_images_without_tags.shを実行した時に発生しました。
docker psでコンテナIDを調べてdocker stop ${コンテナID}で止めてからdocker_rm_containers_for_images_without_tags.shを実行すると大丈夫でした。
その後、再現を試みようとdocker runしたままdocker build -tで同じタグのイメージを何回か作ってdocker_rm_containers_for_images_without_tags.shを実行してみたのですが、再現しません。
別のパターンとして以下のようにNo such imagesが出るケースが発生しましたが、これは実害は無いので気にしないことにします。
$ ~/bin/docker_rm_containers_for_images_without_tags.sh
Deleted: 8746e95203a6273be11188f43af1a1e10219b587ceff60be60c7791c5744a17e
Deleted: e07e561873cd7a4feca3ff68d36d6bc1e91773600870cd3e4cc1219fb43b5208
Error: image_delete: No such image: e07e561873cd
2014/03/08 19:27:21 Error: failed to remove one or more images
42b755c2809a
Deleted: 777e310d5345300d6949e6ed513d93cb96886eccff86109053ae9dd6979e7207
55e8d9b3705a
(…略…)