TenForward

技術ブログ。はてなダイアリーから移転しました

技術書典のオフライン会場で使う見本誌をコンビニコピー機で自作

前の技術書典13で同人本を初めて出して、後のためにも色々ノウハウをまとめようと思っていたものの、イベント終わった後も商業版の出版などバタバタして何も残せていませんでした。

今回の技術書典14でも新刊を出しますので、ちょっとメモだけでもしておくかなということで、まずは勢いで見本誌の作成をメモっておきます。

私は新刊については、あらかじめ印刷はせずに、「後から印刷」を使って売れた分だけ受注生産することにしています。

そのため、オフライン会場で、どのような本か?を確認していただけるように、自作で見本誌を作っています。

今は、コンビニのマルチコピー機で小冊子印刷ができます。まあ、会社なんかにあるコピー機でもできるでしょうから、イマドキは出来て当たり前かもしれません。両面印刷で1ページの隣は最後のページが印刷されるという風に、仕上がったものを2つに折ったらそれだけで小冊子ができるというやつです。

こんな感じです。

詳しくは、次のページをどうぞ。

手順

  1. 原稿は実際に印刷所に出すのとは別にトンボなしで作成しています。それをPDFで出力します。表紙は印刷所に出すやつをそのままPDFに出力して持っていきました。いずれもUSBメモリーに保存してコンビニへ。
  2. まずはコンビニで小冊子印刷をします。私はセブンイレブンでやりました。99ページが上限みたいで、私の本は128ページありましたが、見本誌だからいいや、ってことで99ページで作りました。
  3. 表紙は別にPDFで持って行ってカラー印刷しました(画像でもいけるはず)。私の本はA5サイズなのでB4サイズの表紙原稿を印刷しています。
  4. さすがに100ページある本を真ん中で折るって製本するわけにはいかないので、真ん中で切ります。
  5. きちっとそろえて、表紙の裏側にちゃんと位置合わせして置きます。
  6. 背表紙部分に木工用ボンドをたっぷり塗ります。
  7. 表紙を折り曲げて本の形にします。
  8. 最後はボンドが固まるまで重い本を乗せて乾かします。
  9. 最後は表紙のはみ出た部分を切って本にします。

まあ、見た目は悪いのですが、前のイベントはこれに透明のブックカバーかぶせて、ブースに来た人に見ていただきました。おかげで、実際に中身を見て購入を決めてくださった方も結構いらっしゃるようでした。見本なしでは中身がわからないので売上はもっと少なかったはずです。

技術書典13に出典し、「Linux Container Book (1) Namespace / Network 編」という本を出しました

gihyo.jp で連載している「LXCで学ぶコンテナ入門」やこのブログ、zenn.dev の記事をベースに Linux コンテナの本を書き、技術書典13で「Linux Container Book (1) Namespace/Network編」という本を出しました。

techbookfest.org

技術書典13は終了しましたが、電子版はいつでもご購入いただけますので、ぜひお買い求めください。

この本では Linux でコンテナを作成する場合に使われる Linux カーネルの機能のうち、Namespace とネットワーク関連の機能について説明しています。

Docker 動かしてるけどどんな仕組みで動いているんだろう?と思う方、コンテナランタイムを作るぞという方、その他興味を持たれた方は是非お買い求めいただくとうれしいです。

買うほどでないなあ、という方は是非 gihyo.jp さんで行っている連載だけでもご覧ください(現時点で古い記事が一覧で表示されないんですけど…)

正誤表

見つかり次第追加します。電子版は、後日更新版を技術書典のオンラインショップに上げます。

  • 1.0.1 の後に見つかった誤記を修正しました(2023-01-22)
  • 紙版は次の表で「紙版で修正済」としているものは修正した上で入稿しています(2022-09-29)
  • 電子版は「電子版で修正済」としているものは記載したバージョンで修正しています(2022-09-29)

電子版は技術書典の「自分の本棚」から最新版をダウンロードできますので、お買い上げ頂いた方は最新版の取得をお願いします。

場所 備考 修正
P.76 電子版のみ本文ではないページに余計な閉じカッコがあったので削除し、技術書典14用のv1.0.3としました。内容に変更はありません v1.0.3
全体 表現の調整を行っています。長音記号や漢字→ひらがなの置換で内容には変更ありません 電子版v1.0.2で修正済
P.9 りソース リソース 電子版v1.0.2で修正済
P.26 バインドマウント先として/root/hostファイルを作成 バインドマウント先として/root/hostsファイルを作成 最初の実行例中の説明のファイル名が間違っていました 電子版v1.0.2で修正済
P.62 { ` sudo adduser test と実行している部分の例の一部の文字が変な文字に置き換わっていました("`" が "{" になっていた) 電子版v1.0.2で修正済
P.45 表4.4 privated private 現在の設定 "shared" の行 電子版v1.0.2で修正済
P.39, P.45 propagete_from propagate_from P.39下から2行目、P.45 4.6節の1行目 電子版v1.0.2で修正済
P.16 脚注 2) あとで説明するケーパビリティからchrootを行う特権 CAP_SYS_CHROOT を落とします。 ケーパビリティからchrootを行う特権 CAP_SYS_CHROOT を落とします。ケーパビリティについては本書では説明しません。 ケーパビリティについては後日執筆予定の続編で説明する予定です 紙版、電子版v1.0.1で修正済
P.46 脚注の 2) が 2 つありました P.46の脚注の 1), 2) は P.45 の表中に対する脚注です。2 つ目の 2) は P.46 中盤にある 2) に対する脚注です 紙版、電子版v1.0.1で修正済
第 3 章序盤 一部のみ読点が「,」になっていました 紙版、電子版v1.0.1で修正済
P.7 つまり、図 1 のように物理的なコンピュータ上で動く OS 上でさらに OS が動きます つまり、図 2.1 のように物理的なコンピュータ上で動く OS 上でさらに OS が動きます 図の番号が間違っていました 紙版、電子版v1.0.1で修正済
P.13 一般的には図1 のように 一般的には図2.1 のように 図の番号が間違っていました 紙版、電子版v1.0.1で修正済
P.57 例えば、図のように Namespace 内では UID、GID が共に 0 の root ユーザーを 例えば、図9.1のように Namespace 内では UID、GID が共に 0 の root ユーザーを 図番号を追加しました 紙版、電子版v1.0.1で修正済
P.70 図では macvlan0 には mac0 という MAC アドレスが 図10.2では macvlan0 には mac0 という MAC アドレスが 図番号を追加しました 紙版、電子版v1.0.1で修正済
P.22 表1に示した Namespace を単独で指定したり 表3.1 に示した Namespace を単独で指定したり 表番号が間違っていました 紙版、電子版v1.0.1で修正済
P.45 プロパゲーションがどのように変化するかを表2にに示します プロパゲーションがどのように変化するかを表4.4にに示します 表番号が間違っていました 紙版、電子版v1.0.1で修正済
第9章 紐付け ひもづけ 「ひもづけ」が漢字表記担っている部分があったので表記を合わせました 紙版、電子版v1.0.1で修正済
第9章 ネットワーク Namespace Network Namespace 一部だけ異なる表記になっていたので本の他の部分と合わせました 紙版、電子版v1.0.1で修正済

オフライン出展

9/11 のオフライン会場にも出展しました。当日お越しいただいた方ありがとうございました。

技術書典13

この日は物理本の印刷はせず、見本誌を展示していただけですが、多数の方に手に取っていただいてお買い上げいただきました。

少しお話ができた方もいて、楽しかったですし、見本誌を見ていただいているのを見てるだけでも楽しかったです。

展示の模様

docker-compose.yaml の volumes の指定でハマった話

私はDockerもDocker Composeもcontainerdも素人で、今回の問題がよく知られた問題なのか、そうでないのかもよく知りません。ちなみにDocker Composeは今日まで使ったことがなかったし、Rancher Desktopも今日はじめてインストールしました(^^)。

この辺りのコンテナランタイムの知識もないので、用語の使い方も間違ってたりするかもしれませんがご容赦を。

このエントリは単に「ちょっと時間使って調べた」ので「オレ頑張ったよ」と誰かに言わないと気がすまないし、最近技術ブログ書いてないよなと思ったので書いてみるだけです。

問題

「Sensu Goをコンテナで起動してるけど、コンテナを再起動するたびに初期化されるので、Sensuに詳しいだろうからちょっと見て」という相談を受けたのが始まりです。(ちなみにSensu Go詳しくないです。Sensu Goを使ったシステムをちょっと作ったことがありますが)結局は Sensu の知識は全く不要でした。

Rancher Desktop環境で、Sensu Goの公式ドキュメントにあるDocker Composeを使ってsensu-backend(sensuサーバー)を起動すると、再起動するたびにetcdのデータが初期化されているのか、毎回クライアント側も初期設定する必要があるということでした。

ちなみに yaml はこんな。

version: "3"
services:
  sensu-backend:
    ports:
    - 3000:3000
    - 8080:8080
    - 8081:8081
    volumes:
    - "sensu-backend-data:/var/lib/sensu/sensu-backend/etcd"
    command: "sensu-backend start --state-dir /var/lib/sensu/sensu-backend --log-level debug"
    environment:
    - SENSU_BACKEND_CLUSTER_ADMIN_USERNAME=admin
    - SENSU_BACKEND_CLUSTER_ADMIN_PASSWORD=admin
    image: sensu/sensu:latest

volumes:
  sensu-backend-data:
    driver: local

解決

問題自体はすぐに解決しました。手元に Rancher Desktop がなかったので、Linux 上の Docker 環境で docker-compose.yaml を書いて起動してみました。

しかしどのようにやっても、ちょっとコンテナを強制終了しても、特に再起動後は問題なく使えます。で、このことを相談を受けた人に伝えると、すぐに

  • Linux(のDocker)でやったらたしかに問題は起こらない
  • 試しに Rancher Desktop のコンテナランタイムを "containerd" にしていたのを "dockerd(moby)" に切り替えたら問題が起こらなくなった

というわけで、これで解決です。

問題を再燃させる

でも、気になりますよね、これ!ということであえて Rancher Desktop のコンテナランタイムを "containerd" に切り替えて調査!

ここで引き下がるのはなんか悔しいってことで色々調べてみました。調べたといってもほとんど Docker Compose の YAML の書き方とか、そもそも「ボリュームってなんやねん」とか、皆無だった基礎知識のあたりを調べてた時間がほとんどですが。

まず、最初に気づいたのは起動時に Warning が出ていること。

% nerdctl compose up -d
INFO[0000] Creating network sensu_default
WARN[0000] Ignoring: volume sensu-backend-data: [Driver] <-(コレ)
INFO[0000] Ensuring image sensu/sensu:latest
INFO[0000] Creating container sensu_sensu-backend_1

もしかして、ボリュームがうまくできてないの?とか思ったけど、これは文字通りWarningで関係ないことが後で判明します。多分ですが、

ココ

Unimplemented docker volume create flags: --driver, --opt

と書かれてるので、これが原因でしょう。

色々調べてると、どうやら再起動するたびにボリュームが新たに作られていってることに気づきます。これだったら、毎回新たに etcd のデータが作られるので、毎回初期設定が必要になるのもわかります。こんな感じ。再起動のたびに新たにボリュームが作られています。

% nerdctl volume list               
VOLUME NAME    DIRECTORY
% nerdctl compose up -d
INFO[0000] Creating network sensu_default               
WARN[0000] Ignoring: volume sensu-backend-data: [Driver] 
INFO[0000] Creating volume sensu_sensu-backend-data     
INFO[0000] Ensuring image sensu/sensu:latest            
INFO[0000] Creating container sensu_sensu-backend_1     
% nerdctl volume list  
VOLUME NAME                                                         DIRECTORY
9a3721923ba55334655208752d48846585c9072f11bce8f1e7fa9f2a4a5074a0    /var/lib/nerdctl/dbb19c5e/volumes/default/9a3721923ba55334655208752d48846585c9072f11bce8f1e7fa9f2a4a5074a0/_data
sensu_sensu-backend-data                                            /var/lib/nerdctl/dbb19c5e/volumes/default/sensu_sensu-backend-data/_data
% nerdctl compose down              
INFO[0000] Removing container sensu_sensu-backend_1     
INFO[0000] Removing network sensu_default               
karma@warbird sensu % nerdctl compose up -d
INFO[0000] Creating network sensu_default               
WARN[0000] Ignoring: volume sensu-backend-data: [Driver] 
INFO[0000] Ensuring image sensu/sensu:latest            
INFO[0000] Creating container sensu_sensu-backend_1     
% nerdctl volume list  
VOLUME NAME                                                         DIRECTORY
sensu_sensu-backend-data                                            /var/lib/nerdctl/dbb19c5e/volumes/default/sensu_sensu-backend-data/_data
0b65bbacb252e1ac8953c2b2903aa7ae94b0f213952776ce568d08bdb8b794d2    /var/lib/nerdctl/dbb19c5e/volumes/default/0b65bbacb252e1ac8953c2b2903aa7ae94b0f213952776ce568d08bdb8b794d2/_data
9a3721923ba55334655208752d48846585c9072f11bce8f1e7fa9f2a4a5074a0    /var/lib/nerdctl/dbb19c5e/volumes/default/9a3721923ba55334655208752d48846585c9072f11bce8f1e7fa9f2a4a5074a0/_data

たぶん、ここは sensu-backend-data という名前のボリュームがひとつだけ作られるのが正解っぽいけど、なぜか謎のボリュームが増殖していくという…

これは何が起こっているのかコンテナ内(コンテナのMount Namespace内)を確認しないとダメだね、ってことで、やってみました。

% nerdctl ps          
CONTAINER ID    IMAGE                           COMMAND                   CREATED          STATUS    PORTS                                                                     NAMES
0eeffa3553b5    docker.io/sensu/sensu:latest    "sensu-backend start…"    2 minutes ago    Up        0.0.0.0:3000->3000/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8081->8081/tcp    sensu_sensu-backend_1    
% nerdctl exec -ti sensu_sensu-backend_1 -- /bin/sh
/ # cat /proc/self/mountinfo | grep sensu
146 125 253:1 /var/lib/nerdctl/dbb19c5e/volumes/default/sensu_sensu-backend-data/_data /var/lib/sensu/sensu-backend/etcd rw,relatime master:4 - ext4 /dev/disk/by-label/data-volume rw
147 125 253:1 /var/lib/nerdctl/dbb19c5e/volumes/default/0b65bbacb252e1ac8953c2b2903aa7ae94b0f213952776ce568d08bdb8b794d2/_data /var/lib/sensu rw,relatime master:4 - ext4 /dev/disk/by-label/data-volume rw

これでもうわかりましたね。ちゃんと指定のボリュームは作られているものの、別のマウントもされているので、おそらくはそっち側が上にマウントされてる感じかな?

ちなみに名前付きで作ってるボリュームについては、コンテナ内の別のディレクトリにマウントしてみると空でした。こっちが指定どおり sensu-backend-data という名前で作られてないのも気になりますね。("name" 属性を指定したらちゃんとその名前で作られたけど)

匿名のボリュームは /var/lib/sensu にマウントされていることから、コンテナ内に /var/lib/sensu は存在しなくても作ってくれるものの、さらにその子ディレクトリが /var/lib/sensu/sensu-backend/etcd のように指定されていると、コンテナ上にはそのようなディレクトリがないので、まずは /var/lib/sensu を作りに行って、それに新たにボリュームが作成されてマウントされてしまう感じでしょうか。名前付きのボリュームもマウントはされているので、そちらがどのような状態になっているのかが謎…

存在しないディレクトリにはマウントできないし、でも作成された後であとでマウントされたらそっちが見えるはずだし、でもどうやら匿名で作られた /var/lib/sensu にマウントされている方が上で見えているようだし…

というわけで、docker-compose.yaml には、存在しないディレクトリは /var/lib/sensu のように一段だけ指定して無事解決でした。

version: "3"
services:
  sensu-backend:
    ports:
    - 3000:3000
    - 8080:8080
    - 8081:8081
    volumes:
    - sensu-backend-data:/var/lib/sensu
    command: "sensu-backend start --state-dir /var/lib/sensu/sensu-backend --log-level debug"
    environment:
    - SENSU_BACKEND_CLUSTER_ADMIN_USERNAME=admin
    - SENSU_BACKEND_CLUSTER_ADMIN_PASSWORD=admin
    image: sensu/sensu:latest

volumes:
  sensu-backend-data:

まとめると、

  • containerd をランタイムとして使うと、volumesで指定したパスのうち、コンテナ内に存在するディレクトリ(ここでは /var/lib)の下に存在しないディレクトリ(マウントポイント)は、直下のディレクトリ(ここでは /var/lib/sensu まで)は作成してくれる
  • それ以上深いディレクトリを指定しても作ってくれなくて、とりあえず新しいボリュームを作成し、存在するディレクトリの一層下までのディレクトリまで作成し、そこにマウントしてしまう(ここでは /var/lib/sensu
  • 存在しない深いディレクトリ(ここでは /var/lib/sensu/sensu-backend/etcd)を指定すると、それもマウントはしてくれるようだが、その上にさらに上記のマウントを重ねてしまうようなので見えないので結局は使えない(マウント情報を見ての想像です)
  • Rancher Desktop でランタイムとして "dockerd" 指定すると、最初に示した YAML で問題なく動く
  • ここの volumes の指定をどのように行うのが正解なのかはよく知らない(わからない)<ドキュメントとか読んでません

という感じです。雑なまとめ。

うーん、Mac 上から VM 層が隠蔽されていると、VM 内を覗けないのでトラブルシューティングしにくいなあ…(やる方法あるのかもしれんけどしらん)

ま、これ以上は特に興味がない個別のプロダクトのお話になるのでこの辺りで終わり!

2022 年やりたいこと

技術ブログだけど、今年やりたいことといえば技術のことよりもそれ以外のことが思い浮かぶなあ。フォロワーさんが書いてるのをみて、一年の初めってのもあるし、歳もひとつとったしということで、書いてみるかなと思って書いてみました。

技術

これまで通りのことをやるくらいかな。昨年は忙しかったし、なんか仕事で色々疲れてあまり新しいことをやろうという気がおこらなかった。今年もあまりやる気が湧いてくる気もしないけど。

  • 連載記事を 2021 年よりはたくさん書きたい
  • 連載記事をまとめて技術書典に出すとか何か形にしたいな
  • linuxcontainers.org の翻訳はこれまで通り
  • コンテナの勉強会を最低 1 回はやりたい
    • けれども何もネタを思いつきません。何か面白そうなテーマが思い浮かんで、話してくれる人が見つかりますように
  • 昨年よりはもう少し新しいコンテナ関連の新技術を調べたい
  • Go とか Rust とか新しい言語やりたいな(昨年 Go はちょっと手をつけたけど結局放置…)
  • 仕事で昨年からまたセキュリティ関連やってるんだけど、まあその辺りをぼちぼちと…(あまり技術によってない感じなので(以下略))

趣味

  • 昨年よりはドラマ(韓国ドラマ)の視聴を増やしたい
  • 昨年よりはちゃんと音楽聴きたい
    • イベント復活したらいきたいですね。昨年は久々に King Crimson でコンサート行きました
  • 韓国語
    • Duolingo と NHKテレビ講座で進めて 10 分程度のヨントンに耐えられるようにしたい(それ以前にコミュニケーション能力に問題あるんだけど :-p)
    • ハングル検定 5 級くらい受けてみたいな
  • 本を読みたいな。買って放置してるやつ多い(歳と共に本を読む集中力がなくなってきた)
  • 久々にメガネを買いたいな(JFReyが好きで、これまで10本ほどヤフオクで買ってます)(2021-01-04追記)

運動

  • 昨年はワクチン接種後以外はほぼ毎日運動をしたので継続したい。内容は変わらずジムに行くか、5km ほどの決まったコースを走るか

まとめ

  • なんか「やる気に満ち溢れてる!」感がないなあ。実現しないんちゃう? :-p

『Infra Study 2nd #2「クラウドネイティブを支えるインフラ技術」』でお話してきました

6/11(金)に Infra Study 2nd #2 ってイベントで登壇しました。そのレポートを会社のテックブログで書きました。

blog.idcf.jp

まあ、参加してない方や、アーカイブ動画を見てない方は、このレポートを読むというよりは、もとのアーカイブ動画を見ましょう、って感じですね。

www.youtube.com