Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
コンテナ起動への道
Search
xorphitus
August 16, 2016
Programming
170
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
コンテナ起動への道
コンテナの要素技術を使ってみました。
xorphitus
August 16, 2016
More Decks by xorphitus
See All by xorphitus
オリジナリティのあるGitLabを標準に近づける
xorphitus
1
800
マイクロサービスを作ろう
xorphitus
0
160
型システムを学ぼうとした結果
xorphitus
0
82
M-x doctor
xorphitus
0
180
型で数を表そう
xorphitus
0
110
AOT と direct linking
xorphitus
0
92
CFS入門
xorphitus
0
91
HyperLogLog
xorphitus
0
130
immutable database
xorphitus
0
330
Other Decks in Programming
See All in Programming
社内AIエージェント「Askワンバン」における コストチューニングの取り組み
t0yohei
0
160
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
1.8k
React Native経験者が Flutterを30⽇間触って驚いたこと
3saito
0
160
선언형 햅틱 라이브러리 진동을 소개합니다
l2hyunwoo
1
300
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
160
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
1.8k
AIがコードを書いてくれる時代、我々は何を確かめるのか
yosuke_furukawa
PRO
13
5.8k
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
4
3.5k
AI駆動開発4年目の現在地(『あなたはFDEになるべきか?』イベント資料)
kumaiu
0
320
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
220
Next.js: The final boss of Web Performance
guaca
0
390
Featured
See All Featured
A better future with KSS
kneath
240
18k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
330
The SEO Collaboration Effect
kristinabergwall1
1
620
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
510
The Cost Of JavaScript in 2023
addyosmani
56
10k
Large-scale JavaScript Application Architecture
addyosmani
516
110k
Building Applications with DynamoDB
mza
96
7.3k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
630
Leo the Paperboy
mayatellez
10
2.4k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
310
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
Abbi's Birthday
coloredviolet
4
11k
Transcript
コンテナ起動への道 @xorhitus (2016-08)
Linuxコンテナの仕組み コンテナはVMとは違い、隔離された空間で動く通常のプロセスで云々 と、いう説明は今回はしません 以下のあたりが分かりやすくておすすめ • https://speakerdeck.com/tenforward/jin-sarawen-kenai-linux-kontenafalseji-ch u-2015-06-20 ◦ 氏が技評でやってる連載も良いと思う •
http://www.slideshare.net/enakai/docker-34668707
別に新しくないコンテナ技術 以下の組み合わせで隔離された空間を作っているらしい 1. Namespace 2. Cgroup 3. ネットワーク機能 4. ルートディレクトリの変更
5. bind mount 6. CRIU 7. overlayfs
よし、流行ってるし コンテナを立ち上げてみよう
$ docker run
Dockerは甘え $ docker run
まずはNamespaceから
Namespace自体は全く新しくない 初出はLinux Kernel 2.4.19 その後、2.6系の時に大部分の機能がそろう ちなみに2016年7月19日時点のArch Linux $ uname -sr
Linux 4.6.4-1-ARCH
どんなシステムコールで操作するの? • clone(2) ◦ Namespaceの設定をした新しいプロセスを生成する • unshare(2) ◦ 実行中プロセスのNamespaceを制御する ◦
unshare(1) もあるからシェルスクリプトからも色々できるよ • setns(2) ◦ プロセスを既存のNamespaceに紐付ける
clone(2)によるPIDの隔離 Cでの実装 #define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <stdlib.h>
#include <sys/wait.h> #include <unistd.h> #define STACK_SIZE 1024*1024 static char child_stack[STACK_SIZE]; static int child_fn() { printf("child - self pid: %ld\n", (long) getpid()); printf("child - parent pid: %ld\n", (long) getppid()); exit(0); } int main(int argc, char *argv[]) { int flags = SIGCHLD; int opt; while ((opt = getopt(argc, argv, "p")) != -1) { if (opt) { flags |= CLONE_NEWPID; } else { exit(1); } } pid_t child_pid = clone(child_fn, child_stack + STACK_SIZE, flags, NULL); printf("current - clone pid: %ld\n", (long) child_pid); printf("current - self pid: %ld\n", (long) getpid()); waitpid(child_pid, NULL, 0); exit(0); } -p option付与で PID隔離フラグ 噂のclone(2)
clone(2)によるPIDの隔離 実行してみる $ gcc さっきの.c $ sudo ./a.out current -
clone pid: 15573 current - self pid: 15572 child - self pid: 15573 child - parent pid: 15572 $ sudo ./a.out -p current - clone pid: 15635 current - self pid: 15634 child - self pid: 1 child - parent pid: 0 CLONE_NEWPIDフラ グを 渡さなければ PIDは隔離されない フラグを渡して PIDの隔離に成功 PID 1 は本来(?)initだよ! $ pgrep -fa init 1 /sbin/init 重複が許されている
Namespaceの情報ってどこにあるの? /proc/[pid]/ns にある 先ほどのプログラムを少し変更して、上記のパスを見てみる static int child_fn() { printf("child -
self pid: %ld\n", (long) getpid()); printf("child - parent pid: %ld\n", (long) getppid()); // この sleep を追記 (せっかくなのでC99スタイル) // ここで止まっている間に /proc/[pid]/ns を ls する作戦 (プログラム中で ls 呼べばいいとか言わないこと) sleep(100); exit(0); }
Namespace見てみますよ / PID隔離なしver $ sudo ./a.out current - clone pid:
20026 current - self pid: 20025 child - self pid: 20026 child - parent pid: 20026 $ sudo ls -l /proc/20025/ns 合計 0 lrwxrwxrwx 1 root root 0 7月 19 02:58 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx 1 root root 0 7月 19 02:58 ipc -> 'ipc:[4026531839]' lrwxrwxrwx 1 root root 0 7月 19 02:58 mnt -> 'mnt:[4026531840]' lrwxrwxrwx 1 root root 0 7月 19 02:58 net -> 'net:[4026531957]' lrwxrwxrwx 1 root root 0 7月 19 02:58 pid -> 'pid:[4026531836]' lrwxrwxrwx 1 root root 0 7月 19 02:58 uts -> 'uts:[4026531838]' $ sudo ls -l /proc/20026/ns 合計 0 lrwxrwxrwx 1 root root 0 7月 19 02:59 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx 1 root root 0 7月 19 02:59 ipc -> 'ipc:[4026531839]' lrwxrwxrwx 1 root root 0 7月 19 02:59 mnt -> 'mnt:[4026531840]' lrwxrwxrwx 1 root root 0 7月 19 02:59 net -> 'net:[4026531957]' lrwxrwxrwx 1 root root 0 7月 19 02:59 pid -> 'pid:[4026531836]' lrwxrwxrwx 1 root root 0 7月 19 02:59 uts -> 'uts:[4026531838]' 両者は一致
Namespace見てみますよ / PID隔離ver $ sudo ./a.out -p current - clone
pid: 20332 current - self pid: 20331 child - self pid: 1 child - parent pid: 0 $ sudo ls -l /proc/20331/ns 合計 0 lrwxrwxrwx 1 root root 0 7月 19 02:59 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx 1 root root 0 7月 19 02:59 ipc -> 'ipc:[4026531839]' lrwxrwxrwx 1 root root 0 7月 19 02:59 mnt -> 'mnt:[4026531840]' lrwxrwxrwx 1 root root 0 7月 19 02:59 net -> 'net:[4026531957]' lrwxrwxrwx 1 root root 0 7月 19 02:59 pid -> 'pid:[4026531836]' lrwxrwxrwx 1 root root 0 7月 19 02:59 uts -> 'uts:[4026531838]' $ sudo ls -l /proc/20332/ns 合計 0 lrwxrwxrwx 1 root root 0 7月 19 02:59 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx 1 root root 0 7月 19 02:59 ipc -> 'ipc:[4026531839]' lrwxrwxrwx 1 root root 0 7月 19 02:59 mnt -> 'mnt:[4026531840]' lrwxrwxrwx 1 root root 0 7月 19 02:59 net -> 'net:[4026531957]' lrwxrwxrwx 1 root root 0 7月 19 02:59 pid -> 'pid:[4026532213]' lrwxrwxrwx 1 root root 0 7月 19 02:59 uts -> 'uts:[4026531838]' PIDの所に注目 違う値に なっている
他のNamespace • IPC: System V IPC, POSIX メッセージキュー • Network:
ネットワークデバイス、スタック、ポートなど • Mount: マウントポイント ◦ clone, unshareした内部でmountしたものの中身が外から見えなくなる • User: ユーザー ID とグループ ID • UTS: ホスト名と NIS ドメイン名 https://linuxjm.osdn.jp/html/LDP_man-pages/man7/namespaces.7.html http://gihyo.jp/admin/serial/01/linux_containers/0002?page=2
とりあえず次、chroot
ルートディレクトリを変更する chroot(1) はみんながArch Linuxをインストールするときに いつも使っているやつ 今日はシステムコールなので chroot(2) > chrootシステムコールは、1982年3月18日(4.2BSDリリースの17ヶ月前)、 >
ビル・ジョイがインストールおよびビルドシステムのテスト用に > 作成したのが期限である。 Wikipediaより
chroot(2) によるルートディレクトリ隔離 #include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <unistd.h>
#define PATHNAME_SIZE 512 void show_dir(char *dirname) { struct dirent **namelist; int r = scandir(dirname, &namelist, NULL, NULL); if (r == -1) { exit(1); } printf("--- list files in directory '%s' ---\n", dirname); for (int i = 0; i < r; i++) { printf("%s\n", namelist[i]->d_name); } } int main(int argc, char *argv[]) { show_dir("/"); char current_path[PATHNAME_SIZE]; getcwd(current_path, sizeof current_path); printf("\nchange root to '%s'\n\n", current_path); int r = chroot(current_path); if (r == -1) { printf("chroot failed"); exit(1); } else { show_dir("/"); exit(0); } } 噂のchroot(2)
chroot(2) によるルートディレクトリ隔離 $ sudo ./a.out --- list files in directory
'/' --- lib boot srv bin run tmp root sys lib64 etc (以下略) (実行結果の続き) change root to '/var/tmp/my_chroot' --- list files in directory '/' --- my_chroot.c a.out . .. / の変更に成功
と、ここで気付く Cでシステムコールするより、やっぱユーザコマンドを叩いた方が楽だよね $ unshare -imnpuU $ chroot … $ cgcreate
… $ ip link … いや、分かっていたけど気づかないフリをしていたんだ
すごいぞユーザコマンド! コンテナを作るのが楽になる!!
まとめというか感想 • こんな感じで地道にやっていけばいつか自前コンテナは立ち上がる ◦ ユーザコマンドまじ有能 ◦ Dockerは甘え • 温故知新 •
WebプログラマはWeb f/w使いになりがちなので、たまにはこういうのを書くのは充 足感がある • ちなみに今回のコードはここに置いた ◦ https://github.com/xorphitus/making-linux-container