xargs が Linux と Mac 両方できちんと動くためには -i ではなく -I オプションを使う

LinuxMac で xargs の挙動が違うのは以前から認識していたが、詳細までは調べていなかった。今回、プライベートの git レポジトリをコミットして Mac で xargs を実行した際に illegail option -- i と怒られてしまったので、これを機会に xargs が LinuxMac 両方できちんと動作するように修正した。

Linux では動く、Mac では動かない

# da = dot apply
alias da="ls -A ~/git/$repo/t/dot/ | xargs -i cp {} $HOME && pushd $HOME && source $HOME/.bash_profile && popd"

Mac 版の xargs (BSD) では -i オプションがサポートされていないのが問題だった。

$ da
xargs: illegal option -- i
usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]
             [-L number] [-n number [-x]] [-P maxprocs] [-s size]
             [utility [argument ...]]

xargs 調査

Linux 版の xargs の man を読むと、そもそも -i オプションはすでに deprecated となっており -I オプションを使うことが推奨されている。単純に -i を -I に変えればいいのかと思ったら、少し事情は異なっていて -I オプションは -i と違ってデフォルトの replace-str に {} を設定してくれないので、明示的に {} を指定する必要がある。

$ man xargs
(.. snip ...)

       -I replace-str
              Replace  occurrences  of replace-str in the initial-arguments with names read from standard input.  Also, unquoted blanks do not terminate input items;
              instead the separator is the newline character.  Implies -x and -L 1.

       -i[replace-str], --replace[=replace-str]
              This option is a synonym for -Ireplace-str if replace-str is specified.  If the replace-str argument is missing, the effect is the same as -I{}.   This
              option is deprecated; use -I instead.

(.. snip ...)

上記を踏まえて以下のように修正した。(๑•̀ㅂ•́)و✧

Linux でも Mac でも動く(replace-str に伝統的(?) に {} を使用)

$ git diff -U0 HEAD~2 HEAD
(... snip ...)
-alias da="ls -A ~/git/$repo/t/dot/ | xargs -i cp {} $HOME && pushd $HOME && source $HOME/.bash_profile && popd"
+alias da="ls -A ~/git/$repo/t/dot/ | xargs -I {} cp {} $HOME && pushd $HOME && source $HOME/.bash_profile && popd"
(.. snip ...)

Linux でも Mac でも動く(replace-str に独自のトークンを使ってみた例)

$ git diff -U0 HEAD~2 HEAD~1
(.. snip ...)
-alias da="ls -A ~/git/$repo/t/dot/ | xargs -i cp {} $HOME && pushd $HOME && source $HOME/.bash_profile && popd"
+alias da="ls -A ~/git/$repo/t/dot/ | xargs -I _file_ cp _file_ $HOME && pushd $HOME && source $HOME/.bash_profile && popd"
(... snip ...)

Docker イメージの LABEL 情報は Label-Schema が標準になる

f:id:kyagi:20180216163134p:plain

Docker イメージのメタ情報(メンテナ、ライセンス種別、ビルド日時、Github の URL など) は LABEL に集約しようという動きが広まってきている。そのために「どういった情報を載せるべきか」という議論がコミュニティベースで展開された結果、標準として Label-Schema という規格で定まってきているようだ。

label-schema.org

Docker 社もこの動きには賛同している。現在は 1.0.0-rc.1 (Release Candidate) だが、近いうちに正式に標準となりそうだ。

Docker Inc. express a preference that container labels should be namespaced. Label Schema is a community project to provide a shared namespace for use by multiple tools, specifically org.label-schema.

個人的にもイメージの透明性を高めるために当然の動きだと思う。正直 Dockerhub でよさそうなイメージを見つけても Dockerfile が公開されていない(≒ Github 連携していない) イメージは怖くて使えない。

Dockerfile の中で ARG で指定した変数は docker build 時に --build-arg var=value とオプションで渡すことができる。動的な情報のビルド日時や VCS_REF(=git のコミット値(SHA)) が対象となるようだ。

$ docker build --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` .
(... snip ...)
Successfully built d187459cd07e

$ docker image inspect d187459cd07e | jq '.[].ContainerConfig.Labels' | jq '.["org.label-schema.build-date"]'
"2018-02-05T16:39:17Z"

$ date
Tue Feb  6 01:57:38 JST 2018

Github と Dockerhub を連携して Automated Build を設定している場合は hooks/build というスクリプトを置くことで同様に ARG で指定した変数を渡すことができる。サンプルを公開してくださっている方がいるので、こちらを参考に GitHub - kyagi/rod: REPLs On Docker を修正した。

github.com

Automated Build されたイメージを pull して LABEL 情報を確認すると vcs-ref がきちんと入っていることを確認できた。

$ docker image inspect kyagi/rod:latest | jq '.[].ContainerConfig.Labels' | jq -r '.["org.label-schema.vcs-ref"]'
02714fd

git rev-parse --short HEAD
commit 02714fd

ただ、問題がふたつ。ひとつめは、LABEL に BUILD_DATE など動的な値を渡すとキャッシュが効かなくなるようで、ビルドに時間がかかる。--no-cache を指定した時と同じ動きをしているように見える。ふたつめは org.label-schema.abc とキー名にドットが入っているせいで jq の処理に手間がかかる。どうしたものかなあ。(´・_・`)

Tectonic CoreOS を使って AWS 上に Kubernetes クラスタを構築する

CoreOS 社が提供している Kubernetes にセキュリティ、監視、マルチクラウド統合、そしてカッコイイ管理インターフェイスを備えた統合環境 Tectonic を使用してみた。

同社の推しは「Kubernetes の管理コストをさげる」「クラウドベンダーにロックインされない」だが、逆に柔軟が設計/設定ができる Kubernetes の自由度を下げ、同社にロックインされるとも受け取れる。試していないが Openshift も似たような統合環境のようだ。

coreos.com

課金体系

kubernetes クラスタのノードが 10 台までは無料、それ以上は応相談。

インストール

インストールの前に CoreOS の URL からアカウントを作成してライセンス情報と設定ファイルを入手する必要がある。CoreOS 社が提供する圧縮ファイルの中のインストーラを起動し、ブラウザ上で各種情報(AWS の場合、認証情報や Manage, Worker, Etcd それぞれのノード台数とインスタンスタイプなど)を入力して進めていく。内部では Terraform が使われている。インスタンスタイプはデフォルトで t2.medium なのでそこまでお金はかからない。

ハマりどころ

  • デフォルトでは Manage : Worker : Etcd = 3 : 3 : 3 で kubernetes クラスタを構築しようとするが、個人の AWS だと EIP の上限はだいたい 5 になっているのでそこでエラーになる。
  • 使用するドメインTTL を短くする必要がある。retry = 90, ttl = 89 にして成功した。

DNS caching

An issue arises when a domain's Address record (A record) resolution is attempted before Route 53 publishes the cluster's A record and the NXDOMAIN response is cached in the NCACHE (RFC2308). This negative response may be cached for up to the number of seconds set in the domain's SOA record's TTL. Resolution fails until the negative caching TTL expires. These TTLs are typically large enough to disrupt the installation. The current workaround is to ensure your TTLs are set to a low interval, or to wait for them to expire, then proceed with the installation.

AWS Troubleshooting | Tectonic Installer on AWS | CoreOS

変更前 SOA) ns-123.awsdns-45.com. awsdns-hostmaster.amazon.com.  1 7200 900 1209600 86400
変更後 SOA) ns-123.awsdns-45.com. awsdns-hostmaster.amazon.com.  1 7200 90 1209600 89
  • 上記エラーの場合 Destroy & Start Over でやり直すことができるのだが、IAM ロールが削除されていないようで Already Exists なエラーになるので削除する。

感想

tectonic-system というネームスペースが追加されて、そこで Tectonic 固有の監視やコンソールの Pods が動いているようだ。Prometheus, Grafana も同時にインストールされる。ノードが 10 台まで無料(EC2 や AWS リソースはもちろん自分で払う) なので、開発環境にはよいかもしれない。個人的には kops のほうがコマンド一発で使いやすい。

  • Tectonic Console 1 f:id:kyagi:20180206022634p:plain

  • Tectonic Console 2 f:id:kyagi:20180206022645p:plain

  • Tectonic Console 3 f:id:kyagi:20180206022731p:plain

  • Prometheus f:id:kyagi:20180206022743p:plain

  • Grafana f:id:kyagi:20180206022748p:plain

クラスタ削除は terraform destroy で可能。構築した時のインストーラの情報を削除しないように注意されたし。(´・ω・`) https://coreos.com/tectonic/docs/latest/install/aws/uninstall.html

Scala, Ruby, Go の REPL 環境を Docker コンテナですぐに試せる Rod (REPLs on Docker) を作った

Scala の学習用に Ammonite 環境AWS EC2 上に構築していて、Scala Exercises の例を試せるように紹介されている cats や shapeless のライブラリを追加していた。ただ、個人的に Ruby を使う機会が圧倒的に多いので pry は必須だし、Go もやってみたいと考えているうちに、「REPL 環境をまとめた Docker コンテナを作成してしまえば楽なのでは?」と思って Rod (REPLs on Docker) というツールを作成した。

github.com

Github と Dockerhub を連携させて Automated Build 設定しているので、Github が更新されると自動的に Dockerhub 内部で docker builddocker push してくれる。

https://hub.docker.com/r/kyagi/rod/

簡単な使い方は以下の通り。例えば Scala Exercises の Cats | Semigroup の紹介されているコード例をそのまま打ち込めば試せるようになっている。自分自身が sbt console の使い勝手にあまり満足していないのと、Scala の開発環境構築に手間取ったところがあるので、こういったツールが誰かの役に立ってくれれば嬉しい。(^.^)

docker コンテナをたちあげる。

$ docker run -it kyagi/rod
 ____  _____ ____  _                         ____             _
|  _ \| ____|  _ \| |    ___    ___  _ __   |  _ \  ___   ___| | _____ _ __
| |_) |  _| | |_) | |   / __|  / _ \| '_ \  | | | |/ _ \ / __| |/ / _ \ '__|
|  _ <| |___|  __/| |___\__ \ | (_) | | | | | |_| | (_) | (__|   <  __/ |
|_| \_\_____|_|   |_____|___/  \___/|_| |_| |____/ \___/ \___|_|\_\___|_|
root@e8dcf015f1b5:~# 

Scala の REPL を使いたい時は rod scala で amm が起動する。

root@e8dcf015f1b5:~# rod scala
Loading...
Compiling (synthetic)/ammonite/predef/interpBridge.sc
Compiling (synthetic)/ammonite/predef/replBridge.sc
Compiling (synthetic)/ammonite/predef/DefaultPredef.sc
Compiling /root/.ammonite/predef.sc
Welcome to the Ammonite Repl 1.0.3
(Scala 2.12.4 Java 1.8.0_151)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ import cats.Semigroup
import cats.Semigroup

@ import cats.implicits._
import cats.implicits._

@ Semigroup[Int => Int].combine({ (x: Int) => x + 1 }, { (x: Int) => x * 10 }).apply(6)
res2: Int = 67

@ exit
Bye!
root@e8dcf015f1b5:~#

Ruby の場合は pry が立ち上げる。

root@e8dcf015f1b5:~# rod ruby

[1] pry(main)> ri open
(... snip ...) いっぱいあるけど Tempfile.open が知りたい
[2] pry(main)> ri Tempfile.open
(... snip ...)
[3] pry(main)> ri Array
(... snip ...) Array クラスのドキュメント
[4] pry(main)> ri Array#
(... snip ...) Array クラスのインスタンスメソッド一覧

Go の場合は gore が立ち上げる。

root@e8dcf015f1b5:~# rod go
gore version 0.2.6  :help for help
gore> :help
    :import <package>     import a package
    :print                print current source
    :write [<file>]       write out current source
    :doc <expr or pkg>    show documentation
    :help                 show this help
    :quit                 quit the session
gore> :quit
root@e8dcf015f1b5:~#

いろいろいれたらイメージサイズがふくらんでしまった(1.43GB)。特定の言語の REPL があればいい場合は、Dockerfile を削ることで軽量化できるけど、その逆にこの REPL も入れたい(例えば gore じゃなくて go-pry を使いたいなど) とかもあるかもしれない。

ちなみに .rod-prompt を読み込むことでプロンプトが変わって、Docker コンテナ内の環境にいることがわかりやすくなる(おまけ)。(๑˃̵ᴗ˂̵)و

https://camo.githubusercontent.com/4982b60d784c7eea80e15e3a47de26ab4e4fd01f/687474703a2f2f63646e2d616b2e662e73742d686174656e612e636f6d2f696d616765732f666f746f6c6966652f6b2f6b796167692f32303138303230342f32303138303230343132323935322e706e67

プロンプト新世代を agnoster-bash と docker-prompt に感じた

agnoster-bash

会社の同僚に教えていただいて Mac のプロンプトを変えてみた。今までも環境ごとにプロンプトは変えていたけれど、vt100 で xterm な枠の中でせいぜい背景色と文字書を変更するぐらいだった。大げさかかもしれないけど、ブランチの記号がフォントに含まれるのにプロンプト新世代を感じた。打ったコマンドの終了ステータスが 0 以外だと赤いバツが出るのも心憎い。

GitHub - speedenator/agnoster-bash: Agnoster Theme for Bash

いままで)

f:id:kyagi:20180204111353p:plain

これから)

f:id:kyagi:20180204111407p:plain

コマンドの終了ステータスが 0 以外の場合、赤いバツがでる)

f:id:kyagi:20180204183523p:plain

プロンプト中のブランチマークが ? になってしまって表示できない現象は iTerm2 のフォントを Meslo LG ファミリに変更すれば表示できるようになる。

My theme error, shows question mark symbol · Issue #23 · agnoster/agnoster-zsh-theme · GitHub

個人的にフォントは Menlo 派なので Meslo LG フォントが Menlo の流れを汲んでいるのはありがたい(Menlo と Meslo で名前も似ている理由があるのかな、と探してみたけど、見つからなかった)

GitHub - andreberg/Meslo-Font: Customized version of Apple's Menlo font. Great monospaced font for development work. Should also work with the Windows Console (see Wiki for Windows infos).

日付と時間を表示しておきたいのと、視点はいつも左端に固定しておくのが楽なので、ちょっとだけ修正を加えておく。

Added datetime and newline for my preference by kyagi · Pull Request #1 · kyagi/agnoster-bash · GitHub

docker-prompt

最近では Docker コンテナかそうでないかによってプロンプトを変更するということもあるようだ。環境ごとに違った emoji をプロンプトに出すというのもなかなかいいかもしれない。

How to get a fancier bash prompt PS1 inside a docker container #docker #ps1 #emoji · GitHub

歴史的なプロンプト変更方法

環境ごとにプロンプトを変更するのは昔からよく行われてきた。よくある例だと、開発環境か本番環境によって色を変える *1 など。

昔読んだドキュメントにプロンプトに焦点を当てて解説していたものがあったので探してみた。バージョン管理が RCS ぽいところも懐かしい。ただし、内容はまだ現在でも褪せていない。(๑´ㅂ`๑)

http://linuxdocs.org/HOWTOs/Bash-Prompt-HOWTO/index.html

*1:具体的には ip a show dev eth0 | grep -o 'inet [0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' | cut -d ' ' -f2 して切り出した IP アドレスを、さらに cut -d'.' -f1-2 でネットワーク部分を抽出して case ごとに PS1 を変える

bash: /dev/tty: No such device or address を script コマンドで解決する

GitHub - kyagi/rod: REPLs On Docker を作っている中で Ammonite の起動が早くなるようにあらかじめライブラリをキャッシュさせておくため .ammonite/predef.sc にライブラリを追加したあとに echo exit | amm -s を実行するようにしたところ、docker build 中に bash: /dev/tty: No such device or address が出てビルドに失敗するようになってしまった。原因は amm がメッセージを吐き出す端末(tty)が見つからないことのようだ。REPL はそもそも人間とのインタラクティブなやりとりが想定されているのだから、至極当然な気もするが、このままでは Docker イメージが作れない。

Dockerfile

RUN echo exit | amm -s
$ docker build .
(... snip ...)
bash: /dev/tty: No such device or address
bash: /dev/tty: No such device or address
java.lang.RuntimeException: Nonzero exit value: 1
  scala.sys.package$.error(package.scala:27)
  scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:134)
  scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:104)
  ammonite.terminal.TTY$.stty(Utils.scala:118)
  ammonite.terminal.TTY$.init(Utils.scala:97)
  ammonite.terminal.Terminal$.x$1$lzycompute$1(Terminal.scala:41)
  ammonite.terminal.Terminal$.x$1$1(Terminal.scala:41)
(... snip ...)
ビルドが終わらない...

いろいろ悩んで、ぐぐって、試行錯誤したところ、script -c を使うことで回避することができた。これが今年の今まで一番のハック。╭( ・ㅂ・)و ̑̑ グッ !

$ man script
(... snip ...)
     -c, --command command
             Run the command rather than an interactive shell.  This makes it easy for a script to capture the output
             of a program that behaves differently when its stdout is not a tty.
(... snip ...)

Dockerfile

RUN export TERM=vt100 && script -qfc 'echo exit | amm -s' && rm typescript

https://github.com/kyagi/rod/blob/master/Dockerfile#L63

$ docker build .
(... snip ...)
Successfully built 38b3611dc9b5

Docker を支える Linux カーネル機能 Network Namespace から docker exec の実装が ip netns exec である雰囲気をつかむ

f:id:kyagi:20180216163134p:plain

Linux の Network Namespace を ip netns exec で操作しているうちに「docker exec の正体」がなんとなく見えてきた。

Bridge Networking Deep Dive — Docker Kubernetes Lab 0.1 documentation

デフォルトでは docker はコンテナの Network Namespace を見せないようにしている。これは docker exec からのみコンテナの Network Namespace にアクセスを許可するように意図しているものに感じられる。OOP でクラスのメンバを private や protected で保護することと似ているかもしれない。

$ docker run --rm -d --name b1 busybox sh -c "while true; do sleep 3600; done"
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
0e3030605661        busybox             "sh -c 'while true..."   About an hour ago   Up About an hour                        b1

いつも操作を忘れてしまうので、シェル関数を作っておく。docker-netns show [CONTAINER-NAME] で ip netns 経由で exec できるようになる。隠蔽された状態に戻したい時は docker-netns stash [CONTAINER-NAME] を実行する。

function docker-netns () {
  local action=$1
  local cname=$2

  case ${action} in
    show)
      docker inspect ${cname} | jq ".[].State.Pid" | xargs -i sudo ln -s /proc/{}/ns/net /var/run/netns/${cname}
      echo "Network namespace for container ${cname} is visible now."
      ;;
    stash)
      sudo rm /var/run/netns/${cname}
      echo "Network namespace for container ${cname} is invisible now."
      ;;
    *) :
      ;;
  esac

  ls -l /var/run/netns/${cname}
}
$ sudo ip netns list
$

$ docker-netns show b1
Network namespace for container b1 is visible now.
lrwxrwxrwx 1 root root 18 Jan 31 00:30 /var/run/netns/b1 -> /proc/11385/ns/net

$ sudo ip netns list
b1

$ sudo ip netns exec b1 ip a # 以下 docker exec と内容が同じ
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
91: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever

$ docker exec -it b1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
91: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever

$ docker-netns stash b1
Network namespace for container b1 is invisible now.
ls: cannot access /var/run/netns/b1: No such file or directory

$ sudo ip netns list
$ 

$ sudo ip netns exec b1 ip route
Cannot open network namespace "b1": No such file or directory

ただ ip netns exec b1 ip a でなく ip netns exec b1 hostname だとコンテナのホスト名 0e3030605661 は返ってこずに docker host のホスト名が返ってくるので、あくまでネットワークに限定した名前空間である感覚がしている。その意味では docker exec は Network Namespace だけでなく Process Namespace やその他の名前空間をまとめて隔離した空間に対するインターフェイスなのではないか。

ip netns exec が docker exec の正体というのはただの個人的感覚でしかない。今度、知り合いのカーネルハッカーに聞いてみよう...。自分でソースを読めと言われるに決まっているのだけれど。ただこういった局所的な興味からカーネルソースに飛び込んでみるのも目的がはっきりしていていいかもしれない。(´▽`)

Disjunction と Either の違い

Safari Books Online で検索したところ、以下の記述が見つかった。

Disjunction is conceptually similar to Either, which can be used to represent one of two possible types. Disjunction is different from Either because its operations are right-biased. (6. Concurrency in Scala, Scala High Performance Programming)

scala の API ドキュメントでも Either の「Left を例外処理、Right を正常処理」は慣習的な取り決めのように読み取れる。

Convention dictates that Left is used for failure and Right is used for success. Scala Standard Library 2.12.0 - scala.util.Either

上記から、個人的に以下のような理解をしている。

  • Disjunction はもともと Right を正常値とするように設計されている。
  • Either は convention として慣習的に Right を正常処理とするように使われている(ことが多い)。

※会社の Scala エキスパートによると「2.12からEitherもright-biasedなので古い本は窓から投げ捨てて下さい」だそうだ。(^_^;

docker-machine で aws に docker 環境(docker host) を構築する

f:id:kyagi:20180216163134p:plain

いままでメインの docker 環境は AWS EC2 上で curl -fsSL get.docker.com -o get-docker.sh && sudo sh get-docker.sh のように構築していたけれど、 docker-machine for AWS を使ったほうがいろいろ便利だった。

Amazon Web Services (AWS) EC2 example | Docker Documentation

docker-machine for aws のいいところ

  • 自分で docker をインストールする必要がなく最新のバージョンを入れてくれる(docker インストール済の ec2 をたちあげてくれる)
  • aws でつくると docker-machine stop|start で ec2 も stop|start できる。
  • docker-machine provision で環境をリセットできる(docker と certs の再インストールを行ってくれる。バージョンアップ時に役立つ?)
  • ec2 インスタンスと Key Pairs が自動的に作成されるが、docker-machine rm で ec2 を削除すると Key Pairs も自動的に削除してくれる。

ただ provisioner として chef やその他をフックすることはできないようで、好みの docker 環境を何台も docker-machine create する場合は、あらかじめカスタム AMI を作っておいたほうがよさそうだ。

前提条件

  • docker-machine 操作元となる Mac もしくは Linuxに docker と docker-machine がインストールされていること
  • .aws/credentials に認証情報が設定されていること

環境構築

os は ubuntu 16.04 になる。この場合 docker.aws.net という ec2 インスタンスと Key Pairs が自動的に作成される。インスタンスタイプはデフォルトで t2.micro で OS は ubuntu 16.04)。

$ docker-machine create --driver amazonec2 --amazonec2-region ap-northeast-1 --amazonec2-zone b --amazonec2-vpc-id vpc-abcde123 --amazonec2-subnet-id subnet-abcde123 docker.aws.net
$ docker-machine ls
NAME               ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
docker.mac.local   -        virtualbox   Running   tcp://192.168.99.102:2376           v18.01.0-ce
docker.aws.net   -        amazonec2    Running   tcp://aaa.bbb.ccc.ddd:2376           v18.01.0-ce

ログイン

$ docker-machine ssh docker.aws.net
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-1020-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

145 packages can be updated.
63 updates are security updates.


Last login: Mon Jan 29 17:31:26 2018 from xxx.xxx.xxx.xxx

ubuntu@docker:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.2 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.2 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

おまけ

mac のローカルで docker-machine を使って virtualbox で docker 環境を構築すると os は boot2docker になる。(ฅΦωΦ)ฅ

$ docker-machine create --driver virtualbox docker.mac.local
$ docker-machine ssh docker.mac.local
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 18.01.0-ce, build HEAD : 0bb7bbd - Thu Jan 11 16:32:39 UTC 2018
Docker version 18.01.0-ce, build 03596f5

docker@docker:~$ cat /etc/os-release
NAME=Boot2Docker
VERSION=18.01.0-ce
ID=boot2docker
ID_LIKE=tcl
VERSION_ID=18.01.0-ce
PRETTY_NAME="Boot2Docker 18.01.0-ce (TCL 8.2.1); HEAD : 0bb7bbd - Thu Jan 11 16:32:39 UTC 2018"
ANSI_COLOR="1;34"
HOME_URL="http://boot2docker.io"
SUPPORT_URL="https://github.com/boot2docker/boot2docker"
BUG_REPORT_URL="https://github.com/boot2docker/boot2docker/issues"

Udemy の Learning Docker and Kubernetes by Lab がとてもよい

Docker 再入門として Learning Docker and Kubernetes by Lab | Udemy のコースを受講しているのだが、とてもよい。コンテナを支える Linux カーネルの機能として cgroups, Network Namespaces (Strorage(aufs), Security, Process Namespaces) の概要から、brctl, ip netns の使用例と仕組みまで解説してくれていて、とてもわかりやすい。(^.^)

今まで読んだ Docker 本ではコンテナを支える Linux カーネルの機能を説明しているものがなかったし、当然 brctl や ip netns も出てくることはなかった。O'Reilly の Docker 本は python のアプリを使って説明しようとしていたが、「知りたいのは docker であって pythonフレームワークじゃないんだよ... コンテナなんか素の nginx で十分(docker -d --name my-nginx-1 nginx) なんだよ... 」と言いたい気持ちをぐっとこらえて読んだものの、どこかはぐらかされた気持ちで消化不良を起こしていた。

コースの内容はドキュメントにまとまって公開されている。これを読むだけでもわかる人にはわかるのだろうが、自分の場合は、実際にビデオをみて、手を動かして、ドキュメントで補足するのが一番理解が進んだ。

Docker Kubernetes Lab Handbook — Docker Kubernetes Lab 0.1 documentation

個人的にありがたかった点を以下にあげておく。

  • コンテナの基礎技術である cgroups の説明により k8s の CPU 割り当ての実態が見えてくる。
  • brctl と ip netns の説明により docker の Network Namespaces の実態が見える。実際、docker は自身の Network Namespace を隠してしまうため ip netns list では表示されないが、それを裏技的に表示する方法を紹介している。ip netns exec が実際の docker exec なのではないかと思う(大きく外れてはいないはず)。
  • CNM や overlay ドライバを利用した複数ホストをまたいだネットワークがよくわかる。docker 本家でもこれらの例をわかりやすい図で説明してくれているのだが、学習者はなかなかそのリンクまでたどり着かないことが多いと思う。(⌍་д་⌌)

libnetwork/design.md at master · docker/libnetwork · GitHub

labs/06-overlay-networks.md at master · docker/labs · GitHub