はじめに
最近はSingularityの使い勝手がよく感じられて、Docker imageをbulidしてはSIFを作製しています。色々なツールを使っていると、あるものはPython3.9が必要だったり、あるものは3.7が必要だったりnumpyやpandasのバージョンが特定のものじゃないとエラーになったり...というのを経験します。そこで、Dockerを使ってそれぞれのツールに適したConda環境を作製してSingularity imageにすることにしました。がしかし、色々と詰め込んでいたらDocker imageのサイズが大きくなりすぎてしまいpushできないという状況に陥りました。そんなときの覚書です。色々と試しましたがpushできない問題は解決できていません。。。
今回何がしたかったのか
以前の記事
ynagaoka.hatenablog.com
で書いたようにSingularity image (SIFファイル)はDockerHubにアップロードされているDocker imageからbuildすることができます。
作製したオリジナルのDocker imageを何らかの経緯で公開・他者と共有する必要がある場合は、DockerHubにアップロードする必要があります。ここにアップロードしておけばローカルのDocker imageを消去しても、再度pullすることで使用できます。PCの容量を圧迫しないためにも作製したDocker imageはDockerHubにアップロードしておくのが良いでしょう。Singularity imageを作製するのも楽です。
注意点は無料版のDockerを利用している場合、アップロードしたDocker imageは開発途中や未発表のものでも基本的に一般公開となり誰でも利用できる状態になることです。これが嫌だという場合は無料版でも1つのRepositoryに限りプライベートにできるのでこの設定をしておくのが良いでしょう。
前置きが長くなりましたが僕が何をやろうとしたのかというと、自分で作製したDocker imageをDockerHubにアップロードし、それを基にSingularity imageを作製しようとしたわけです。
問題点
Dockerfileからimageを作製してDockerHubにpushしたところunauthorized: authentication required
というエラーが出現しました。ログは下記 (imegeの名前は適当です。)
$ docker push yunagaoka/XXX:latest The push refers to repository [docker.io/yunagaoka/XXX] e395ddd90784: Layer already exists 10d409a506d1: Layer already exists 9496213096b0: Layer already exists 8e0a710a5b19: Layer already exists c5281a67b2ea: Layer already exists 7c81a2cd73a3: Layer already exists ae9c36ce183c: Pushing [==================================================>] 12.52GB 36f0da07ddc7: Layer already exists c31c719464dd: Layer already exists 3a2bb5d558b6: Layer already exists 0914ed36d165: Layer already exists 3ba0366e3919: Layer already exists 11e30c0ea9b3: Layer already exists 7a08d5b6af48: Layer already exists 02bb5b88bf7b: Layer already exists c4688e47e324: Layer already exists 88c461480888: Layer already exists 68792e5280b6: Layer already exists f46aa005659a: Layer already exists b0cf95f783d1: Layer already exists 843c029bd148: Layer already exists 5f70bf18a086: Layer already exists 01d4e4b4f381: Layer already exists unauthorized: authentication required
pushに失敗したようです。色々調べてトラブルシューティングをしました。 エラーの内容からこれは原因では無いだろうなというものも試しています。
考えられる原因1:アカウントが間違っているかログインに失敗している。
これはログアウトとログインで解消するか試しました。コマンドは以下です。
$ docker logout $ docker login Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one. You can log in with your password or a Personal Access Token (PAT). Using a limited-scope PAT grants better security and is required for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/ Username: yunagaoka Password: Login Succeeded
再ログインできたので再度pushを試しましたが効果なし同じエラーです。
考えられる原因2:Repositoriy名等が間違っている
これはDockerHubにyunagaoka/XXX
というRepositoriyが存在しない場合に起こりえます。今回はyunagaoka/XXX
という場所に何回もpushした実績があるので原因では無いでしょう。
ある記事ではTagを変更するとうまく行ったというものもあったので変更して試してみました。コマンドは下記です。
$ docker tag <IMAGE ID> yunagaoka/XXX:<New tag>
これでも改善しませんでした。
考えられる原因3:認証トークンが期限切れ
Dockerにloginする際パスワードの代わりに認証トークンを使用することができます。このトークンの期限が切れているのではないか?というものです。今回ログインに認証トークンは使用していませんが、新しくトークンを作製してそれを使ってログイン、再度pushを試しました。
アクセストークンを生成するにはまずhub.docker.com にログインします。
画面右上に表示されている自分のユーザー名をクリックして、Account Settingsを押します。
Security > New Access Token を実行します。
Descriptionは適当に書いて、プルダウンからAccess permissionsを選びます。ここでは全て行える様にRead,Write,Deleteを選択します。- 次の画面でトークンが表示されるので、それをコピーして保存します。 誤ってコピー前に表示画面を閉じてしまうとトークンを再表示することはできないので、消去して再発行する必要があります。
ログアウトし、作製したトークンを使ってログイン、再度pushしましたがこれもまた失敗です。
考えられる原因4:~/.docker/config.json
の不備
config.json
の内容を変更するとうまく行くという記事を見つけました。
github.com
docker.io
の部分をhttps://index.docker.io/v1/
に変更すると良いみたいです。
変更前
{ "auths": { "docker.io": { "auth": "XXXXX", "email": "your email" } } }
変更後
{ "auths": { "https://index.docker.io/v1/": { "auth": "XXX", "email": "your email" } } }
cat ~/.docker/config.json
で確認してみますが、自分の場合は既にこの形式になっていた...これも不発です。
考えられる原因4:回線速度の問題!?
調べていくと同じ問題を抱えている人が多くいました。
Docker imageのサイズが大きすぎてpushに時間がかかり、タイムアウトになる。そのせいでエラーが出るのではないか?という考えに至りました。imageのサイズはというと27.3G
で、pushにかかる時間を計ってみると7分程度でした。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE yunagaoka/XXX 0.9.2 d14a39797cbf 4 hours ago 27.3GB
試しに同じRepositoryに対して17G
くらい大きさのimageを作製してpushしてみたら成功しました。かかった時間は4分30秒程度でした。
次に、もう少し大きい21G
くらいのimageをpushしてみたら失敗しました。かかった時間は5分30秒程度でした。
もしかすると、push時間が5分を超えるとunauthorized: authentication required
になってしまうのかもしれません。
結局DockerHubにpushすることは諦め別の方法でSIFを作製することにしました。
(後日談:思い出した時に再度pushしたら何故か成功しました。何が原因だったのか...)
ローカルのDocker imagesからSingularity imageを作る
とりあえずSIFが作製できれば良いので、ローカルのDocker imagesから作製することにしました。方法は以下を参照しました。
方法1 : ローカルのdocker imageから直接.sifを作製
少し時間がかかりますがこれが一番簡単な方法です。コマンドは下記です。
$ singularity build <SIF image name> docker-daemon://<user name>/<Repository>:<Tag> 例$ sudo singularity build XXX.0.9.2.sif docker-daemon://yunagaoka/XXX:0.9.2
sudo
なしでエラーが出る場合はつけてください。
しばらくすると.sif
ができます。
方法2 : docker save
を使用して.tarを作製し、それをもとに.sifを作製する
- まず、
docker images
でDocker image のIDを確認します。 - IDをもとに.tarを作成(パーミッションエラーが出る場合はsudoを使用。その場合は次のbulidにもsudoをつける)
$ docker save <IMAGE ID> -o <tar file name> 例$ docker save 4776877a2b64 -o XXX.0.9.2.tar
しばらくすると.tar
ができます。
3. .tar
をもとに.sifを作製
$ singularity build <SIF image name> docker-archive://<tar file name> 例$ singularity build XXX.0.9.2.sif docker-archive://XXX.0.9.2.tar
しばらくすると.sif
ができます。
方法2では.tar
からDocker imageに変換することもできるのでローカルの容量を節約したい場合はこちらの方が良いかもしれません。
$ tar tvf <tar file name> #中身を確認できます $ docker load -i <tar file name> #tarをimageに変換できます
方法3としてDefinition Filesを使ってもSIFを作製できますが、とりあえず上記で事足りたのでスキップします。
今回はローカルのDocker imageからSingularity imageを作製しましたが、根本のDockerHubにpushできない問題は解決できていません。どなたか解決方法をご存じでしたら教えて頂ければ幸いです。