2018/12/07

ReFe + ref.vim で Neovim から Ruby の document を読む

この記事は Okinawa.rb Advent Calendar 2018 の 7 日目の記事です。
昨日の記事は @hanachin_ さんの 『refineをしてるモジュール取り出せるrefinements_robbery gem』 でした。


なにができるの

カーソルが指している(クラス|メソッド)名のドキュメントが一発で引けます。
これが
こうじゃ

的な感じ。


環境

OS: macOS Sierra 10.12.6
Neovim: 0.3.1
ReFe: 2
Ruby: 2.5.3p105 (2018-10-18 revision 65156)
vim-ref: b45d10f6d0c82e3afd17774626e952fde03274a1



NeoVim + vim-ref

私の環境では NeoVim を使っていますが、Vim でもおそらく動くはずです。
vim-ref というリファレンスを読むのに便利なツールがあり、2014年あたりから私は活用させてもらっています


ReFe 2

クラス名かメソッド名を指定すると該当するドキュメントを表示してくれるツールです。


ReFe + vim-ref

さて。この二つを組み合せていきます。

  • $ bitclust setup
で refe を使えるようにします。
この時点で
  • $ refe Integer
とするだけで

のように表示できます。便利。

ちなみに vim-ref は plugin を入れると refe に関しては設定無しでも動きます。
normal mode で K を押すだけ。便利便利。


まとめ

ということで vim-ref を使って ReFe 2 を引くお話でした。
ちなみに vim-ref で開いた buffer 内のワードでも refe を引けるので、色々と探検できたりします。
後、地味な利点としてオフラインでもドキュメントが見られる点があります。
快適な Ruby ライフをー

2018/10/31

tmux 2.8 を全角記号対応させる

ということで恒例の分割線を EastAsianAmbiguous から ascii の線に変更するバージョンを作成。
2.7 の時とか 2.6 の時とかの作業履歴とかもまとめてあります。
そもそもどういう問題なのかはこの記事で。


環境

  • macOS Sierra 10.12.6
  • tmux: 2.8-border-ascii (4283f6b6e3f3c46b8665ce398a164063a7ef0aab)
  • utf8proc: 2.1(562edab805b82d66622914d06a5da3f53cd54a17)
  • Homebrew: 1.8.0-76-gcbb2e1b
  • Homebrew/homebrew-core: (git revision 95614; last commit 2018-10-30)
  • Ricty: 3.2.2(no option)


作業

今回は割とあっさりできました。cherry-pick して tag 更新して終わり。
  • $ git pull upstream
  • $ git checkout 2.8
  • $ git cherry-pick border-ascii
  • $ git checkout -b 2.8-border-ascii
くらい。

make できるかの確認は
  • $ sh autogen.sh
  • $ ./configure --enable-utf8proc
  • $ make
くらいで。

current directory に tmux command ができるので、動作確認とかもできます。
  • $ ./tmux -V
    • tmux 2.8
  • $ ./tmux
    • border-ascii 版の tmux が起動します。
あとは自分用の tap に反映しておしまい。


インストール方法

1からインストールする場合のコマンドは
  • $ brew tap atton/customs
  • $ brew install atton/customs/utf8proc
  • $ brew install --HEAD atton/customs/tmux
でいけます。


ぼやき

これで分割時の線が ascii になりました。良し良し。

自分用にメンテし続けてるけれど、tui を使う時とかはどうしても崩れてしまう。
特定の文字を表示する時かけられる hook があれば、置換表を config に書くと tui も問題無く表示できるとは思うのだけれど、そんなの無いかなー。

2018/09/13

ISUCON7の予選問題を解いて、スコアを27万点まで上げた

こんにちは。フリーランスのエンジニアのあっとんです。
仕事が一段落したのもあってプチ夏休みという名の仕事が無い期間、ISUCON7 の予選問題をやったりしました。
それを改めてログにまとめる次第です。

結論から言えば、予選突破のボーダーの21万点を越えられました。
ちなみに累計作業時間は58時間くらいで、最終スコアは 270957 でした。
あとリモートワークのお仕事を募集中(2018/09/13現在)です。


どうして ISUCON の問題を触ってみようと思ったのか

  • Twitter でたまに見た単語で気になっていたので
  • ミドルウェアをインストールする事はあってもガリガリにチューニングする経験が無かったので
  • とりあえず数字で善し悪しが分かるので


自分レギュレーションと目標とか

  • スコア的な目標は予選突破ボーダー(21万点くらい)
  • とりあえず最初(ISUCON7予選)はブログとか見て良いのでノウハウを積む
  • ノウハウを積んだ上で本戦問題を時間制限+解説見ずに解く


環境構築とベンチマーカを動かす

まずは環境構築から。
とりあえず GCP の上に 4core 8GB の instance を上げる。
ISUCON7 の予選問題の README.md に従って環境構築。
初期スコアは5000点くらいだったと思います。
ベンチマークをかける側も 4core 8GB で環境構築。


なんとなくの知識で高速化をする

とりあえず知ってる範囲で適当に進めていく。
  • nginx の proxy を経由せずに直接 puma で 80番を bind するように
    • スコアが 3000 くらいになる。 却下。
  • rackup する時に environment を production にする
  • logger を無しにして log を disk に書かないようにする
    • 一応スコアが 5980 くらいにはなる
  • css と js を minify する
    • yui-compressor なるものを使う
    • $ yui-compressor main.css -o minimain.css # とか
    • Validation に失敗するのでこの手は使えない
  • gzip で圧縮してみる
    • .gz を置いて配る
    • そんなにスコアが変わんなかった
  • N+1 を解決したいが SET IN ... に書き換えるのが面倒
    • 普段 ActiveRecord を使っていたので includes で解決して欲しい……
    • (後から結局 sinatra-activerecord を入れることになる)
  • SELECT * の結果に対して first していた部分に LIMIT 1 を付ける
    • 1万点くらいになる
  • メモリの上に DB の全データを載せる
    • tmpfs + rsync で載せてしまう
    • 19340 点になる。倍。
  • mysql の log の WARN を取り除く
    • 22511 点になる。10%増し。


予測するな計測せよ

結局何が一番のネックなのかが分からないとどうしようもない。
ということで計測していく。
profiling には rack-mini-profiler を使ってみた。
さてこれでどこがネックなのか探るか、と思ったら作成されたファイルが読めない。
結論から言えばファイルに書く前に Marshal.dump されているせいで Marshal.load しないと読めなかった。
Marshal.dump を JSON.dump に monkey patch して無理に plain text にして jq で読む。
しかしファイルが多すぎて(200個とか)まともに読めない。
profiler を使うのは諦めて top だけで行くというゴリ押しをする。
(rack-mini-profiler を rack application で動かす、というのも記事にできそうなので後から書くかもしれない)
なお、初期の段階でベンチマークをかけると CPU を mysql が 55% 、puma が 35% くらい食っていて DB ネックだった。


参考文献を参照開始


1Core 1GB にスペックダウン



11万あたりの伸び悩み

その後もチマチマと変更を加えるものの、12万点の壁は越えられず。
CPU使用率も合計100%にならなくなった。
気付くのに結構かかってしまったけれど、オチとしてはメモリ不足。
具体的には残り10k とかになっていた。
というわけでここからは複数台構成にする。


複数台構成



lsyncd を使って画像の同期

解決すべき問題は icons を3台の間でどう整合性を取って返すか。
業務だったら S3 に置くなり CDN を使うのが良さそう。
しかし ISUCON なので、手元にあるサーバでどうにかする必要がある。
画像ファイル自体は1MB以下なのが保証されている。
なので書き込み時に memcached じゃなくて全サーバに書き込むことに。
そうすれば /icons を nginx が Cache-Control 付きで返してくれて良さそう。
(nfs で mount しても良かったのですが、結局 network access が発生するので早くならなそうだったので断念。)
(nfs の cache の config でどうにかなった可能性もゼロではないが……)
最初は inotify + rsync でゴリ押ししようと思ったのですが、 lsyncd なるものを発見
(rdiff-backup とか osync とか csync2 とか unison とか mirror とかあるがどれも古い)
サーバA は更新があったらサーバB に rsync。 B は C へ。 C は A へ。という形に。
これでファイルが upload されたら全サーバが共通のファイルを返せる。
結果、1台だけの時にスコアが 69770 に。3倍にできれば目標達成かな。


最終的な構成

3台 nginx にするより、2台 nginx + DB のがスコアが高かった。
あと mysqltuner というスクリプトを見つけて、それで値を調整。
最終的には score 270957 を達成したので脳内予選突破。



まとめ

  • ISUCON7 の予選問題のスコアを 27 万点くらいまで上げました。
  • 作業ノートによると58時間くらいかかっているらしい。
  • これで夏休みの自由研究2018としましょうか。



参考

2018/07/22

Docker Registry の backup と restore

前回は Image の Backup/Restore について書きました。
これで Image を指定してバックアップ可能になったのですが、Registry に登録される Image が1つとは限らない。
ということで Docker Registry ごと全イメージをバックアップしてみる。


環境

  • OS: CentOS Linux release 7.4.1708 (Core)
  • Docker: version 1.13.1, build 774336d/1.13.1
  • Kernel: 3.10.0-693.5.2.el7.x86_64


Docker Registry を tar にする

さて、Registry はコンテナ内部に登録イメージのファイルを持ってます。
ファイルごとバックアップを取りたいので、戦略としてはコンテナのバックアップを取る。
今度使うのは docker export コマンド

  • $ docker run -d -p 5000:5000 --name registry registry:latest
  • $ docker push hogehoge
  • $ docker export registry > registry-backup.tar
これで Registry のコンテナが tar ファイルになります。


Docker Registry を復元する

さて、 tar ファイルから復元したいと思います。
  • $ docker import - registry:latest < registry-backup.tar
今回はタグの情報とかは無いので自分で指定する。
というかコンテナからイメージを作るので実質 docker commit みたいなものか。

tar から作られた registry:latest を実行します。
  • $ docker run -d -p 5000:5000 --name registry registry:latest
お? 動かない。 
/usr/bin/docker-current: Error response from daemon: No command specified.
と言ってくる。CMD の情報が吹っ飛んでるのか。
Github にある Registry の Dockerfile を見ると、'docker-registry' とすれば良いかな。
  • $ docker run -d -p 5000:5000 --name registry registry:latest docker-registry
動かない。今度は
/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"docker-registry\": executable file not found in $PATH
か。そんなコマンドは無いらしい。 
もうコンテナ内に入ってしまうかな。export 前の registry に対して
  • $ docker exec -it registry bash
すると
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"bash\": executable file not found in $PATH"
おお、bash すら無いのか。sh も無ければ最早 user interactive に何もできないコンテナだ。

  • $ docker exec -it registry sh
流石に sh はありました。find もある。
find で docker-registry を探しても無い。
他に探索していると registry というのが /bin/registry にあった。
実行すると serve か garbage-collect と help がサブコマンドにある。serve してみます。
  • $ registry serve
文句言ってきました。具体的には
configuration error: configuration path unspecified
と。 docker-registry の configuration path って何だろう。
どこかに mount してたらそれを参照してくれるから設定変更可能、とかそういう意図なんだろうか。

とかとか、いろいろ試した結果、ps で path が分かりました。
Process ID 1 のやつが
registry serve /etc/docker/registry/config.yml
で動いていました。
と、いうことで、実行するコマンドは
$ docker run -d -p 5000:5000 --name registry registry:latest registry serve /etc/docker/registry/config.yml
で Import した Registry を復元できました。やったね。


おまけ

/etc/docker/registry/config.yml を読むと storage.filesystem.rootdirectory が /var/lib/registry
だったので、run する時に -v で /var/lib/registry に Host の Directory を mount しておけば Image の保存が楽だった説が。

それと、Docker EE だと、 DTR (Docekr Trusted Registry) の backup/restore 手順が提供されています
きちんとサポートを受けたい場合は Docker EE を使うのもアリかも。


参考

2018/07/15

Docker Image の backup と restore

さて、Docker Registry を立てたは良いものの、マシンが壊れたりすると悲しい事態になります。
Build 元と Registry で二重になってはいるのですが、両方が同じマシンだと悲しい事態が発生する可能性がありますね。
と、いうことで Build した Docker の Image をファイルに書き出したり、そのファイルからイメージを復元します。


環境

  • OS: CentOS Linux release 7.4.1708 (Core)
  • Docker: version 1.13.1, build 774336d/1.13.1
  • Kernel: 3.10.0-693.5.2.el7.x86_64


Docker Image をファイルへバックアップする

Docker そのものはファイル群を /var/lib/docker の下に持ってます。
Image は default だと overlay2 で作成されます。
overlay2 は差分でファイルを管理するファイルシステムなので、そういったメタ情報もバックアップしないといけない。
つまりは cp とか rsync だと事故る可能性があります。

さて、何を使うのが正しいかと言えば公式です。具体的には docker save コマンド
Image を構成する全レイヤをきちんと tar に書き出してくれます。
実行例として、hogehoge Image をバックアップするのはこんな感じ。
  • $ docker image save hogehoge > backup.tar
この tar をバックアップ先 HDD 等に持っていけば良い。


Docker Image をファイルから復元する

バックアップする方法は分かりました。
次はバックアップからの復元。
docker load コマンドを使います。具体的には
  • $ docker image load < backup.tar
で終わり。
Image の repository name や tag も tar に入っているので、それらの情報も全部復元されます。楽。


参考

2018/07/08

自前の Docker Registry を Systemd で管理する

前回の記事では自前で Docker Registry を立ててみました。
ですが、これだと docker run しただけなので、マシンを再起動すると上がってこない。
ということで systemd の unit にしてしまって自動起動させるようにしました。


環境

  • OS: CentOS Linux release 7.4.1708 (Core)
  • Docker: version 1.13.1, build 774336d/1.13.1
  • Kernel: 3.10.0-693.5.2.el7.x86_64


systemd の unit を書く

ググると誰かが書いた unit がいくつかヒットしました。これとかこれとか。
これらを参考に unit を書きます。とはいっても、考慮する具体的な内容は
  • registry の container の name は決めうち
    • unit を書くのを楽にするため
    • volume は面倒なので mount しない
  • registry の dependency には docker がある
    • サービスの起動順番の指定
くらいのものです。

ということで、できたのが
です。こいつを
  • /usr/lib/systemd/system/docker-registry.service
に配置。それから怒涛の systemctl 。
  • $ sudo systemctl daemon-reload
    • unit の reload で認識させる
  • $ sudo systemctl start docker-registry
    • systemd 経由で docker-registry を起動してみる。
    • docker ps するときちんと生きてます。
  • $ sudo systemctl restart docker
    • docker を再起動してもちゃんと生きてる。
    • dependency の設定も上手くいってそうです。
  • $ sudo systemctl enable docker-registry
    • んで、マシン起動時に起動するように
  • $ sudo reboot
    • そして再起動。
    • 再起動後にもきちんと registry が上がってました。良し良し。

ってな感じで再起動しても docker-registry が上がるようになりました。
めでたしめでたし。


参考

2018/07/01

自前の Docker Registry を立てて、 Build した Image を保存する

さて、Docker を使っていて Image を作った後、他の人に配るにはいくつか方法があります。
export/import したりとか、dockerhub に置いたりとか、自前で Registry を立てたりとか。
今回は自前で Docker Registry を立ててみようと思います。


環境(docker client と registry server の両方は同じ環境)

  • OS: CentOS Linux release 7.4.1708 (Core)
  • Docker: version 1.13.1, build 774336d/1.13.1
  • Kernel: 3.10.0-693.5.2.el7.x86_64


Registry を立てる

Image が提供されているのでコマンド一発でおしまい。
  • registry-server$ docker run -d -p 5000:5000 --name registry registry:2
便利ですね。


Config とか

立てるのは簡単ですが、外から使うにはいくつか設定がいります。
まずは firewall で 5000 番を開放します。
  • registry-server$ sudo firewall-cmd --add-port=5000/tcp --permanent
  • registry-server$ sudo firewall-cmd --reload
これでOK。ということで push してみましょう。
  • docker-client$ docker image tag hoge 192.168.0.1:5000/hoge
  • docker-client$ docker push 192.168.0.1:5000
怒られます。
Get https://192.168.0.1:5000/v1/_ping: http: server gave HTTP response to HTTPS client
クライアント側が https で繋ぎにいってるのに http を返してきてる、と。
調べたところ、http でアクセスする registry と指定すれば良いらしいです。

と、いうことで指示通りに /etc/docker/daemon.json に書く。
  • docker-client$ sudo echo '{ "insecure-registries":["192.168.0.1:5000"] }' > /etc/docker/daemon.json
  • docker-client$ sytemctl restart docker
  • docker-client$ docker push 192.168.0.1:5000
これで通りました。良し良し。

今日日 https 必須感もありますし、https にするのが正しい気もしますが、動いたのでまずは一段落。


参考

2018/06/24

docker build で作成した image の layer を統合してサイズを縮小する

Docker で Dockerfile を書いて image を build すると、 RUN したコマンド毎に layer ができます。
結果、次回 build 時にコマンドを再実行せず、layer を cache として使って build 時間の短縮ができます。
また、build に失敗した場合でも、layer の id を指定して docker run して原因特定、などができます。
などなど、 RUN ごとに layer を作成することには多くのメリットがあります。
ですが、'毎回 layer を作成する == 全コマンド結果保存' ということでもあるので、image のサイズが大きくなります。

ビルドする側からすると、全 layer を保存しても問題無いと思います。
ですが、ダウンロードする側、特に何度もダウンロードが発生する場合はサイズが小さいほど良い。
例えば dockerhub にイメージを登録する場合がありますね。
image 作成過程の試行錯誤を dockerhub に登録して、ダウンロード容量が大きくなるとよろしくない。

と、いうことで、layer を統合してサイズを抑えてみます。


環境

  • OS: macOS Sierra 10.12.6
  • Docker for mac: 18.03.1-ce, build 9ee9f40


export/import

と、言ったはものの、同じ考えをしている方がまとめていました
export/import すれば layer を統合できます。
統合というか結果的に1 layer になる、という言い方が正確です。
具体的なコマンドはこんな感じ。
  • $ docker run -itd --name nya big-image
  • $ docker export nya > nya.tar
  • $ cat nya.tar | docker import - big-image-single:latest
今回試してみた image では、57 layers(13GB) -> 1 layer(9GB) になりました。
イメージの性質による思いますが、なかなか効果がありますね。
ちなみに、image save/image import をすると全 layer 含めて export するので縮小はできません。


参考

2018/06/17

Mac に fontforge を直接入れずに Docker を使って Ricty を作成する

私は普段 Terminal で作業する時、フォントは Ricty を使っています。
Ricty は Inconsolata と Migu 1M の合成フォントで、生成スクリプトが公開されています。
合成には fontforge を使うのですが、 brew で入れると結構な数の依存パッケージが入ります。
fontforge  は普段使いしていないので、おそらく Ricty の生成以外に使わない。
なので Mac に直接 fontforge を入れず、コンテナに入れて合成してみます。


環境

  • OS: macOS Sierra 10.12.6
  • Docker for mac: 18.03.1-ce, build 9ee9f40
    • Distribution: CentOS Linux release 7.4.1708 (Core)
    • fontforge: 20120731
  • Ricty: 4.1.1
    • Inconsolata: v2.001
    • Migu 1M: 20150712


mac 側の事前準備(ダウンロード)

事前にダウンロードが必要なのはフォント2つ。
具体的には Inconsolata と Migu 1M の .ttf ファイルです。
加えて、Ricty の生成スクリプト ricty_generator.sh もダウンロードしておきます。
Migu 1M は unzip して、とりあえず全ファイルを ~/Downloads へ mv。

最終的な ~/Downloads はこんな感じになりました。
$ ls Downloads
Inconsolata-Bold.ttf  Inconsolata-Regular.ttf  ipag00303  migu-1m-bold.ttf  migu-1m-regular.ttf  migu-README.txt  mplus-TESTFLIGHT-060  ricty_generator.sh


Docker に ~/Downloads を mount して合成

さて、合成に必要なファイル群は ~/Downloads に集まりました。
これを mount したコンテナを立ち上げて合成します。

具体的なコマンドはこんな感じ。run に渡す用のスクリプトを書いた方がスマートかも。
  • $ docker run -v ~/Downloads/:/root/fonts -it centos:7
    • # yum install -y fontforge
    • # cd /root/fonts
    • # chmod u+x ricty_generator.sh
    • # ./ricty_generator.sh -n 4.1.1 Inconsolata-{Regular,Bold}.ttf migu-1m-{regular,bold}.ttf
生成されたフォントにバージョン番号を付けておきたいので、 "-n 4.1.1" オプションを指定しておきます。
実行した結果、~/Downloads はこんな感じになりました。
$ ls ~/Downloads
Inconsolata-Bold.ttf Inconsolata-Regular.ttf Ricty4.1.1-Bold.ttf Ricty4.1.1-BoldOblique.ttf
Ricty4.1.1-Oblique.ttf Ricty4.1.1-Regular.ttf Ricty4.1.1Discord-Bold.ttf
Ricty4.1.1Discord-BoldOblique.ttf Ricty4.1.1Discord-Oblique.ttf Ricty4.1.1Discord-Regular.ttf
ipag00303 migu-1m-bold.ttf migu-1m-regular.ttf migu-README.txt mplus-TESTFLIGHT-060
ricty_generator.sh
きちんと生成されていますね。良し良し。

2018/06/10

Docker Universal Control Plane を CentOS7 で起動してみる

前回の記事では CentOS7 に Docker EE を入れました
さて、何故入れたかと言えば Docker Universal Control Plane(UCP) を使ってみたかったからです。

Unix User を dockergroup に所属させることで、複数のユーザが root でなくても docker を利用できます。
しかし、他人が run した container に attach 可能。場合によってはよろしくない。
何か解決策が無いかと調べたところ UCP を見付けました。

UCP には Permission Control があって、Full Control の権限をユーザに与えても
The user can view and edit volumes, networks, and images, They can create containers without any restriction, but can't see other users' containers.
とのことで、別のユーザのコンテナは見られない。
なので、root でない複数ユーザが、相互に干渉せず docker を使えそうです。


環境

  • OS: CentOS Linux release 7.4.1708 (Core)
  • Kernel: 3.10.0-693.5.2.el7.x86_64
  • Docker: docker-ee-17.03.0.ee.1-1.el7.centos.x86_64
  • Docker Universal Control Plane: 2.2.6


run UCP

公式の document に従って UCP のイメージを run します。
  • $ docker image pull docker/ucp:2.2.6
  • $ docker container run --rm -it --name ucp -v /var/run/docker.sock:/var/run/docker.sock docker/ucp:2.2.6 install --host-address 127.0.0.1 --interactive
    • --interactive が付いてるので適宜入力します
    • 具体的には Admin username や password とかですね
さてこれで起動……しません。
INFO[0000] Initializing a new swarm at 127.0.0.1     
FATA[0034] the following required ports are blocked on your host: 12385, 12376, 12383, 443, 12384, 12379, 12387, 12386, 12381, 12382, 2376, 12380.  Check your firewall settings 
と言われました。おお、結構な数の port 使うな。

ということで firewall に穴を開けます。
  • # for i in 12376 4789 12386 2376 443 12381 12380 12382 12383 12384 12385 12379 12387 ; firewall-cmd --add-port=$i/tcp --permanent
  • # firewall-cmd --reload
くらいかな。

そして再度 run してみる。今度は
FATA[0031] The following required ports are already in use on your host - 2377.  You may specify an alternative port number to 2377 with the --swarm-port argument.
と言われた。あれ。何が 2377 使ってるんだ?
  • $ netstat -lntp
すると確かに 2377 が listen になってる。 process name は dockerd か。

結論から言うと、一回目で起動した swarm が生きてたのが原因でした。なので
  • $ docker swarm leave --force
して抜ける。さて三度目のトライ。コマンドは変わらず
  • $ docker run -it --rm --name ucp -v /var/run/docker.sock:/var/run/docker.sock docker/ucp:2.2.6 install --interactive
で実行します。お、起動したっぽいですね。三度目の正直。
INFO[0007] Generating UCP Client Root CA
INFO[0007] Deploying UCP Service
INFO[0035] Installation completed on raven (node abcdefghijklmnopqrstuvwxy)
...
INFO[0035] Login to UCP at https://127.0.0.1:443
https//127.0.0.1 にアクセスすると UCP の画面が出てきました。ログインも可能。良し良し。


参考

2018/06/03

Docker EE を CentOS 7 に install する

Enterprise Edition の Docker を CentOS 7 に入れてみたのでそのメモ


環境

  • OS: CentOS Linux release 7.4.1708 (Core)
  • Kernel: 3.10.0-693.5.2.el7.x86_64
  • Docker: docker-ee-17.03.0.ee.1-1.el7.centos.x86_64


yum-config-manager --add-repo

まずは公式のドキュメントに従います。
Enterprise Edition の Docker は無料では使えないので、 subscription を買う必要があります。
なのですが、一ヶ月無料お試しもできるので、s

trial が始まるとユーザアカウント固有の URL が貰えます。
  • $ export DOCKERURL="<DOCKER-EE-URL>"
のところですね。ちなみに具体的なURL は
  • $ export DOCKERURL='https://storebits.docker.com/ee/centos/<uuid>'
でした。たぶん uuid は user ごとに違いそうなのでここには書きません。

DOCKERURL も分かったので、後は公式ドキュメント指示通りに続けます。
  • $ sudo -E sh -c 'echo "$DOCKERURL/rhel" > /etc/yum/vars/dockerurl'
  • $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
  • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/rhel/docker-ee.repo"
  • $ sudo yum -y install docker-ee
でインストール……されないですね。
[Errno 14] curl#6 - "Could not resolve host: storebits.docker.com; Unknown error"
と言ってきますが、 dig では storebits.docker.com は返ってくる。謎。


DOCKERURL

結論から言うと、 DOCKERURL が間違っていました。
RHEL のドキュメントの DOCKERURL は
  • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/rhel/docker-ee.repo"
ですが、store.docker.com から提供された URL は
  • https://storebits.docker.com/ee/centos/<uuid>
なので、どうも帳尻が合っていない。
いろいろ試した結果、 CentOS 用のキュメントは RHEL とは別にありました。
おお、そこまで区別してるのか。 sensitive だ。

ということで CentOS 用のドキュメントに従って
  • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/centos/docker-ee.repo"
  • $ sudo yum -y install docker-ee
で Install できました。良し。


おまけ: docker-ee.repo

ちなみに DOCKERURL をブラウザで開くとファイル一覧が見られます。
ちょっと見た結果 yum の repo と rpm が置かれていました。
にしても、 yum の repo の仕様なのか、 docker-ee.repo が
  • DOCKERURL/docker-ee.repo
  • DOCKERURL/centos/docker-ee.repo
みたいに2つあって、どっちが正しいのか悩んだり。両方とも正しい可能性もあるな。



参考

2018/05/27

Oracle Java SE 8 JDK を CLI で Install する

さて、Java を CLI でインストールしたい時があります。
例えば Docker の Image を作る時などですね。 Dockerfile に書きたい。
OpenJDK ならば yum や apt-get で Install できるのですが、Oracle の JDK だとそうはいかない。
なので、作業ログを残しておこうかと思います。


環境

  • macOS Sierra: 10.12.6
  • Docker for mac: version 18.03.0-ce, build 0520e24
  • Base Image: ubuntu:16.04
  • Oracle JDK: 1.8(build 1.8.0_161-b12)


ppa:webupd8team repository

Oracle JDK を公式のサイトから落っことしてきても良いのですが、zip と rpm しか無い。
Ubuntu の dpkg で install したいので deb ファイルが欲しい。
どうも調べてみると、 apt の追加 repository にあるらしい

ので追加して Install してみる。
  • apt-get install -y software-properties-common # install apt-add-repository command 
  • apt-add-repository -y ppa:webupd8team/java
  • apt-get update
  • apt-get install -y oracle-java8-installer
License に同意するか聞かれるので yes 。そうしたら Install される。


License Agreement with debconf

License に同意する部分には stdin に yes と入れたら済むだろう、ということでやってみる。
  • yes yes | apt-get install -y oracle-java8-installer
ところが上手くいかない。
apt-get が license を表示するやつ(自前かlessか?)に stdin を渡していないっぽい。

ということで調べてみたらやっぱり解決策がある
debconf で License を読んだことと、同意したことを事前に登録すればOKとのこと。
  • echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
  • echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections
  • apt-get install -y oracle-java8-installer
これで yes を入力しなくても Java が Install できる。良し良し。


参考

2018/05/20

Homebrew の auto-update を止める

いつからか、Homebrew が upgrade や install の際に auto update をするようになりました。
しかし毎回 update が走るのは煩わしい。
特に連続で何かを install する時などは「さっきも update したじゃん」となります。
なので auto-update を止めました。


環境

  • macOS Sierra: 10.12.6
  • Homebrew 1.6.1-7-g6233b9d
  • Homebrew/homebrew-core (git revision 9623af; last commit 2018-04-16)
  • zsh: 5.5 (x86_64-apple-darwin16.7.0)


HOMEBREW_NO_AUTO_UPDATE を set

とはいえやることは環境変数を追加するだけです。
  • export HOMEBREW_NO_AUTO_UPDATE=1
あたりを .zshrc に追記
これで煩わしい auto-update を無効にできます。
あと、 man brew を読むといろいろと環境変数に指定できることが分かります。が、今はこれだけで良いかな。


参考

2018/05/13

Ubuntu 16.04 に CUDA を install する

過去に CentOS7 に CUDA 環境を構築したことがある のですが、Ubuntu 16.04 上にも構築してみたのでそのログ。


環境

  • Ubuntu: 16.04
  • CUDA: 9.1

Install

手順は公式のドキュメントが懇切丁寧に解説しています。
指示された通りに
  • # apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
  • # wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
  • # dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
  • # apt update
  • # apt-get install -y cuda cuda-drivers
したらおしまい。
ダウンロードは 1.3GB とかかな。使う disk は 4GB くらい。
特に問題も無く構築できたので良きかな良きかな。


参考

2018/05/06

ssh した先で GUI Application を起動する

前回の記事では IP Reachable であれば DISPLAY を設定することで GUI Application も動く、と書きました。
ssh に関して言えば、もっとスマートな解決方法があったようです。


ssh と -X -Y option

man ssh を見ると、 X11 に関するオプションがいくつかありますね。
特に X11Fowarding が yes で -X か -Y を付けると
  • The DISPLAY value set by ssh will point to the server machine.
とのこと。勝手に DISPLAY を設定してくれるっぽい。便利。

X11Fowarding option は sshd_config の方(サーバ側)の option で見たことがあります。
なるほど、ここで使うのか(というか ssh した状態で GUI 使うって発想がそもそも無かった……)。


-X option with ssh proxy

-X や -Y の方が優れている点として、ssh proxy を通していても GUI が使える点があります。
具体的には -W option を使って、
  • global IP を持っているマシンに ssh
  • そこから local IP を持っているマシンに ssh
をしている状態でも動きます。

ちなみにその時の DISPLAY の値は
  • $ ssh -Y 10.20.30.40
  • $ echo $DISPLAY
    • localhost:10.0
とか。localhost の host はどこなの状態。IP reachable とかそんなレベルじゃない。

いやまー、 22 番にアクセスしてきた socket を使ってデータを送受信している、みたいなオチだとは思う。
が、「通信が相互に疎通可能である状態ならGUIでもOK」と書いた身としては、すみません嘘つきました、という気持ち。


参考

2018/04/29

GUI application を docker で起動する

私は Host の環境を汚したくないので、開発環境の構築は Docker でなるべくやっています。
今のところDocker 固有の凶悪な問題に遭遇していないので、軽いVM みたいな形で使ってます。
centos:7 でコマンドを試した後、 ubuntu:16.04 でもそのコマンドを試す、とか。ぽんぽん立ち上げられるのが良い。
CUI の場合はガンガンコンテナを作るのですが、GUIはさてどうするんだろう、と疑問。
それで調べたりしたログがこの記事です。

結論としては、この記事は Docker の話では無く X11 の話です。
正確には「X11 に詳しいと、プロセスが走る場所がコンテナ内でも ssh 先でも、GUI を表示できる」という話。


環境

  • macOS Sierra: 10.12.6
  • Docker: 18.03.0-ce-mac60 (23751)
  • XQuartz: 2.7.11 (xorg-server 1.18.4)


GUI Application Container

GUI を利用する Container を調べていたら実行コマンド付きの firefox がありました
XQuartz を起動して、いろいろオプションを足せばOKみたいです。


XServer の起動

X11 の Server として XQuartz を使っていたっぽい。

まずは Server(GUI への remote access を許可) を起動するために
  • Preferences > Security > Allow connections from network clients
にチェックを入れる。
これで XQuartz を起動時に 6000 番とかで listen してくれる。
  • $ netstat -at
とかして :x11 とかがあればOK。
xauth とかで access control もできるっぽいんだけれど、まずは全てのアクセスを許可。
  • $ xhost +
これで X11 Server 側は準備OK。


XServer を指定してコンテナ起動

XServer の情報をオプションで run する時に渡せば firefox が起動しそうです。
元ページのコマンドは
  • $ docker run -d -e DISPLAY=$ip:0 -v /tmp/.X11-unix:/tmp/.X11-unix jess/firefox
ですが、今回は volume の mount はいらないので
  • $ docker run -d -e DISPLAY=$ip:0 jess/firefox
にしてみる。$ip には XServer の ip が入っていると仮定します。
実行すると X11 Server 側で firefox が起動します。やったね。
ちなみに 10.0.0.10:2.0 などのフォーマットはこういうことらしいです。



コンテナの中で DISPLAY を設定してみる

さて、docker run の時の -e オプションは単に環境変数を渡すだけみたいですね。
ということは後から変更できたりするかも。
一旦 centos:7 を起動して、後から DISPLAY を設定してみる。
  • $ docker run -it centos:7
    • # yum install -y epel-release
    • # yum install --enablerepo=epel xcalc
    • # export DISPLAY=10.0.0.30:0.0
    • # xcalc
xcalc は x11 を使う計算機です。
firefox の setup などは難儀なのでこれで代替。
まー、こいつも epel を入れるとか、ちょっとだけ面倒ですが割愛。

結論としては、run した後から DISPLAY を設定しても GUI は起動します。ふむふむ。


ssh 先での GUI Application

DISPLAY が設定できていれば GUI は起動する。
その前提として docker for mac <-> XQuartz 間の疎通が必要。
何故かといえば IP でディスプレイを指定しているからです。

なら、 docker on ssh server <-> XQuartz も可能?
ということで ssh した先でも DISPLAY を設定して xcalc 。
表示される計算機。
なるほど、別に docker だろうと、 ssh 先の linux だろうと、 DISPLAY にデータが送れるのなら GUI process は起動できるっぽい。

この場合、 GUI の描画は X11 経由で mac に、Application のプロセスは ssh した Server の中の docker が起動、なんて状態に。複雑。

ということで、 DISPLAY を適切に設定できれば GUI はぽこぽこ生やせる。


結論

DISPLAY を設定すれば GUI Application も docker で動きます。
というか DISPLAY を設定すれば ssh 先のサーバだろうと何だろうと GUI Application は動きます。


おまけ: xhost 

  • $ xhost +
は全てのIPからGUI access を許可するので危なすぎる。
  • $ xhost -
で access control を再び有効にできます。
本来なら 
  • $ xhost + 10.0.0.20
とかするらしいです。

Docker 触ってると思ったら X Window を触っている。
トレンドを追ってるのか、過去を追ってるのか分からなくなってきます。


参考

2018/04/22

https proxy があるネットワークで Docker を動かす

時にプロキシを介さないと外に出られないネットワークがあります。
curl とかは http_proxy や https_proxy の環境変数を設定するだけで外に出られるので楽。
具体的にはこんな感じ。

  • $ export http_proxy=http://192.168.100.200:12345
  • $ export https_proxy=https://192.168.100.200:54321

しかし docker は環境変数の設定だけでは外に出られない。
具体的には docker pull ができなかった。
docker pull はデフォルトだと https で docker.io に image を取るので引っかかる。


環境

  • Ubuntu 16.04 LTS
  • Docker: 1.5-1

proxy 設定

素直に公式のドキュメントを見る。
具体的には
  • $ mkdir -p /etc/systemd/system/docker.service.d
  • $ vi /etc/systemd/system/docker.service.d/http-proxy.conf
    • [Service]
    • Environment="HTTP_PROXY=http://192.168.100.200:12345"
    • [Service]
    • Environment="HTTPS_PROXY=https://192.168.100.200:54321"
でOK。
systemctl restart docker をすると proxy 経由で pull ができるようになります。


参考

2018/04/15

tmux 2.7 を全角記号対応させる

2018/03/29 に tmux 2.7 がリリースされました。
ということで自分用の border-ascii 版も update しました。(2.6 の時はこんな感じ)
実際やったことは cherry-pick して細かいところの修正とか。


環境

  • OS: macOS 10.12.6
  • tmux: 2.7-border-ascii (65784831fcf0040b78d68b180c6ca8c1210e4317)
  • utf8proc: 2.1(562edab805b82d66622914d06a5da3f53cd54a17)
  • Homebrew: 1.6.0-19-gf9f9dbc
  • Homebrew/homebrew-core: (git revision 6e3b1; last commit 2018-04-14)


利用方法

  • $ brew tap atton/customs
  • $ brew install atton/customs/utf8proc
  • $ brew install --HEAD atton/customs/tmux
これで縦に画面分割する時の線が - になります。
--------------------------------- みたいな感じですね。


おまけ: update 手順

私は tmux の自分用 fork を持っているので、まずはそれに patch を当ててビルド。
OK なら homebrew の formula にしてインストール。
最後に homebrew の tap としてインストール、という流れで作業をしました。
今回はちょろっとした問題があったので、メモてがら書いておきます。


tmux の make

まずは最新の tmux を落としてきてpatch を当てます。
  • $ git pull upstream # upstream は公式の tmux/tmux です。
  • $ git checkout 2.7
  • $ git cherry-pick border-ascii # patch の 1 commit を拾います
  • $ git checkout -b 2.7-border-ascii
これで patched 2.7 ができました。

次に make します。
  • $ ./configure --enable-utf8proc
  • $ make
すると以下のような文言が。

WARNING: 'aclocal-1.15' is missing on your system.
         You should only need it if you modified 'acinclude.m4' or
         'configure.ac' or m4 files included by 'configure.ac'.
         The 'aclocal' program is part of the GNU Automake package:
         <http://www.gnu.org/software/automake>
         It also requires GNU Autoconf, GNU m4 and Perl in order to run:
         <http://www.gnu.org/software/autoconf>
         <http://www.gnu.org/software/m4/>
         <http://www.perl.org/>
make: *** [aclocal.m4] Error 127
んー。 aclocal はあるのだけれどどうしてかな。
  • $ which aclocal
    • /usr/local/bin/aclocal
  • $ aclocal --version
    • aclocal (GNU automake) 1.16.1
バージョンが 1.15 固定じゃないと動かないとかなのだろうか。

とりあえず調べてみる。
そうすると
  • $ touch *
うーん。タイムスタンプ周りの問題か。
にしてもこんなんで解決……しました。はい。
ということで動作確認。
  • $ ./tmux -V
    • tmux master
  • $ tmux
    • うん。問題無く起動するし画面分割も問題無し。
手で make する分には動く状態になりました。
ということで github の自分用 fork に反映
  • $ git push


formula の修正

さて、お次は brew で install できるようにします。
自分用の formula は atton/customs で持っているのでそこへ修正をかける。
その前に local の repository で install できるかを確認します。

素直に 2.6 を 2.7 に置換して、local で install
  • $ brew install --HEAD tmux.rb
とすると
Error: Calling <<-EOS.undent is disabled!
Use <<~EOS instead.
と怒られた。ので素直に <<~ を使う

もう一度 install
  • $ brew install --HEAD tmux.rb
install できました。 tmux -V は tmux master と出るので少々確認しづらいですが。


homebrew の tap へ反映

最後に homebrew の tap で使えるようにします。
といっても既に repository は作ってあるので、そこに push するだけです。
さて、最後の install 確認。
  • $ brew install --HEAD atton/customs/tmux
問題無く install されました。良し良し。

2018/04/08

CentOS7 で root 以外のユーザも Docker を操作できるようにする

基本的に Docker を使う時は root です。
しかし複数人数で Docker を利用したい場合、全員に root をあげるのは良くない。
調べたところ docker というグループに所属させることで、 root でなくても Docker を操作できるらしい


環境

  • OS:CentOS Linux release 7.4.1708 (Core) 
  • Kernel: 3.10.0-693.5.2.el7.x86_64
  • Docker: version 17.06.2-ee-7, build 925df35


dockerroot group

さて docker group の gid でも見るかと
  • $ cat /etc/group | grep docker
    • dockerroot:x:985:
すると docker group が無い。
が、 dockerroot というものがある。
  • $ sudo gpasswd -a atton dockerroot
して所属させてみる。
しかし、
  • $ docker ps 
すると見られない。


Socket の Owner

どうやら /var/run/docker.sock の owner は root:root らしい。
docker を yum install したら dockerroot group を作るのに何故 owner は root のみなんだろ。
まー root 以外に操作させないように念のため、ってことなのかな。

とりあえず dockerroot が読み書きできるように変更。
  • $ sudo chown root:dockerroot /var/run/docker.sock
そして一旦 exit して
  • $ docker ps
すると見られた。
  • $ docker -it run ubuntu:16.04 bash
しても動く。良し良し。


権限とか

ちなみにコンテナ内部で
  • $ whoami
すると root と言われる。
あと、他人が起動したコンテナも操作できてしまう。

なので
複数人数で Docker 操作+他人のコンテナに干渉しない
場合は wrapper を作るか、他の手段に頼る必要がありそう。


参考

2018/03/03

Python 3 が /usr/local/bin/python に配置されるようになった Homebrew で NeoVim の :CheckHealth をパスさせる

いつの間にか Homebrew の /usr/local/bin/python が python3 になってました。中々気合が入っている変更ですね。
私は Python そのものはあまり使わないのですが、 Neovim が使っているのでいろいろと調整したログ。

さて、この変更がある前の Neovim + Python 周りをまとめると
  • $ brew install python
    • python 2 系が入る
    • $ pip2 install neovim
    • pip2 は /usr/local/bin/pip2
  • $ brew install python3
    • python 3 系が入る
    • $ pip3 install neovim
    • pip3 は /usr/local/bin/pip3
といった感じだったのですが、変更後は
  • $ brew install python
    • python 3 系が入る
    • pip3 は /usr/local/bin/pip
  • $ brew install python@2
    • python 2 系が入る
    • が、keg-only の formula 。
    • python2 や pip2 を使うには  /usr/local/opt/python@2/ などに PATH を通す必要がある
    • 詳しくは $ brew info python@2 
という形になっているようです。
keg-only の formula を使い続けると混乱しそうなので、python@2 はアンインストール。

Python 2 系は system builtin のものを使うことにしました。
root で書き込む必要があるのでしくじった時のダメージが大きいですが……

ということで
  • $ brew uninstall python@2
  • $ sudo easy_install-2.7 neovim
して解決。

具体的な :CheckHealth の結果は
  • before
  • after

といった感じです。:CheckHealth 便利。


環境

  • macOS: 10.12.6
  • Homebrew: 1.5.7
  • Homebrew/homebrew-core (git revision b33d4d; last commit 2018-03-03)
  • NeoVim: 0.2.2
  • python2.7: 2.7.10 (macOS provided)
  • python: 3.6.4 (Homebrew provided)