DockerのDjangoコンテナに対してpython manage.py shell_plusするときのメモ、正確にはdocker-composeで行っている。メモなので雑な記録。
app/settings.pyに下記追加してipythonを有効化、重要なのは後のIPYTHON_ARGUMENTS、ここにprofileの配置ディレクトリとして永続化される場所を渡しておくことで履歴や設定が保存される。
SHELL_PLUS = "ipython"
IPYTHON_ARGUMENTS = [
'--profile-dir', '/app/ipython_profile'
]
Dockerfileはこんな感じ、中国なのでpip用にProxy設定追加してる
FROM python:3.6
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV http_proxy http://192.168.1.X:8080
ENV https_proxy http://192.168.1.X:8080
RUN mkdir /app
WORKDIR /app
ADD requirements.txt /app/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ADD . /app/
Django==2.0.4
uwsgi==2.0.17
PyMySQL==0.8.0
django-extensions==2.2.8
ipython==5.9.0
あと、~/.docker/config.jsonに下記を書いておくとCtrl-pがDockerに横取りされて履歴アクションがおかしくなるの(Ctrl-p2回押し問題)を防げる。これはdjangoのshellでもbashでも同じ
{
"detachKeys": "ctrl-\\"
}
で、下記で起動する。オプションのCOLUMNSやLINESオプションはコンソール上で表示がおかしくなったりする問題の対応。
docker-compose run -e COLUMNS="`tput cols`" -e LINES="`tput lines`" python-container python manage.py shell_plus --print-sql
参考サイト:
tmuxにおけるコマンドによる外部からセッション制御等のメモ
# パネルの指定方法: TestSession:0.0
[SessionName]:[WindowIndex].[PaneIndex]
# SessionName で新たにtmuxセッションをバックグランド(-d)で開始
tmux new -d -s [SessionName]
# SessionName を持つtmuxセッションに対して新規ウインドウをバックグランド(-d)で追加
tmux new-window -d -t [SessionName]
# SessionName を持つtmuxセッションのウインドウ WindowIndex を縦分割(-h)
tmux split-window -h -t [SessionName]:[WindowIndex]
# SessionName を持つtmuxセッションのウインドウ WindowIndex のペイン0にKey入力
# Ctrl-C
tmux send-keys -t [SessionName]:[WindowIndex].0 C-c
# Enter
tmux send-keys -t [SessionName]:[WindowIndex].0 Enter
# "echo 'abcd'"を実行
tmux send-keys -t [SessionName]:[WindowIndex].0 "echo 'abcd'" Enter
特定のセッション(TestSession)のウィンドウ一覧を指定のフォーマットで取得する場合
# #Sはセッション名、#Iはウィンドウインデックス、#Pはペインインデックス
for windex in $(tmux list-windows -F '#S:#I' -t TestSession)
do
echo $windex
done
何故かたまたまSamsungのUWQHD(3440×1440)のS34J550WQCという機種が京东というECサイトにて異常に安かった ので購入した。ただし曲面仕様ではないので若干辛いところだが3万円というありえない価格なので我慢する。
問題がある、横に糞長いこのディスプレイをどのように分割して使うべきかという部分だ。FullHDのときは半々だったが、UWQHDは半々で使うには幅が広いし勿体無い。そこで左に1920のウインドウ、右に残りの幅で割り当てることでFHDとサブディスプレイ的な使い方をすることに決めた。
しかしウインドウのスナップツールがカスタムサイズに対応していないという問題がある。ウインドウを左隅に持ってくと半分のサイズになり、右に持ってくと右半分サイズになるあれだ。
で、作った。上記はスクリーンショットだ、ハッカーみたいで格好良い。 Ubuntuとかなら予めwmctrl とxdotool をaptかなんかで入れておく必要がある。その後、下記のファイルuwsnap.sh をチェックアウトして/usr/local/binなんかに放り込んでchmod +xして欲しい。引数0でアクティブウィンドウが左スナップ、引数1で右スナップになる。
あとは現在使っているWindowManagerのショートカットにでも割り振れば完了だ。自分はCtrl+Shift+LEFT とCtrl+Shift+RIGHT に割り当ててある。
Thinkpad T480s(CPU: i5-8250U / dGPU: GeForce MX150)にUbuntu 18.04.1(Kernel: 4.15.0-44-generic)をインストールしたのだがGPU周りでハマった。
何にハマったのかと言うと、dGPU(GeForce MX150)と内臓GPU(UHD620)の切り替え、協調処理の設定だ。Linuxを利用する場合にIntel以外のGPUは基本的に鬼門だし、ましてやノートPCで外部GPUはハマりまくる。でも(できもしないのに)時代はディープラーニングだし当然(使いもしないのに)CUDAとか欲しかったし、ノートPCなのにハイパフォーマンスとか、普段は内蔵GPUなのに負荷が高いときにdGPUへ処理をオフロードしてブーストするOptimus機能とか厨二病を痛く刺激されたのだ。だって格好良いじゃん。
もちろん余計なことをせずdGPUのみを利用するという方法もある。その場合でも動作自体には大きな問題はないが、なにせノート用とはいえ独立GPUのため消費電力が大きい。つまりバッテリー駆動時間に大きな影響がある。具体的にはT480sに搭載されている低電力版MX150(1D12)はTDP 10Wあり、これがそのままi5-8250UのTDP 15Wに乗ってくると思われ単純計算で1.7倍前後の消費電力となる。つまり駆動時間が約半減するわけだ。これは痛い。
Linuxにおいて消費電力を抑えつつNVIDIAのdGPUを利用する方法は2つある。1つ目はPRIME、2つ目はBumblebeeだ。PRIMEは静的な切り替え、BumblebeeはNVIDIA特有のOptimusをLinuxから利用する技術である。簡単に言うとPRIMEは描画セッション自体を切り替える必要があるが、Bumblebeeは同一のセッション内でもProxyを通してプロセス毎にdGPUと内臓GPUを変更することができる・・・らしい。
Continue Reading »
Bitcoin CoreのChainstateDBの’C’レコードのamount記録時に利用されている謎の圧縮方式 Amount Compressionについてのメモ。
どこで使われているのか?
このAmount Compressionは簡単に言うと、Bitcoinで通貨量の表現に利用されているSatoshi単位の数値のデータサイズを圧縮するという目的の元に作られている。具体的には0を減らして表現するということに主眼が置かれおり大半のtxoutのamount valueが1バイトか2バイトで表現できる(とのことだ)。この奇妙な方式がいつ誰によって導入されたかというと、sipaというコミッターにより2012/6/16に下記のコメントとともにコミットされている。2018/10現在の0.16.3においてはcompressor.cpp以下に存在するが、コミット当時はmain.cppの最下部に追加されている。
Compact serialization for amounts Special serializer/deserializer for amount values. It is optimized for values which have few non-zero digits in decimal representation. Most amounts currently in the txout set take only 1 or 2 bytes to represent.
Compact serialization for amounts · bitcoin/bitcoin@0fa593dhttps://github.com/bitcoin/bitcoin/commit/0fa593d0fb3a6f731a31610e98ce6bfd6a50a96c
また、さらにこの半月後には同じくsipaにより現在のBitcoin Coreにおける内部構造の原型となったUltraprune(ウルトラプルーン)と呼ばれる一連の変更がコミットされている。Ultrapruneの全容についてはまだ理解が追いついていないので改めて書きたいと思うが簡単に言うとUTXOをブロックデータを舐めまわさずとも高速に取得できるようにするための仕組みとデータ構造、実装を含んだフレームワークであり、2012/10/21にIssue:1677 がメインラインに取り込まれた。余談だが、sipa さんは本名Pieter Wuille と言い、金融機関向けサイドチェーンを開発、提供しているBlockstream の創業者のようだ。またSegwitの時のマージも担当している。
Topic: Ultraprune merged in mainline I’ve just merged my “ultraprune” branch into mainline (including Mike’s LevelDB work). This is a very significant change, and all testing is certainly welcome. As a result of this, many pull requests probably don’t apply cleanly anymore. If you need help rebasing them on the new structure, ask me.
Ultraprune merged in mainlinehttps://bitcointalk.org/index.php?topic=119525.0
そのためBitcoin CoreのUTXO管理は
Ultraprune前(ver < 0.08) この当時はブロックやUTXOの管理にBDBをつかってたらしい 初代Ultraprune(0.08 <= ver < 0.15) ここからブロック用、UTXO用のLevelDBの利用が始まる 現行のUltraprune改(0.15 <= ver) これまではvoutが1レコードに複数格納されていたのがTransactionHash+voutIndexをKeyとして、Valueにはブロック高とAmount、hashが格納されることになった。多分obfuscate_keyによるvalueの難読化もここから始まってる。
と変遷していることになる。なお、このUltraprune改のドキュメントはマジで驚くほど少ない。
Amount CompressionのRuby実装と振る舞い
本題に入るとAmount Compressionは下表のような可逆圧縮を行う、基本的には1桁目が0の個数、2桁目以上が0を省いた後の数値の変換値を表現している。
uint64 Compress uint64 Compress 0 0 1 110 992 1 1 1 000 000 000 9 2 11 10 000 000 000 10 9 81 10 000 000 001 9000000001 10 2 10 000 100 000 900006 11 91 153 000 000 1377 100 3 1 530 000 000 1378 1 000 4 1 532 100 000 137886 1 100 93 1 532 123 400 137891103
直感的でなく奇妙な振る舞いをする。 基本的には9桁以下が10で割り切れる数値であれば元の数値よりバイト数を節約できる。一方でどんなに0が多くても1satoshiとかが出現すると圧縮できないどころか桁が増加してしまう。そのため将来Bitcoinがデフレ傾向が続き、マイクロペイメントが主流になった時Ultrapruneも見直しが入るかも知れない。(※まあ実際にはオフチェーンで決済させれてまとまってからオンチェーンになるだろうから心配ないかも) 実装は下記となる。基本的にはBitcoin Coreのcompressor.cppのCompressAmountとDecompressAmountをRubyへ移植しただけである。
以上がAmount CompressionのRuby実装となる。Ultraprune構造等については後日改めて触れてみたい。
ちょっとした募集
諸般の事情からこの場で詳細を書くことは出来ないが、もしこの記事を読んで、BitcoinやEthereumなどのブロックチェーンに興味があり、こいつとフルタイムで一緒に仕事するのも面白いかも知れないという奇特なソフトウェアエンジニアがいたら、about に書いてあるTwitterから是非私に連絡をとってみて欲しい。東京でしかるべく待遇で採用してくれるところを紹介したいと思う。
前回の記事 でLEB128(正しくはUnsignedなのでULEB128)について書いたのだが、そもそも論としてBitcoinCoreで利用されているBase128とは微妙に結果が異なっておりこれはおかしいとBitcoin Core 0.16.3のコードを良く確認するとやはり別物であったので、各表現の整理とBitcoin CoreのBase128のRuby実装を再掲載したいと思う。
Bitcoin Core界隈での奇妙な表現の数々について
Bitcoin界隈では整数の表現について幾つかの特徴的な方法がある。まずコードを全て確認しているわけではないので(マサカリ対策として)全てを網羅していない事を断っておく、その上で現時点で私が認識しているBitcoin界隈での整数表現には下記の3つがある。
BitcoinのプロトコルのVariable Length Integer BitcoinでVarIntと言ったら通常はこれ を指し、Protocol Documentation で定義されている。トランザクションやブロック上のIntのByte表現に利用され符号なし64bit整数まで表現できる。簡単に言うと253未満の数値は1byteで表現し、それ以上は1byte目をtype表現(FD=uint16,FE=uint32,FF=uint64)として利用しlength(1,3,4,9)を決定する。つまり1byte目が0xFCなら252として扱い、0xFDなら更に後続2byte取得して16bit整数として扱い、0xFFなら更に後続8byte取得して64bit整数として扱うということだ。BitcoinCoreで利用しているVarInt BitcoinCoreの内部で利用されているByte表現で、ULEB128類似の方式であるが、こちらはMSBから並ぶのでBigEndianである。あえて言うならUBEB128類似(後述)と言ったところだろうか。基本的には無限のサイズの整数を表現できる方式で整数を7bit毎に分割し最下位の7bitには先頭に0付与し8bit=1byte、それ以外は先頭に1を付与し8bitにした後、8bit目から1を減算(ここが類似という理由) し1byteとしたものを配列として構成した後に結合する。BitcoinCoreで利用しているAmount Compression これは内部的には全てSatoshiなどで表現されるbtcの数量(uint64)を圧縮して表現するための整数変換方式であり0が多いほど返還後の桁数が小さくなる一方で0の存在しない数値は桁が大きくなる。2のVarIntと合わせて利用されることが多い。
1、2は整数をByte表現に変換する方法で3は整数を圧縮する方法である。1についてはWiki自体も分かりやすい上に、プロトコルなので結構色んな所で実装され解説されている。一方で2や3についてはBitcoinCoreの実装の話なので情報が極端に少ないのである。なお3のAmount Compressionについては別な機会に記述したいと思う。
BitcoinCoreのVarIntとULEB128について
さて前回の記事ではULEB128を稚拙なRubyで実装してドヤってしまい大変恥ずかしいのだが、よくよく実行してみると下記の様にBitcoinCoreのVarInt(Base128風)とULEB128の数値が異なっていた。
整数 Hex ULEB128 BC版VarInt 127 0x7f 7f 7f 128 0x80 8001 8000 4660 0x1234 b424 a334 65535 0xffff ffff03 82fe7f 624245 0x98765 e58e26 a58d65
この時ULEB128では下記のような処理を行っている
624485 変換対象整数 → 10011000011101100101 2進数表現 MSB ------------------ LSB
10011000011101100101 2進数表記
010011000011101100101 7bitで割り切れるようにMSB側に0埋め処理
0100110 0001110 1100101 7bit単位で分割
0 0100110 1 0001110 1 1100101 MSB側の最初の7bitの最上位bitには0を付与 それ以外のグループの最上位bitには1を付与1 1100101 1 0001110 0 0100110 バイトオーダーの反転(Little Endianへ変換)
0xE5 0x8E 0x26 16進数表記
→ 0xE5 0x8E 0x26 結合
一方でBC版のVarIntでは下記の様に処理を行っている
MSB ------------------ LSB
10011000011101100101 2進数表記
010011000011101100101 7bitで割り切れるようにMSB側に0埋め処理
0100110 0001110 1100101 7bit単位で分割
1 0100110 1 0001110 0 1100101 7bit単位でMSB側から順に最上位8bit目に 1を付与し、最後には0を付与する 10100101 10001101 01100101 LSBの最終グループ以外から1を引く
0xA5 0x8D 0x65 16進数表記
→ 0xA5 0x8D 0x65 結合
いずれの方式もデコード時はMSB側から1byte毎に読み込み、最上位bitが0になるまで次の読み込みを行う。それぞれ特有の処理(LEB128ではバイトオーダーを反転、BC版VarIntでは最終byte以外に1を加算)を行う。その後双方とも各byteから下位7bitを取得し結合すれば元の値が得られるという仕組みである。 それぞれの実装は下記になる。
ULEB128のRubyによる実装
下記実装だが前回とは異なり、BitcoinCoreのコードを参考にビットシフトで実装してみた。具体的にはエンコード時は対象数値から下位7bitを取得、最上位に1bit付与(0x80をOR)して配列に追加、その後対象数値を7bit下げ最初から処理を繰り返す。なお、配列に追加後に対象数値が0x7F以下であれば(つまり最もMSB側であれば)0x80をXORして最上位bitを0にする。
Bitcoin CoreのVarIntのRubyによる実装
これはもう、BitcoinCoreのC++実装を移植しただけである。ただし7bitずつ取ってくるという処理を論理積とシフトダウンで実装しており非常にシンプルである。C++とかの本物プログラマって凄いんだね。
本当はAmount Compressionについても書きたかったんだけど疲れてしまったので今回はここまでとしたい。
ちょっとした募集
諸般の事情からこの場で詳細を書くことは出来ないが、もしこの記事を読んで、BitcoinやEthereumなどのブロックチェーンに興味があり、こいつとフルタイムで一緒に仕事するのも面白いかも知れないという奇特なソフトウェアエンジニアがいたら、about に書いてあるTwitterから是非私に連絡をとってみて欲しい。東京でしかるべく待遇で採用してくれるところを紹介したいと思う。
Bitcoin CoreのChainstateDB等で使われる可変整数フィールドにBase128 VarIntという表現がある。よく知らなかったのだがこれはLEB128(Little Endian Base 128)と呼ばれ整数をバイト配列にするときに一般的な方式らしい。ChainstateDBにおいてはvoutのインデックスやamountの数値を表現するために利用されている。 (2018/10/7修正、追記)嘘である。Chainstate記録時にBitcoinCoreが用いている方式は正しくはLEB128ではない。改めてこちらの記事 に掲載した。
LEB128 – Wikipedia https://en.wikipedia.org/wiki/LEB128
下記がエンコード処理の実際となる。簡単に言うと、整数を2進数へ変換、7bitで割り切れるように上位に0埋めし分割、さらに7bit毎に最上位に1bit追加(最上位7bitには0、それ以外は1を付与)し8bit毎に16進数に変換し、バイト配列とした後にByte OrderをLittle Endianへ変更する。
624485 変換対象整数 → 10011000011101100101 2進数表現 MSB ------------------ LSB
10011000011101100101 2進数表記
010011000011101100101 7bitで割り切れるようにMSB側に0埋め処理
0100110 0001110 1100101 7bit単位で分割
00100110 10001110 11100101 MSB側の最初の7bitの最上位bitには0を付与 それ以外のグループの最上位bitには1を付与
0x26 0x8E 0xE5 16進数表記
→ 0xE5 0x8E 0x26 Little Endianへ変換(バイトオーダーの反転処理)
なぜこのような紛らわしい処理をしているのかというと、デコード時の利便性を考えてあるようだ。デコード時は1byteずつ読み込みながら1bit目をチェックし0になるまで読み込み続け、0になった時点で読み込みを終了する。あとはエンコード処理を逆転させてやれば復元できる。なおこの読み込み終了判定は読み込んだbyteに0x80をビット積してやった結果が0という記述が可能である。
Rubyによる実装
GemにはLEB128(https://rubygems.org/gems/leb128/versions/0.1.0 )という物が存在しているが、メタ情報が古いのかGemのLEB128は既にGithubのリポジトリ が存在しない。そのためいささか車輪の再発明めいているが、向学の意味も含めて自分で実装してみた。
下記がRubyで実装したコードとなる。https://gist.github.com/muyesh/0e29c9e6d66e801ebe4db3b6c7957768#file-leb128-rb
BitcoinのプロトコルにおけるVarInt表現
なお、紛らわしいことに、BitcoinではTransactionでの可変整数(64bit整数表現)フィールドにも下記のような独自の表現形を持っているため区別が必要だ。
Variable length integer : Protocol documentation – Bitcoin Wiki https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
Value Storage length Format
< 0xFD 1 uint8_t
<= 0xFFFF 3 0xFD followed by the length as uint16_t
<= 0xFFFF FFFF 5 0xFE followed by the length as uint32_t
– 9 0xFF followed by the length as uint64_t
この表現は上位1byteの値からintのサイズを判定し読み込むbyte数を得る。例えば1byte目が0xFD(253)未満であれば、そのbyteの数値を採用し、0xFDの場合は2byte読み込みuint16_tとする。同様に0xFEであればuint32_tとして4byte読み込み、0xFFであればuint64_tとして8byte読み込むと言った具合だ。 最初は何言ってるのかわからなかった。
2019/2/26 追記 Ubuntu 18.04.2ではudevの設定変更が不要なことを確認、下記は16.04以下の場合、またAWSのコンソールへのログインに用いるMFAについても飛天のePassが設定可能になっていた。以前は無理だった。
昨今、なかなか物騒な感じなので2段階認証を導入することも増えている。 ところが2段階認証アプリにはスマホを紛失した時に詰むという重大なリスクがあり日々ドキドキしていたが、Googleなどではハードウェア鍵を2段階認証アプリと併用できると聞き早速導入してみた。
購入したePass FIDO -NFC Security Key: 真ん中の扇部分が青く点滅してタッチを促す
U2F対応製品について
導入したのは飛天ジャパン(https://www.ftsafe.com/ )のePass FIDO-NFCというもので、fido認証のU2Fというグローバル規格(https://fidoalliance.org/?lang=ja )に対応した製品である。親会社は中国の会社で発音としてはフェイティエンとなるがヒテンで問題ないだろうと思う。Amazonで2980円だったので1つ試しに購入してみることにした。特に問題がなければ更にバックアップ用としてもうひとつ準備する予定だ。 このFeitianという会社はそれなりの歴史と採用実績がありfido認証にも加盟しておりかなり有名な組織のため個人的には問題ないと思われるが、製造工程においてシリアル番号を控えて同一の物を複製されていたりする可能性は(この会社に限らず)否定しきれないので、中国製がどうしても嫌な人はYubico(https://www.yubico.com/ )製の物を購入したほうがよいかも知れない。
いずれにしても、この手の鍵製品は流通経路が非常に重要 となるためAmazonで購入する場合は正規代理店やオフィシャルの出品であることを確認するべきである。また動作確認や開発用のためではなく正式に会社などで導入する場合は多少値段が高くなっても正規代理店やメーカーから直接手に入れる事をお勧めする。更にプロダクトの選定にあたってfidoのサイトで商品や会社をチェックしたほうが安心だろう。
FIDO Alliance FIDO® Certified – FIDO Alliance https://fidoalliance.org/certification/fido-certified-products/
Ubuntuへの導入方法
Windowsなどの場合は特に設定は不要と思われるが、UbuntuなどのLinuxにおいてはudevのrulesを記述しておくことが必要となる。これを記述しないとChromeなどがU2Fデバイスにアクセスできない。ただ、全部自分で記述する必要は無く、基本的にはYubicoがサイトで下記のサイトで公開している方法に従えば良い。自分の環境はUbuntu 16.04.5であるが、その他のLinuxでも大差ないと思われる。
Using Your U2F YubiKey with Linux : Yubico Support https://support.yubico.com/support/solutions/articles/15000006449-using-your-u2f-yubikey-with-linux
簡単に言うとGithubにて公開されている下記のファイルを取得して /etc/udev/rules.d 以下に配置するだけで良い。親切なことに、YubicoだけではなくFeitianや、Google謹製(日本未発売)のGoogle Titan U2Fなどのデバイスについても記述してくれているので、メジャーな製品であれば自分でログからidVendorやidProductを確認して追加する必要はないだろう。
libu2f-host/70-u2f.rules at master · Yubico/libu2f-host https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules
なお、Feitian ePass FIDOに対応する部分だけ抜き出すと下記の様になる。今回買った製品のidProductは0858 になる。
ACTION!=”add|change”, GOTO=”u2f_end” # Feitian ePass FIDO KERNEL==”hidraw*”, SUBSYSTEM==”hidraw”, ATTRS{idVendor}==”096e”, ATTRS{idProduct}==”0850|0852|0853|0854|0856|0858|085a|085b”, TAG+=”uaccess” LABEL=”u2f_end”
https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules#L31
以上、これを機にみなさんもハードウェアキーによる2要素認証を導入してみたらどうだろうか?
ここは上海、イエス!チャイナ!
人民が不用意に有害な情報に接することで不愉快な思いをすることがないように国家が防いでくれるという、子離れできないやや過保護気味で歪な親の愛を体現したかのような場所である。まあProxyとかVPNとか通してもよいのだけど、Dockerはイメージも比較的大きいためできることならミラー的なものを使いたい。
はい、そんなときはDaoCloud
このDaoCloudは名前からわかる通り、Dockerイメージをデプロイできるクラウドインフラサービスなのだが、加速器という名前でDockerHubのミラーリポジトリを提供している。
使い方は簡単、まず注册からサインアップし、加速器のメニューを開く。するとDockerのレポジトリにDaoCloudのミラーサイトを設定方法が書かれている。
Linuxの場合は下記のようなワンライナーを教えてくれるが、MacやWindowsは手動で設定を追加する必要がある。要するに、ユーザーごとにサブドメインを割り振ったURLを提供してくれるので、それをミラーレポジトリとして使えということのようだ、そのため下記のワンライナーの場合はサブドメイン部分はXXXXXで伏せてあるので注意して欲しい。
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://XXXXX.m.daocloud.io
なお、細かい設定は下記のサイトにドキュメントが公開されている、中国語で書かれているが技術ドキュメントなのでだいたいわかるだろう。
上記のミラーレポジトリの設定を変更したら、Dockerデーモンの再起動をすれば次回からDockerはDaoCloudのミラーサイトから各種イメージをダウンロードしてくれるはずである。