0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

docker imageを直接pullしてみた

Last updated at Posted at 2019-05-25

背景

userlandの仮想化基盤としてだけでなく、ソフトウェアの直接導入にもdockerは使われてきている。dockerはimageという単位で取り扱うことが多いが、このimageをリモートリポジトリからpullしたり、リモートリポジトリにpushしたりすることが可能である。これによりimageを共有することができるのである。
ところが一部、このpullを直接はできない環境があり得る。当該マシンが直接インターネットに繋がっていないことや、イントラネットにすら繋がっていないこともあるだろう。そのような場合、docker loadにより標準入出力を介してimageをやり取りすることになる。この場合に使われるのはpullしてきたファイル群をTarで固めたものである。これは手元のdocker daemonからdocker saveすることで作成することができるが、一旦手元にdocker pullしなければ、docker saveは実行できない。バッチ処理に組み込む場合等、不便なことがあるかもしれない。
今回は、リモートからダウンロードしたdocker imageのTarを直接標準出力に生成することを試みる。[1]はそうした試みの先駆けであるが、単体ではログイン機構を有しておらず、docker.ioで使うには力不足である。これをBashからRuby/Pythonで書き直し、再利用をしやすくしたい。

方法

docker pullはHTTPSを用いており、認証 -> マニフェストダウンロード -> レイヤーダウンロード -> メタファイル生成という順序で行われる。
まずはマニフェストをダウンロードする。ここで401になったら、WWW-Authenticateヘッダの情報を用いて認証を行う。この認証はBasic認証であり、docker loginが済んでいれば、認証文字列は.docker/config.jsonから直接得ることができる。ここで帰ってきたtokenをBearer認証に用いる。レイヤーはマニフェストに書いてある順番で重ねれば良い。レイヤーのIDは[1]にならいSHA256(parentId+"\n"+layerDigest+"\n")とした。

結果

モジュール

Pythonは標準ライブラリで完結させることができた。Rubyはminitarとmechanizeについて外部ライブラリを利用する。minitarはTarライブラリで、mechanizeはプログラムベースブラウザとも言うべきウェブ操作ライブラリである。

WWW-Authenticateヘッダの取扱い

Pythonはurllib内にparse_keqv_listやparse_http_listといった関数群があり、これでparseすることができる。Rubyは標準ライブラリでは処理できないため、mechanizeを使用する。ただし、mechanizeはsavonというSOAPライブラリが導入されている環境に導入しようとするとruby-ntlm関係でエラーが発生することが知られているため、今回はMechanize::HTTP::WWWAuthenticateParserの中身を埋め込むこととした。

30xステータスコードの取扱い

mechanizeであれば30xステータスコードが来たら自動でLocationを読みに行ってくれるが、HTTPを直接触る限りそういうわけにも行かない。30xが来たら、今のレスポンスを捨てたあと、locationを読みに行き30xが来る限りレスポンスを捨てることを繰り返せば良い。この繰り返しはブロック(Pythonの場合はcontextmanagerを使う)を用いて行い、HTTP bodyはyieldで渡すようにすると、後処理が楽である。

Tarの取扱い

Tar(に限らずアーカイブファイル一般)はヘッダにメンバサイズを書かなければならない(またはアーカイブに追加したあとでシークが必要であるが、標準出力を扱うため認められない)。HTTPヘッダのContent-Lengthをこのメンバサイズとして書き込めば良い。Rubyの場合は、tar.add_fileではなくtar.add_file_simpleを使う必要があった。add_fileはメンバ内に書き込んだサイズを自動判別(しシーク)するバージョンだからである。

結論

今回はRuby/Pythonを用いてdocker imageをtarとしてpullすることができた。
https://github.com/cielavenir/pulldockerimage にて利用可能である。

参考

[1] https://raw.githubusercontent.com/moby/moby/master/contrib/download-frozen-image-v2.sh

余談

(英語で書いたとしても)Linux Journalとかに載せるレベルじゃないですよねー肝心な場所のアルゴリズムは既存の技術ですしorz
7bgzfは違う領域だからある程度の価値があるけども。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?