docker in docker
昼食後は昼寝と言うかうたた寝と言うかシエスタと言うか多層睡眠をする事にしてる。本格的に布団を敷いて寝てしまうと、起きられなくなって しまうので、ソファーにごろり。肘置きを枕にしてね。
で、その昼寝で悲劇が起こった。大惨事。さて、どんな惨事でしょうか? 報告はCMの後で、 とかやっちゃうと、最近とみに酷いTV並みになっちゃうんで、取り合えず想像して楽しんで ください。
寝ぼけてソファーから落っこち、肋骨を折った。長年使ってヘタってきた ソファが壊れて、尻が挟まった?
寝違えて、全治1週間のむち打ち症状。幸いな事に交通事故を喰らって、むち打ち症って経験は 無いんだけど、多分、これがむち打ち症なんだろな。
首が(痛くて)回せません。本を読むのでちょっと頭を下向きに出来ません。女房に呼ばれても首を回せません、体ごと反転させます。首へのコルセットが欲しいとマジで思った次第。でも、じっと我慢。
散歩ぐらいは出来るんだけど、前から来た人に軽く会釈するってのが出来ない。こちらの人は 律儀で、よく頭を下げて挨拶してくれるんだけど、返礼が出来ない。申し訳ない。 いちいち、ただいま、寝違えて首を垂れませんと言うもの馬鹿みたいだしね。
そんなこんなで、難儀な一週間でした。
nc
前回見つけておいたpyftpdlibを使って、マストドン内のファイルをClearLinux側に転送してみる。
clearLinux側で、サーバーを立てて
[clr tmp]$ python3 -m pyftpdlib [I 2017-06-24 16:03:56] >>> starting FTP server on 0.0.0.0:2121, pid=1299 <<< [I 2017-06-24 16:03:56] concurrency model: async [I 2017-06-24 16:03:56] masquerade (NAT) address: None [I 2017-06-24 16:03:56] passive ports: None [I 2017-06-24 16:04:31] 172.18.0.2:47196-[] FTP session opened (connect) [I 2017-06-24 16:04:31] 172.18.0.2:47196-[anonymous] USER 'anonymous' logged in.[I 2017-06-24 16:04:31] 172.18.0.2:47196-[anonymous] FTP session closed (disconnect).
マストドン側からput
/tmp # ftpput -P 2121 -u anonymous -p anonymous 172.18.0.1 secret.log ftpput: unexpected server response to STOR: 550 Not enough privileges.
特権が足りないと言われててもねぇ。送り出し側がrootってのが気に障るのかしらん。 マストドンユーザーにしても、やはり同様エラー。一応 -vを付けてみた。
Connecting to 172.18.0.1 (172.18.0.1:2121) ftpput: cmd (null) (null) ftpput: cmd USER anonymous ftpput: cmd PASS anonymous ftpput: cmd TYPE I (null) ftpput: cmd PASV (null) ftpput: cmd STOR secret.log ftpput: unexpected server response to STOR: 550 Not enough privileges.
PASVがnullって、そりゃないでしょ。
まあ、こういう事もあらーな。強い兵士は、サバイバルできなければいけません。 で、/usr/binの中をじっと観察します。オイラーの琴線に触れるコマンドが見つかりましたよ。 幸い、ClearLinux側にも同様なコマンドが用意されてました。(後で調べたら、BSDにも有る、 標準コマンドでした)
サーバー側(Clear Linux)で待ち受けする。
[clr tmp]$ nc -l -p 1234 > T.txt
そしてクライアント側(mastodon in docker)から送信する。
/tmp # nc -n 172.18.0.1 1234 < T.txt
サーバー側は、データを受信すると、コマンドが自動終了する。これ、面倒なくて便利。
result
前回の続きで、シークレットはどうしてるか? 調べたら、下記の動的ファイルに有った。
vendor/bundle/ruby/2.4.0/gems/railties-5.0.3/lib/rails/tasks/misc.rake
desc 'Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions).' task :secret do require 'securerandom' puts SecureRandom.hex(64) end
もう、追うの止めよう、どんどんと迷宮に入って行く感じがするから。
pyftpdlibの正しい使い方
先に試した、pyftpdlibでftpサーバーを作り、そこにftpputを使ってファイルをアップロード する作戦。パッシブモード問題と瞬間判断したけど、早とちりだな。転送コマンドが出された後に、特権が無いと言ってるから。(年寄りですから、判断が鈍るのね。歳は取りたくないな) 端的に言うと、サーバー側の問題だ。
場所を変えて、Debianで検証してみる。で、困った事が有る。ftpputなんてのが無い。ftpなら 有るんだけど...で、ftpでもいいじゃんと思ってmanするも、ポートは昔から21番と決まってて、任意に設定出来ない。
諦めて、pyftpdlibの__main__.py あたりを見ると、オプションで任意に設定出来るように なってた。21番さんは特権ポートなので、特権を付けて起動。
[debian tmp]$ sudo /home/sakae/conda3/bin/python -m pyftpdlib -p 21
普通のftpを普通に使ってみた。
[debian ob61]$ ftp localhost ftp: connect to address ::1: Connection refused Trying 127.0.0.1... Connected to localhost. 220 pyftpdlib 1.5.2 ready. Name (localhost:sakae): anonymous 331 Username ok, send password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 200 Active data connection established. 125 Data connection already open. Transfer starting. : drwxrwxrwt 2 root root 40 Jun 24 20:19 .font-unix drwx------ 2 sakae sakae 60 Jun 24 20:26 tmux-1000 226 Transfer complete. ftp> put serial local: serial remote: serial 200 Active data connection established. 550 Not enough privileges. ftp> quit 421 Data connection timed out.
サーバー側のデフォルトのdirは、サーバーを起動した(/tmp)場所になってた。で、putして みると、特権足りないぞ、ボケ が、出てきた。
改めて、__main__.py を見直すと
parser.add_option('-p', '--port', type="int", default=2121, metavar="PORT", help="specify port number to run on (default 2121)") parser.add_option('-w', '--write', action="store_true", default=False, help="grants write access for the anonymous user " "(default read-only)")
grantsってSQLのコマンド名に採用されてたな。と言う落ちが待ってましたよ。英語が 分からない君にもヒントって事で、デフォルトでは読み出しだけよって、注意書きも されたたぞ。親切な作者さんだ。これがpython流のおもてなしだな。
実際に-wを付けて起動すると、誰でも書き込めちゃ危ないよと警告が出てきた。putすると、 受け取ったファイル名とそのサイズを報告しつつ、格納してくれたよ。
raspberry pi
数独を解くのに現代風なWolframを使うとかで、雲の向こう側にあるサーバーをアクセス するんだけど、手元にも置いておきたい。何処かにあったなと過去の記憶を辿ると、 去年の夏ぐらいに、ラズパイの真似をした時に出てきてた。あの時は、32Bit版のWindows7 だったので、今回のWindows10でどれだけ速くなったか検証してみる。
Raspberry pi(Raspbian Jessie)を OS X の QEMU で動かす
こんな所を参考に入れてみた。使ったカーネルは下記。
pi@raspberrypi:~$ uname -a Linux raspberrypi 4.4.34+ #3 Thu Dec 1 14:44:23 IST 2016 armv6l GNU/Linux
いざ実行すると、大分待たされたあげぐ、ユーザー登録しろと 言われた。待たされるのは、ブラウザーから登録させようとしてるからかな?
/optの中にあるmathを起動するも、やはりユーザー登録を要求してるっぽい。さして速いとも 思われないので、使うのを断念したよ。
その代わり、qemu-arm-staticを入れて、armの雰囲気だけを味わう事にした。 unameを問うと、amd64と言ってきた。なのに、けなげにarmv61のふりをしてくれてる。 おかげで、ドッカー並みに直ぐに使えるけどね。
[debian RASP]$ ./boot root@debian:/# uname -a Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2 (2017-04-30) armv6l GNU/Linux root@debian:/# cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)" NAME="Raspbian GNU/Linux" VERSION_ID="8" VERSION="8 (jessie)" ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
bootっていう、いかにもな名前を付けてるけど、実態は、 イメージをループマウントしてから、chrootしてるだけ。
[debian RASP]$ cat boot sudo mount -o offset=47185920 170410.img rootfs sudo QEMU_CPU=arm1176 chroot rootfs sudo umount /home/sakae/RASP/rootfs
qemu-aarch64-static なんてのが有って、どうもこれがarm64だと思うんだけど、、、 OSのタスク切り替え処理とaarch64(ARM64)の関数呼び出し規約やっぱり、そうなのね。知らなかったぞ。
docker in docker
ドッカーって、chrootっぽい事をやってないかい? ただ使うだけだと、実態が闇に包まれて しまっているんで、紐解いてみたい。
去年のアドベンドカレンダーに投稿されてたのを参考に、後追いしてみる。
[clr docker]$ make BIND_DIR=. shell : Step 51/51 : COPY . /go/src/github.com/docker/docker ---> 539486b8857a Removing intermediate container 7b121ea28e92 Successfully built 539486b8857a Successfully tagged docker-dev:master docker run --rm -i --privileged -e BUILD_APT_MIRROR -e BUILDFLAGS -e KEEPBUNDLE -e DOCKER_BUILD_ARGS -e DOCKER_BUILD_GOGC -e DOCKER_BUILD_PKGS -e DOCKER_CLI_PATH -e DOCKER_DEBUG -e DOCKER_EXPERIMENTAL -e DOCKER_GITCOMMIT -e DOCKER_GRAPHDRIVER -e DOCKER_INCREMENTAL_BINARY -e DOCKER_PORT -e DOCKER_REMAP_ROOT -e DOCKER_STORAGE_OPTS -e DOCKER_USERLANDPROXY -e TESTDIRS -e TESTFLAGS -e TIMEOUT -e HTTP_PROXY -e HTTPS_PROXY -e NO_PROXY -e http_proxy -e https_proxy -e no_proxy -v "/home/sakae/docker/.:/go/src/github.com/docker/docker/." -v /home/sakae/docker/.git:/go/src/github.com/docker/docker/.git -v "dockerdev-go-pkg-cache-gopath:/go/pkg" -v "dockerdev-go-pkg-cache-goroot-linux_amd64:/usr/local/go/pkg/linux_amd64" -v "dockerdev-go-pkg-cache-goroot-linux_amd64_netgo:/usr/local/go/pkg/linux_amd64_netgo" -t "docker-dev:master" bash root@12579827e63d:/go/src/github.com/docker/docker#
途中、debianの開発環境をごっそり取って来るので、結構時間がかかる。なんたって、51の ステップに分かれて、ごちゃごちゃやりますからねえ。
で、出来上がった物。これでやっとこさdockerを作るための環境が整った。
[clr tmp]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker-dev master 539486b8857a 58 seconds ago 2.34GB debian jessie a25c1eed1c6f 9 days ago 123MB [clr tmp]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 12579827e63d docker-dev:master "hack/dind bash" 2 minutes ago Up 2 minutes nostalgic_noether
次は、いよいよバイナリーを作るとな。
root@12579827e63d:/go/src/github.com/docker/docker# hack/make.sh binary ---> Making bundle: binary (in bundles/17.06.0-dev/binary) Building: bundles/17.06.0-dev/binary-daemon/dockerd-17.06.0-dev Created binary: bundles/17.06.0-dev/binary-daemon/dockerd-17.06.0-dev Copying nested executables into bundles/17.06.0-dev/binary-daemon
後は、成果物を確認。
root@12579827e63d:/go/src/github.com/docker/docker/bundles/17.06.0-dev/binary-daemon# ls -l dockerd lrwxrwxrwx 1 root root 19 Jun 25 07:30 dockerd -> dockerd-17.06.0-dev
実体の方を /usr/bin/dockerd として、コピーしておいた。 そして、いよいよ起動。
root@12579827e63d:/go/src/github.com/docker/docker# dockerd -D & [1] 4087 root@12579827e63d:/go/src/github.com/docker/docker# DEBU[0000] Listener created for HTTP on unix (/var/run/docker.sock) INFO[0000] libcontainerd: new containerd process, pid: 4092 DEBU[0000] containerd: grpc api on /var/run/docker/libcontainerd/docker-containe rd.sock : DEBU[0001] Registering POST, /networks/prune DEBU[0001] Registering DELETE, /networks/{id:.*} INFO[0001] API listen on /var/run/docker.sock
そして、動作確認の一歩目。
root@12579827e63d:/go/src/github.com/docker/docker# docker version DEBU[0302] Calling GET /_ping DEBU[0302] Calling GET /v1.30/version Client: Version: unknown-version API version: 1.30 Go version: go1.8.3 Git commit: unknown-commit Built: unknown-buildtime OS/Arch: linux/amd64 Server: Version: 17.06.0-dev API version: 1.31 (minimum version 1.12) Go version: go1.8.3 Git commit: 4f259698b Built: Sat Jun 25 07:08:22 2017 OS/Arch: linux/amd64 Experimental: false
心配だった docker は、/usr/local/bin の下に用意されてたぞ。バージョン不明って言ってるで、 今回作られたものじゃなく、debianと共にやって来たものかな?
第2歩目は、お約束のハロワとalpineです。
root@12579827e63d:~# docker ps -a DEBU[1935] Calling GET /_ping DEBU[1935] Calling GET /v1.30/containers/json?all=1 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 415f0300b1b0 alpine "/bin/ash" 3 minutes ago Exited (0) 2 minutes ago nervous_boyd 98d68bfb4b99 hello-world "/hello" 7 minutes ago Exited (0) 7 minutes ago eloquent_hermann
ちゃんと動きました。
docker service
ClearLinux側のdockerdって、どんな風に起動してるか、調べてみる。手がかりは、登録時に 出て来るあれ。
[clr ~]# systemctl enable docker Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
そして、docker.serviceの仕様書になるかな。
[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target docker.socket firewalld.service Wants=network-online.target Requires=docker.socket [Service] Type=notify ExecStart=/usr/bin/dockerd -H fd:// --storage-driver=overlay ExecReload=/bin/kill -s HUP $MAINPID LimitNPROC=infinity LimitCORE=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target
こちらは、同じ所にあった、docket.socket
[Unit] Description=Docker Socket for the API PartOf=docker.service [Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target
コピペの作法
よくWebに掲載されてるコードをコピペして試す事が有る。コピペ用の台紙は、viなりemacsの 白紙のページって事が多い。
コードがpython語とかhaskell語みたいに、レイアウト命って場合は、都合が悪い事が発生 する場合が有る。前行のレイアウトを見て、editorが勝手にレイアウトを変更してしまう事が 有るんだ。そんな場合はどうするか?
答えは、editor画面に張り付けるな。奴らはインテリジェント過ぎるから。
[clr tmp]$ cat -- > hoge.py : ;; ペーストする Ctl+d ;; 終了
常識だったら、スマソ。
これも常識っぽいけど、 以前出て来た あらゆる数独パズルを解く を、ipython上で試そうとすると
In [1]: import sudoku In [2]: grid1 = '003020600900305001001806400008102900700000008006708200002609500 ...: 800203009005010300' In [3]: display(parse_grid(grid1)) --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-4-5b55b305dbdd> in <module>() ----> 1 display(parse_grid(grid1)) NameError: name 'parse_grid' is not defined
と、何も考えないコピペ野郎は、怒られるのであります。で、少しは頭を使って
In [1]: from sudoku import * In [2]: grid1 = '003020600900305001001806400008102900700000008006708200002609500 ...: 800203009005010300' In [3]: display(parse_grid(grid1)) 4 8 3 |9 2 1 |6 5 7 9 6 7 |3 4 5 |8 2 1 2 5 1 |8 7 6 |4 9 3 ------+------+------ 5 4 8 |1 3 2 |9 7 6 7 2 9 |5 6 4 |1 3 8 1 3 6 |7 9 8 |2 4 5 ------+------+------ 3 7 2 |6 8 9 |5 1 4 8 1 4 |2 5 3 |7 6 9 6 9 5 |4 1 7 |3 8 2
何とか、切り抜けられました。
clear Linux + miniconda3
VBOXに入れたclear Linuxでもグラフを書きたい。常用してるのはgnuplotなんだけど、 そんなのバンドルに入っていない。そこで、バッテリーであるminiconda3を入れました。
下記のように、設定。
sakae@clr:~$ cat /etc/ssh/sshd_config X11Forwarding=yes sakae@clr:~$ echo $DISPLAY localhost:10.0
テストスクリプト。最後にshowが無いと、描画されないので注意。
sakae@clr:~$ cat t.py import numpy as np import matplotlib.pyplot as plt plt.hist(np.random.randn(1000)) plt.show()
ipythonにrunコマンドが有った事を思い出した。
sakae@clr:~$ ipython Python 3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:09:58) Type 'copyright', 'credits' or 'license' for more information IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: run t.py QXcbConnection: XCB error: 145 (Unknown), sequence: 165, resource id: 0, major code: 139 (Unknown), minor code: 20
どきっとするようなメッセージを表示しつつも、ヒストグラム図が表示されたぞ。