2.8K Views
April 18, 21
スライド概要
研究室内で使用予定のコンテナ入門スライドです。
Container入門 2021-04-?? 丹羽 直也 1
この研修の目的 • 研究インフラとしてDockerなどのコンテナ技術を使える知識を身につける • ふんが研での運用ルール私案を伝える ◼ そして、フィードバックを得たい 2
目次 • ROAD to CONTAINER • 解決したい問題 • コンテナの使い方/コンテナ探訪 • 研究室での運用方法案 3
ROAD to CONTAINER • コンテナ技術とは何かを説明する。 • コンテナ技術に行き着くまでの系譜を大雑把にたどる。 ◼ 技術史としての順序が正しいわけではないのはご注意を • なぜコンテナ技術が求められているのだろうか? 4
仮想化 • コンテナ技術はソフトウェアを仮想的な環境で動かすための技術の一つ • なぜ仮想化するのか、何を仮想化するのかを追っていこう 5
ソフトウェアの“Environment” • 最も素朴に捉えるならばソフトウェアは機械語列 • この場合のEnvironmentはCPUの”Core” • アーキテクチャ系研究室なので、ここからスタートしてコンテナに辿り着こう ユーザーが用意するもの これをなるべく使いまわしたい! Software Machine codes 界面(interface) Core 根本的な目的 : きちんと機械語を「環境」に食わせれば正しく動く 6
機械語レベルのInterfaceは「レジスタ」 • プログラムカウンタ(PC)を始めとする各種レジスタ類 ◼ ソフトウェアはレジスタを制御し、レジスタがソフトウェアを制御する。 Software Machine codes PC add addi bne x2, x4, x1 x2, x2, 1 x2, x3, hoge 汎用レジスタ FPレジスタ … Core 7
レジスタレベル仮想化(造語) • あとでレジスタさえ再現できれば、他のことにCoreを使っても問題ない ◼ ◼ PC 要はマルチタスキングである レジスタ退避は一般にはOSによって行われるが、fiberのようにソフトウェアが自力でやっても 良い レジスタを一時的に保存すること で、Software1,2を自由なタイミング プロセス プロセス で動かすことができる。 Software1 Software2 Machine codes Machine codes 汎用レジスタ PC 汎用レジスタ PC 汎用レジスタ FPレジスタ FPレジスタ FPレジスタ … … … Virtual Core Virtual Core Actual Core 8
機械語レベルのInterfaceには「メモリ」もある • CoreにメモリIOを指示する命令も当然多く使われる ◼ メモリは1つのアドレスを持つ1次元の記憶域 0x0000 Software Machine codes Memory PC Load /Store lw addi sw lw addi sw x4, x4, x4, x4, x4, x4, 0x05(x0) x4, 1 0x05(x0) 0x05(x0) x4, 2 0x05(x0) 汎用レジスタ FPレジスタ … 0xFFFF Core 9
このままでマルチタスキングすると… • 同じプログラムを実行できない!! ◼ プログラムを用意する時点で実行時のアドレス調停が必要になる。 初期値 : 10 lw addi sw lw addi sw x4, x4, x4, x4, x4, x4, 0x05(x0) x4, 1 0x05(x0) 0x05(x0) x4, 2 0x05(x0) 11? 12? 13? 14? 15? 16? lw addi sw lw addi sw x4, x4, x4, x4, x4, x4, 0x05(x0) x4, 1 0x05(x0) 0x05(x0) x4, 2 0x05(x0) Software Software Machine codes Machine codes Virtual Core Load/Store Memory (0x05) Load/Store Virtual Core 10
アドレス空間仮想化(仮想記憶) • プロセス毎に専用のアドレス空間を用意する 0x0000 0x0000 Virtual Memory Load/Store Virtual Core Software Virtual Core Software 0xFFFF Actual (Physical) Memory MMU 0x0000 Virtual Memory Load/Store 0xFFFF 0xFFFF 被らないようにいい感じにマッピング(詳細はヘネパタ) 11
なぜ仮想化したいのか? • ソフトウェアをプログラムする、という行為と、ソフトウェアを実行する、という行 為を分離したい! ◼ 実行環境がプログラミングを左右する要素を可能な限り削りたい。 • 極端な話をするなら、すべての実行計画が予め定まっているのであれば、仮想記憶も OSもなしに100個のプログラムを並行(concurrent)に1つのコアで実行することが可能 である。 ◼ ◼ 予めメモリ上に物理アドレスとレジスタ退避タイミングを調整したプログラムを100個分配置す れば良い。 でもこれを一度やったあとに101個目のプログラムを追加したくなったら? • すべての調整をやり直す必要がある。まったくもって実用的ではない。 • ソフトウェアの「環境」を実行時環境に左右されないものにしたい ◼ ◼ これによって初めてソフトウェアは再利用可能になる。 (私見)ソフトウェアは何度も実行されることでより高い価値を得る。 • 一回しかしない計算ならコンピューターではなく電卓でやったほうが速い 12
補助記憶など • Memory(主記憶)だけでソフトウェアは完結しない。 ◼ 大抵はファイルという形で補助記憶を扱うだろうし、何らかの出力も行うだろう。 • 補助記憶も主記憶同様の1次元のアドレスを持った記憶域、ではある。 ◼ だが、生で1次元のデータを扱うのはあまりに使いにくい • 他にも画面やキーボードなど雑多なデバイスがいっぱい ◼ 仲介者が必要 HDD、SSDなど ? Virtual Core Software 次スライドから「Process」 Virtual Core Software 13
Operating System • レジスタ、仮想記憶以外に触りたければOSを使え! ◼ そもそもソフトウェアをメモリにロードするのもOSの仕事だが • ご存知の通りOSの役割は膨大だが、今回はコンテナで重要になるファイルとネット ワークに絞っていく HDD、SSDなど OS Process Process 14
OSとのInterface • 当然OSによって違う ◼ なおISA(x86,x64,IA64,ARM,ARM64など)が違う場合、同じ名前のOSでも割と別 Software(ユーザーが用意) function call 余談:ここの超え方がISAで変わってくる。 なおここでのsyscallはx86_64命令 0F 05のこ とであり、Unix System Callsではない。 Linux x86 : int 0x80などCPU依存(vsyscall) ← これがWSLは32bit ELFを動かせない一因 Linux x64 : syscall Windows x86 : CPU依存(int 0x2e or sysenter, 一部AMDではsyscall。使えるなるべく速い ものを選ぶ。2500cycles (int) → 500cycles (sysenter)ぐらい) Windows x64 : syscall Windows IA64 : epc Software Win32 API(function call) Kernel32 GDI32 glibc (vsyscall含む) syscalls kernel Linux この辺 にも 色々あ る … Ntdll.dll User-mode Kernel-mode system service dispatch Ntoskrnl.dll win32k.sys Windows ↓ドキュメント化され、互換性が考慮されたInterface 15
OS Interfaceの仮想化 • もちろん先のを仮想化する技術もある Software (32bit) Software WINEとかLibrary OSとか色々ある kernel32 … (32bit) Ntdll.dll (32bit) Wow64cpu.dll Wow64.dll Guest OS ISA VMM ISA Ntdll.dll (64bit) Linux ELF SSD syscalls Ntoskrnl.dll (64bit) User-mode Ntoskrnl.dll Kernel-mode Lxss.sys Physical Core 仮想マシン WOW64 (Win32 emulation on 64-bit Windows) WSL (Windows Subsystems for Linux) 16
OS Interface(syscalls)の向こう側 • 要はすべてがあるのだが、コンテナでは以下2つが大きな関心事 ◼ ◼ ファイル(ディレクトリツリー) ネットワーク • 以降すべてLinuxの話(Windowsコンテナもあるけど研究室では使わない) Linux ストレージ Network (via NIC) AHCI,SCSI,NVMe VFS なお問題児もおる…(後述) ioctl Ethernet, Infiniband Socket syscalls Process ストレージはディレクトリ ツリーという扱いやすい形 で抽象化 ネットワークはSocketとして 抽象化 17
syscallsの向こう側を見据えたソフトウェア(Process)の環境 Virtual Memory Load/Store Process syscalls データ類 共有ライブラリ syscallsで受け取ら ないけど図の都合 でここに入れます。 VFS kernel 環境変数 ioctl Socket stdio(tty) ioctlはデバイス制御のためのsyscallである。ターミナ ルのサイズを取得したり、GPIOの設定したり、NIC一 覧を取得したりと、とにかく多様な使い道がある。故 に問題児である…。 • VFSを介した統一的なファ イルアクセス • “/”を起点とした構造 • 共有ライブラリの探 索はディレクトリツ リーの構造と環境変 数により決定する • デバイスファイルも ディレクトリツリー に入る コンテナはこれらを仮想化、す なわち「実行時環境に非依存に して、事前に制御可能とする」 18
GOAL of “ROAD to CONTAINER” • syscallsの向こう側を仮想化する Computer Virtual Memory 普通のプロセス コンテナ内のプロセス メモリは普通の プロセスと同じ Virtual Memory Process syscalls Process syscalls VFS kernel 環境変数 ioctl Socket stdio(tty) (真の)VFS VFS kernel 環境変数 (Limited)ioctl Socket stdio(tty) コンテナで仮想化 仮想ネットワーク Socket 19
解決したい問題 研究室で起きる問題でコンテナによって解決できそうなもの 20
Dependency Hell(DLL Hell) • ソフトウェアはいろんな共有ライブラリに依存している ◼ ◼ 確認 : 共有ライブラリは実行時に読み込まれるライブラリ Python packageのようなインタプリタが読み込むのも同類 別の環境でビルドしたので動かないgem5 • 共有ライブラリの目的 ◼ 容量の削減 • ほぼみんなが使うglibcは3MBちょいある。もしLinux内のすべての実行 ファイルがこれを内蔵していたら…? ◼ リビルド無しでパッチを当てる • 共有ライブラリを使わずにライブラリのバグ修正を行うには、利用する ソフトウェアすべてのリビルドと再配布が必要になる。アップデート サーバーが落ちちゃう… • 共有ライブラリが引き起こす問題 ◼ 実行時環境の要件が厳しくなる • ユーザーはライブラリを予めインストールしておく必要がある。 ◼ どうやってバージョンを指定する?(Hellは主にこれ) • 完全固定をしたらパッチを当てられない、どこまで互換性がある? • アップデート後に起動するけど動作がバグるとかありえる。 Python環境の依存関係 https://tech.instacart.com/freezing-pythons-dependency-hell-in2018-f1076d625241 より引用 21
再現性の確保 • とある学生の物語 ◼ ◼ ◼ ◼ ◼ ◼ ◼ ◼ ◼ ????「XXXを動かせました!やりました!データ取れたぞ!」 ~1ヶ月後~ ????「パラメータ変えてXXXを再実行しよう!」 XXX「Error : error while loading shared libraries」 ????「あれ、ライブラリ入れ忘れかな。ライブラリ入れて元のパラメータに戻して…」 XXX「Error : segmentation fault」 ????「 」「リビルドしよ」 gcc「File not found」 ????「 」 • 研究用のツールというのは概して移植性がゴ○である。 ◼ ◼ ◼ 天使の声「移植性を確保する時間があったら研究しろ」 コンテナ、もしくはそれのもととなるDockerfileを書いておけば、環境を再現しやすくなる (論文に書いたデータ、自分ですら再現できないってやばいじゃん?) 22
コンテナの使い方/コンテナ探訪 実際の使い方を踏まえつつ機能を探訪していきます 23
2つのコンテナ実装 Docker, Podman • 機能はほぼ同じ ◼ ◼ 中身はrunc Dockerは管理用デーモンあり、Podmanはない • 現在は圧倒的にDockerが主流 ◼ パイオニア的実装なので • ただ研究室では今の所混在 ◼ まあDockerに統一が無難かなと思っている • ということで、原則Dockerを前提に話をすすめる 24
Dockerで抑えておきたい要素 • コンテナ ◼ ◼ 仮想的なファイルツリー、ルートプロセスとその状態を持つ ネットワークとかも構成されているかも • イメージ ◼ ◼ コンテナの雛形 仮想的なファイルツリー • Docker Hub https://hub.docker.com/ ◼ ◼ ◼ イメージをホストしている 各種パッケージングマネージャーのリポジトリみたいな認識で良い なお、Dockerで「リポジトリ」というとイメージ名的なものを指す(ややこしい) • 下から説明する ◼ いきなりコンテナから話すと重いので • 困ったらドキュメントを読む https://docs.docker.com/ ◼ https://docs.docker.jp/index.html ←ここも大変良い 25
Docker Hub https://hub.docker.com/ • イメージがおいてあるサイト ◼ Dockerを使うときには、ここにあるど れかのイメージを基礎にコンテナを構 築する • アカウント登録すれば誰でもイメー ジを公開できる ◼ ◼ ◼ これはすなわち悪意のあるプログラム もアップロードできることを意味して いる。 Docker Hubに仮想通貨を発掘する不正 なコンテナ--Kubernetes悪用の恐れも ZDNet Japan https://japan.zdnet.com/article/35120944/ 提供元には要注意 • バイナリを直接アップロードするシステム なので、中身の調査が比較的難しい 例 : Go処理系のイメージ 26
イメージ • ルート“/”から始まるファイルツリーが収まった仮想的なストレージ ◼ SHA-256ハッシュによる一意のIMAGE IDが振られている • 下記のように普通は短縮表示されている ◼ 物によってはREPOSITORYやTAGが設定されている • この”REPOSITORY”は先の”golang” のように特定の名前のついたイメージ管理単位 • GitHub的なニュアンスと取ると良さそう • “TAG”はバージョンを指すと思ってもらって問題ない ◼ ◼ Read Only(RO)である Docker Hubからpullしてきたり、それをベースに手動、もしくはDockerfileを書いて作成する イメージ一覧の表示例 [naoya@axion ~]$ docker images REPOSITORY TAG IMAGE ID naoya_gem5 latest 48156141ad5e <none> <none> e770a02c7c94 <none> <none> 86f96000b98e CREATED 2 months ago 2 months ago 2 months ago SIZE 3.08GB 3.08GB 3.08GB 27
Dockerfile • イメージを構築するための命令列 ◼ 必ずFROMから始まり、元となる親イメージを指定する • リポジトリ[:タグ]という書式で指定する。詳細はドキュメント ◼ Dockerfileをおいたディレクトリで docker build することでイメージが構築される Dockerfileの例 FROM ubuntu:16.04 LABEL maintainer Naoya Niwa <[email protected]> RUN apt-get update RUN apt-get install -y build-essential git-core m4 scons zlib1g zlib1g-dev libpcre3-dev curl RUN apt-get install -y software-properties-common 上のファイルをビルド(長すぎて全然収まってないけど…) [naoya@axion docker]$ docker build -t naoya_gem5 . Sending build context to Docker daemon 39.56MB Step 1/36 : FROM ubuntu:16.04 ---> 77be327e4b63 Step 2/36 : LABEL maintainer Naoya Niwa <[email protected]> ---> Using cache ---> 34e6bfb7da16 Step 3/36 : RUN apt-get update 28
環境構築手順をDockerfileにつらつら書いていくのが基本 • よく使う命令 ◼ RUN : コンテナ(ここでは≒イメージ)内でコマンドを実行する • ベタで書くとシェル( /bin/sh )経由、配列形式で書くと exec*(syscall) で実行 ◼ COPY(ADD) : コンテナの外からコンテナ内にファイルを追加する • ビルドコンテキスト、すなわちカレントディレクトリより下のファイルしか追加できない(理由は後述) ◼ ◼ WORKDIR : コンテナ内でのカレントディレクトリの移動 ENV : コンテナ内で永続的な環境変数の設定 • RUN k=v での環境変数はそこで立ち上がったシェル内で設定されるので、RUNが終わったら消える ◼ CMD/ENTRYPOINT : コンテナ開始時のデフォルトのコマンドを指定 • それぞれ1つのみ可能。細かい違いはドキュメントをご参照あれ。困ったらCMD ◼ EXPOSE : ネットワークのポートを開ける • 他はドキュメント読んで ◼ https://docs.docker.com/engine/reference/builder/ 29
ビルドコンテキスト • イメージ構築時に使えるファイルはカレントディレクトリ以下に格納されたファイル のみである • この使えるファイルたちを「ビルドコンテキスト」と呼ぶ ◼ ◼ 下記ビルドログで赤字で示したとおり、真っ先にそれらはすべてDocker daemonに送られる カレントディレクトリ以下に不必要なでかいファイルを置いていると遅くなる • 必要に応じて .dockerignore するか親ディレクトリに移動を ◼ もちろんignoreしたらCOPYできない • 例えば gem5 だと kernel や img はビルド時には必要ないので、別のディレクトリ [naoya@axion docker]$ docker build -t naoya_gem5 . Sending build context to Docker daemon 39.56MB Step 1/36 : FROM ubuntu:16.04 ---> 77be327e4b63 Step 2/36 : LABEL maintainer Naoya Niwa <[email protected]> ---> Using cache ---> 34e6bfb7da16 Step 3/36 : RUN apt-get update 30
レイヤーとCOW(Copy-On-Write) • Dockerfileの命令1つ1つに対してイメージが生成される(レイヤー) ◼ ◼ ◼ ある命令に対応するイメージは直前の命令に対応するイメージとの差分になっている COWの仕組みの上で命令を実行→差分を保存という仕組み 生成されたイメージにはIDが振られ、ROとなる • 変更したいときは差分を作り必ず新しいIDが振る • この資料がわかりやすいかも https://www.slideshare.net/zembutsu/explaining-bestpractices-for-writing-dockerfiles [naoya@axion dockertest]$ docker history d50ec84fdc52 IMAGE CREATED CREATED BY d50ec84fdc52 32 seconds ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "cat … 8577984de217 33 seconds ago /bin/sh -c #(nop) COPY file:3b0023cc7800aa04… d8935d81d484 33 seconds ago /bin/sh -c #(nop) WORKDIR /root 5b5e46372de0 33 seconds ago /bin/sh -c apt-get update adafef2e596e 8 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] <missing> 8 months ago /bin/sh -c mkdir -p /run/systemd && echo 'do… <missing> 8 months ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… <missing> 8 months ago /bin/sh -c [ -z "$(apt-get indextargets)" ] <missing> 8 months ago /bin/sh -c #(nop) ADD file:cf87af1f0e27aa6ff… SIZE 0B 14B 0B 27.4MB 0B 7B 811B 1.01M
FROM ubuntu:20.04 ビルドキャッシュ FROM ubuntu:20.04 RUN apt-get update • レイヤーの仕組みを使うことで、 差分ビルドが可能 FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY(ADD)はファイルの 中身もハッシュに組み 込まれている FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test01.txt . FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test01.txt . CMD cat test01.txt この2つのイメージだけ を生成すれば良い test01.txt の変更 FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test01.txt . FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test02.txt . Dockerfile FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test01.txt . CMD cat test01.txt FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test02.txt . CMD cat test01.txt 変更前 変更後 32
コンテナ • ストレージとプロセス、その他ネットワーク設定 などを抱える ◼ ◼ ストレージはイメージ(RO)にCOWな差分(RW : ReadWrite可能)を1枚重ねたもの プロセスは”ROAD to CONTAINER”の通りの仮想化が施さ れている • Linuxではchroot, cgroupsなどを駆使 • コンテナはPID名前空間を持つ ◼ docker run などでメインで立ち上がるのがPID 1 FROM ubuntu:20.04 RUN apt-get update WORKDIR /root COPY test01.txt . CMD cat test01.txt Dockerfile (ビルド後のID d50ec84fdc52) It is test01. https://docs.docker.jp/storage/storagedriver/imagesandcontainers.html より引用 test01.txt [naoya@axion dockertest]$ docker run d50ec84fdc52 It is test01. [naoya@axion dockertest]$ docker run d50ec84fdc52 ps PID TTY TIME CMD 1 ? 00:00:00 ps 33
名前をつけよう • コンテナ起動時にIMAGE IDを指定するの はまったくもって使いにくい ◼ また、後述の運用ルール案にも不都合 • 継続的に使うなら名前をつけよう ◼ ◼ docker build –t <name>[:tag] tagは無指定だとlatestとなる [naoya@axion dockertest]$ docker build -t dockertest . Sending build context to Docker daemon 15.87kB Step 1/5 : FROM ubuntu:20.04 ---> adafef2e596e Step 2/5 : RUN apt-get update ---> Using cache ---> 5b5e46372de0 Step 3/5 : WORKDIR /root ---> Using cache ---> d8935d81d484 Step 4/5 : COPY test01.txt . ---> Using cache ---> 8577984de217 Step 5/5 : CMD cat test01.txt ---> Using cache ---> d50ec84fdc52 Successfully built d50ec84fdc52 Successfully tagged dockertest:latest [naoya@axion dockertest]$ docker run dockertest It is test01. 34
コンテナは消そう • 普通にdocker runで動かしたコンテナはプロセスが終了しても消えない ◼ docker ps –a でExitedのを見るとずらーーーーーーーーーーということに • docker run --rm で立ち上げることで、終了時に自動で消えるようにできる ◼ 保存したいデータはどうするのって…?volume mountしましょう(次スライド) [naoya@axion dockertest]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS [naoya@axion dockertest]$ docker ps -a CONTAINER ID IMAGE COMMAND aaab85665aa6 dockertest "/bin/sh -c 'cat tes…" 9090545861d7 d50ec84fdc52 "ps" b23343045eeb d50ec84fdc52 "/bin/sh -c ps" 4ffcfe008894 d50ec84fdc52 "/bin/sh -c 'echo 34…" 49309289b7be d50ec84fdc52 "/bin/sh 3442866" f144576585be d50ec84fdc52 "/bin/bash 3442866" c4e736310ad4 d50ec84fdc52 "echo 3442866" 917b9b4e209c d50ec84fdc52 "echo 3442866" cc6daa5e2f82 d50ec84fdc52 "echo" 15207849dbc4 d50ec84fdc52 "echo " 1aae8027cf0f d50ec84fdc52 "/bin/sh -c 'cat tes…" PORTS NAMES CREATED 5 minutes ago 11 minutes ago 11 minutes ago 11 minutes ago 11 minutes ago 11 minutes ago 12 minutes ago 12 minutes ago 12 minutes ago 13 minutes ago 17 minutes ago STATUS Exited (0) 5 minutes ag
ビルドに必要ないファイル、永続化したいファイルはvolume mount • ここまで説明してきたCOW(レイヤー)をバイパスしてディレクトリをマウント ◼ ◼ ◼ コンテナ内外で直接共有できる 代わりに先のレイヤーの恩恵は無い 例 : Dockerfileでgem5をビルドして、kernelやimage、制御スクリプトをmount • また、COW部のIOは遅いのでそれを回避できるという利点も ◼ ◼ ◼ 気合い入れて環境構築すると速くなるけど研究室では特に気合を入れる理由も無いので、遅い ままです まあ金で殴って高速なマシンで動かしているので無視できる ↓ビルドコンテキストに入れたくない以下のようなファイルもサクッと読める [naoya@axion dockertest]$ total 5.0G -r--r-----. 1 12357 11500 -rw-r--r--. 1 12357 11500 -rw-r--r--. 1 12357 11500 -rwxr-xr-x. 1 12357 11500 drwxr-xr-x. 1 12357 11500 -rw-r--r--. 1 12357 11500 docker run --rm -v /home/hlab/naoya/jupiter/images:/root dockertest ls -lh /root/x86/disks 2.0G 512M 512M 66 0 2.0G Mar Apr Mar Apr Apr Mar 8 2020 linux-bigswap2.img 8 2020 linux-x86-omp.img 8 2020 linux-x86.img 7 2020 mount.sh 7 2020 ompimage 8 2020 x86root-parsec.img 36
Everything is a file. Is it TRUE? • ここまでで、ファイル絡みはきちんとコンテナに繋げられる • すべてがファイルとする、というのがUnixの夢 • Simple answer : No • 現実にネットワークやデバイス制御はファイルとして提供されていない ◼ ◼ ioctl, socket etc. つまりファイルシステムを仮想化しただけではcontainerは完成しない • 余談 : Plan 9 ◼ ◼ このすべてをファイルというのを推し進めるベル研究所のプロジェクト 9PやUTF-8などの技術を生み出した 37
STDINをアタッチする • さっきの”ps”の結果で見えたように初期状態ではTTYなしで動く ◼ ◼ 走らせっぱなしのプログラムならこれで問題ない でも、これだとシェルが使えない • docker run –it (-i -t)でシェルを立ち上げるとちゃんと使える ◼ ◼ ◼ 意味としては –i でSTDINをつなげ、-tで疑似ttyを割り当てる なおコンテナはその利用形態からDocker Hubのベースイメージにbashが入ってないことが多い /bin/bash がなければ /bin/sh を指定するか、Dockerfileを書き換えてbashを入れよう [naoya@axion dockertest]$ PID TTY TIME 1 ? 00:00:00 [naoya@axion dockertest]$ PID TTY TIME 1 pts/0 00:00:00 [naoya@axion dockertest]$ [naoya@axion dockertest]$ # ls test01.txt docker CMD ps docker CMD ps docker docker run --rm d50ec84fdc52 ps run --rm -it d50ec84fdc52 ps run --rm d50ec84fdc52 /bin/sh run --rm -it d50ec84fdc52 /bin/sh 38
Docker デフォルトネットワーク • デフォルトでNAT諸々が構成されたbridgeネットワークが動いている ◼ DockerfileのEXPOSEはコンテナからDockerのネットワークにポートが開いてるだけで、コンテナ を動かしているコンピューターの外から見られない [naoya@axion dockertest]$ ip a (色々略) 5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:fd:fe:3a:25 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:fdff:fefe:3a25/64 scope link valid_lft forever preferred_lft forever コンテナ外 # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 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 54: eth0@if55: <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 link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever コンテナ内 39
ioctlは…? • 爆発だあああああ! • こまけえことはググれ! • 事故ってから調べても遅くない! • 初期状態では大幅に制限されているけど privileged で突破できるよ! ◼ 名前通り扱い要注意だけど • Google「Docker privileged」 40
仮想マシンでよくね? • 実際良い • でも遅いし不便だ ◼ ◼ ◼ ◼ イメージにカーネルも入るのでかい 起動が遅い メモリをバカ食いする ページキャッシュをホストと共有できない • 無策だと2重にキャッシュされてメモリをバカ食いにさらに拍車がかかる ◼ Docker Hubの様な便利なエコシステムがない 豆知識:WindowsもLinuxも 「空き」とされていると ころにはページキャッ シュがある • まあvagrantとかあるけど… • ただ、ディスクIOに関しては仮想マシンの方が速いことも多々 ◼ ◼ ◼ これは技術的アプローチではなく実装に起因する問題で、コンテナでディスク差分管理をして るところはそのオーバーヘッドが大きい volumeなどでバイパスしよう ただコンテナ関連の処理がkernelで詰まるケースもあり、これはしょうがない 41
コンテナで得られる効果 • (巷ではもっと色々効果あるけど) • 研究室で言うなら ◼ ◼ ◼ ◼ ライブラリが静的リンクされていないソフトウェアでも、静的リンクしたのと同様の可搬性が 確保できる 環境構築を自動化できる ホストOSのアップデートをきちんと行える(neutrinoみたいな地獄を避けられる) 履歴書にDocker使えますって書ける • 問題点 ◼ ◼ ◼ root権限が無いとぶっちゃけ使い物にならない Rootlessモードもあるが、実験的であり、バグる、遅い、設定がめんどくさい Rootlessでなくてもdockerグループに足すと動かせるが、ファイルがroot権限で作られたりしたと きに結局対処にroot権限がいる 42
研究室での運用方法案 • 名前をつけてないイメージ、止まっているコンテナは消すぞ!!!!! ◼ ◼ docker system prune で無断で消していく 消さないとガンガンストレージがうまる • 先のビルドキャッシュ、消す仕組みなかったよね? ◼ そう、無いんです。上限なしのキャッシュなので…。 • お作法 ◼ ◼ ◼ 消えてほしくないイメージには名前をつける run には --rm をつけてコンテナを消す docker buildで再現できるようDockerfileを書く [naoya@axion ~]$ docker system prune WARNING! This will remove: - all stopped containers - all networks not used by at least one container - all dangling images - all dangling build cache Are you sure you want to continue? [y/N] y Deleted Containers: aaab85665aa6e30c8a1fb65fcc77d46eca5c645e1792a7012b3981d0dd76fee0 9090545861d79b53d6c505d2a9b9745d975ed2fe17a6a9d40feeeba0fb487591 …(続く) Deleted Images: deleted: sha256:e4a9b229cdca48126c1d546bbd8a7eecd4ba015f119c7a299a453391af4a801a deleted: sha256:78d29cb63a3ea60a40f818f7e40bb0e104fc4761fa60d505fbecbff5a23cc4b0 …(鬼のように続く) 43
Have a nice Container Life. 44