Mais conteúdo relacionado
Semelhante a BuildKitによる高速でセキュアなイメージビルド (20)
Mais de Akihiro Suda (20)
BuildKitによる高速でセキュアなイメージビルド
- 1. Copyright©2018 NTT Corp. All Rights Reserved.
NTT ソフトウェアイノベーションセンタ
須田 瑛大
BuildKitによる
高速でセキュアなイメージビルド
Container Build Meetup#1 (2018/10/09)
https://slideshare.net/AkihiroSuda
- 2. 2
Copyright©2018 NTT Corp. All Rights Reserved.
• コンテナ関連OSSのメンテナ(いわゆるコミッタ)を務めている
• Docker Moby メンテナ (2016年11月~)
• 2017年4月,OSSプロジェクトとしてのDockerはMobyに名前が変わった
• 商用製品としてのDockerはMobyをベースとして開発されている
• Moby BuildKitメンテナ (2017年夏 プロジェクト発足時~)
• 次世代 `docker build`
• CNCF containerdメンテナ (2017年9月~)
• Kubernetesなどで利用できる次世代コンテナランタイム
: ≒ :
RHEL Fedora
自己紹介
- 3. 3
Copyright©2018 NTT Corp. All Rights Reserved.
• Dockerfileと呼ばれるシェルスクリプト風言語を用いて,コンテナイメー
ジをビルドする
• 各命令は,overlayfsなどのCopy-on-Writeファイルシステムを用いてキ
ャッシュされる
`docker build` の復習
mount –t overlay
–o lowerdir=0,upperdir=1 ..
FROM golang:1.11
COPY . /go/src/github.com/foo/bar
RUN go build –o /bar github.com/foo/bar
mount –t overlay
–o lowerdir=1,upperdir=2 ..
- 4. 4
Copyright©2018 NTT Corp. All Rights Reserved.
• Docker 17.05からはマルチステージDockerfileが利用可能
• 最終的なイメージのサイズを小さくできる
`docker build` の復習
FROM golang:1.11 AS foobar
COPY . /go/src/github.com/foo/bar
RUN go build –o /bar github.com/foo/bar
FROM alpine:3.7
COPY –-from=foobar /bar /
"bar"だけを
最終的なイメージに
コピー
- 5. 5
Copyright©2018 NTT Corp. All Rights Reserved.
• `docker build`を実行するには,(`docker run`などと同様に)Docker
デーモンがroot権限で起動している必要がある
• `docker build`は`docker run`に似ているが,セキュリティ上の観点な
どから,機能が制限されている
• ボリューム機能が無い (`docker run -v`, `docker run --mount`)
• privilegedモードが無い (`docker run –-privileged`)
`docker build` の復習
- 6. 6
Copyright©2018 NTT Corp. All Rights Reserved.
• Dockerfileのキャッシュが効きにくい
• DockerfileのN行目を書き換えると,N+1行目以降のキャッシュは破棄される
• ユーザはDockerfileの命令の順序に気をつける必要がある
• コンパイラやパッケージマネージャのキャッシュが保存されない
• ~/.m2 (Maven), ~/.cache/go-build (Go), /var/cache/apt (apt) など
• ビルドコンテキストの転送に時間がかかる
• ソースを1行編集しただけでも,ソース全体をtar ballとしてデーモンに送信する必要
がある
従来の`docker build`に対する不満: パフォーマンス
FROM debian
EXPOSE 80
RUN apt update && apt install –y HEAVY-PACKAGES
EXPOSEを書き換えるだけでRUNのキャッシュが効かなくなる
- 7. 7
Copyright©2018 NTT Corp. All Rights Reserved.
• 並列実行できるはずの命令を,並列実行してくれない
従来の`docker build`に対する不満: パフォーマンス
FROM golang AS stage0
...
RUN go build –o /foo ...
FROM clang AS stage1
...
RUN clang –o /bar ...
FROM debian AS stage2
COPY --from=stage0 /foo /usr/local/bin/foo
COPY --from=stage1 /bar /usr/local/bin/bar
0
2
1
各ステージの依存性は
DAGとして表現できる
- 8. 8
Copyright©2018 NTT Corp. All Rights Reserved.
• 並列実行できるはずの命令を,並列実行してくれない
従来の`docker build`に対する不満: パフォーマンス
FROM golang AS stage0
...
RUN go build –o /foo ...
FROM clang AS stage1
...
RUN clang –o /bar ...
FROM debian AS stage2
COPY --from=stage0 /foo /usr/local/bin/foo
COPY --from=stage1 /bar /usr/local/bin/bar
0
2
1
0
1
2
シーケンシャルにしか
実行してくれない
- 9. 9
Copyright©2018 NTT Corp. All Rights Reserved.
• プライベートなGitやS3などへのアクセスが困難
• `COPY`命令で鍵を置くのは危ない
• ステージを分けるか `--squash` しないと鍵が漏れる
• 環境変数を使うのも危ない
従来の`docker build`に対する不満: セキュリティ
FROM ...
COPY id_rsa ~/.ssh
RUN git clone ssh://...
RUN rm –f ~/.ssh/id_rsa
rmしてもレイヤの
tarからは消えない
- 10. 10
Copyright©2018 NTT Corp. All Rights Reserved.
• root権限が必要であるため,HPC環境や,Kubernetesクラスタ上などで
は,利用を許可されないことがある
• 個人上のラップトップ上で実行する場合でも,セキュリティ上のリスクが
大きい
• CVE-2014-9356:不正なDockerfileをビルドすると,ホストのroot権限を奪取される
(シンボリックリンクを扱う部分のバグ)
• CVE-2014-9357:同 (LZMAアーカイブを扱う部分のバグ)
従来の`docker build`に対する不満: セキュリティ
- 11. 11
Copyright©2018 NTT Corp. All Rights Reserved.
• DAG構造を備える中間言語であるLLBを用いる
• Protocol Buffers形式
• 依存性を正確に表現できるので,キャッシュがよく効く
• 命令を並列実行できる
• LLBは主にDockerfileからコンパイルされる
• Dockerfile以外の言語からのコンパイルも可能 (Heroku, CFのBuildpacksなど)
• 他にも,コンテキストの差分転送などの最適化有り
BuildKit: 次世代 `docker build`
コンパイル
Dockerfile
LLB DAG
Buildpacksなど
docker-image://alpine
Image
git://foo/bar
docker-image://gcc
Run("apk add ..")Run("make")
3命令を同時に実行できる
2
- 12. 12
Copyright©2018 NTT Corp. All Rights Reserved.
• DAG構造はマルチステージDockerfileを用いて簡単に記述できる
BuildKit: 次世代 `docker build`
FROM golang AS stage0
...
RUN go build –o /foo ...
FROM clang AS stage1
...
RUN clang –o /bar ...
FROM debian AS stage2
COPY --from=stage0 /foo /usr/local/bin/foo
COPY --from=stage1 /bar /usr/local/bin/bar
0
2
1
- 13. 13
Copyright©2018 NTT Corp. All Rights Reserved.
• Docker v18.06以降には,BuildKitが組み込まれている
• コマンドラインは従来の `docker build` と同じ
• クライアント側で `export DOCKER_BUILDKIT=1` すると有効になる
• Docker v18.06では,加えて Docker daemonをexperimentalモードで起動する必要
がある (Docker v18.09以降では不要)
• ただし,`docker build`コマンドでは,BuildKitの全ての機能が使えるわ
けではない
• 例えば,後述するssh-agent連携機能は未だ使えない
• `buildkitd`(BuildKit単体のデーモン) と `buildctl` (クライアント)を使えば,全
ての機能が使える
• コマンドラインは`docker build`より複雑
BuildKitの使い方
v18.09は10月中にはリリースされるはず..
- 14. 14
Copyright©2018 NTT Corp. All Rights Reserved.
• DAGはマルチステージDockerfileを用いて記述できる
BuildKit: 次世代 `docker build`
FROM golang AS stage0
...
RUN go build –o /foo ...
FROM clang AS stage1
...
RUN clang –o /bar ...
FROM debian AS stage2
COPY --from=stage0 /foo /usr/local/bin/foo
COPY --from=stage1 /bar /usr/local/bin/bar
0
2
1
https://t.co/aUKqQCVmXa より引用
- 18. 18
Copyright©2018 NTT Corp. All Rights Reserved.
• Dockerfileの最初の行に `# syntax = ${FRONTEND_IMAGE}` を指定する
と,非標準の命令を利用できる
• `${FRONTEND_IMAGE}` には,DockerfileをLLBに変換するプログラムを含んだコンテ
ナイメージを指定する (つまり,新しい命令や構文を自作できる!)
• 例: `RUN –-mount=type=cache`
• コンパイラやパッケージマネージャのキャッシュディレクトリを保持できる
• 将来的には,`# syntax = ...` を指定しなくても標準で利用できるようになるものと
思われる
新しいDockerfile構文: `RUN –-mount=type=cache`
# syntax = tonistiigi/dockerfile:runmount20181002
...
RUN --mount=type=cache,target=/root/.cache go build ...
https://github.com/moby/buildkit/pull/442 https://github.com/moby/buildkit/pull/455
- 20. 20
Copyright©2018 NTT Corp. All Rights Reserved.
• S3やSSHの鍵を,`RUN`コンテナ内に安全にマウントできる
• マウントされるだけなので,出力イメージ内には残らない
• SSHの鍵にパスフレーズを設定している場合は,後述する `RUN –-mount=type=ssh`
を用いる
• Docker v18.09から利用可能
新しいDockerfile構文: `RUN –-mount=type=secret`
# syntax = tonistiigi/dockerfile:secrets20181002
...
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials
aws s3 cp s3://... ...
$ docker build –-secret id=aws,src=~/.aws/credentials ...
https://github.com/moby/buildkit/pull/567
- 21. 21
Copyright©2018 NTT Corp. All Rights Reserved.
• クライアントのssh-agentソケット(SSH_AUTH_SOCK)に,`RUN`コンテナか
らアクセスできる
• Docker v19.03から利用可能となる見込み (buildctlでなら今すぐ使える)
• あるいはv18.09に入るかも
新しいDockerfile構文: `RUN –-mount=type=ssh`
# syntax = tonistiigi/dockerfile:ssh20181005
...
RUN --mount=type=ssh git clone ssh://gitlab.com/...
$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_rsa
(パスフレーズ入力)
$ buildctl build –-ssh default=$SSH_AUTH_SOCK ...
https://github.com/moby/buildkit/pull/608 https://github.com/moby/buildkit/pull/655
- 22. 22
Copyright©2018 NTT Corp. All Rights Reserved.
• Heroku・Cloud FoundryのBuildpacksも,`docker build`から直接ビ
ルドできる
• やはりLLBに変換されて実行される
Dockerfile以外の言語
# syntax = tonistiigi/pack
---
applications:
- name: myapp
memory: 128MB
disk_quota: 256MB
random-route: true
buildpack: python_buildpack
command: python hello.py
$ docker build –f manifest.yml ...
https://github.com/tonistiigi/buildkit-pack
- 23. 23
Copyright©2018 NTT Corp. All Rights Reserved.
• 複数のアーキテクチャに対応したイメージをビルドできる
• アーキテクチャ毎にtarレイヤを作り,1つのマニフェストにまとめる
• QEMUのusermode emulationをbinfmtで登録しておくことで,他アーキ
テクチャのバイナリの`RUN`も可能
• full system emulation (いわゆるVM) ではない
• Docker v19.XXで利用可能となる見込み (buildctlでなら今すぐ使える)
マルチアーキテクチャ対応
$ buildctl build –-platform=linux/amd64,linux/arm64,linux/arm/v6 ...
https://asciinema.org/a/GYOx4B88r272HWrLTyFwo156s https://github.com/moby/buildkit/pull/499 https://github.com/moby/moby/issues/32487
...
ENV GOOS=$TARGETOS GOARCH=$TARGETARCH
...
- 24. 24
Copyright©2018 NTT Corp. All Rights Reserved.
• User namespaceを用いることで,buildkitdを一般ユーザ権限で実行可能
• Docker daemon全体のroot権限不要化は,作業中: https://github.com/rootless-
containers/usernetes
• Docker v19.03までにはマージされる?
• ただしoverlayfsを使えなくなる
• overlayfsが使えなくなっても,XFSならreflinkを用いたCopy-on-Writeが可能
• Ubuntuのカーネルでは例外的にoverlayfsも利用可能
• 将来的にはFUSEを用いて対応予定 (要kernel 4.18以降)
• Docker・Kubernetesのコンテナ内での一般ユーザとしての実行も可能
• Docker v18.06・Kubernetes v1.12以降では,`securityContext.procMount`の設
定が必要 (それより前のバージョンでは,`securityContext.privileged`が必要)
root権限不要
- 25. 25
Copyright©2018 NTT Corp. All Rights Reserved.
• img: https://github.com/genuinetools/img
• デーモン不要版のBuildKit
• コマンドラインは `docker` とほぼ同じ
• MicrosoftのJessie Frazelleが開発
デーモン無しでの実行も可能 (img)
$ img build –t example.com/foo .
$ img push example.com/foo
$ img save example.com/foo | docker load
- 26. 26
Copyright©2018 NTT Corp. All Rights Reserved.
• Kubernetes・Knative上での分散ビルドの改善
• キャッシュやノード負荷情報を利用したスケジューリング
• 単一のDockerfile内の各ステージを,別々のノードで実行
• キャッシュの自動ガーベジコレクション
• OCI v1に代わるイメージフォーマット・配布プロトコルへの対応
• レイヤtarballの重複除去
• lazy-pulling対応
• P2Pへのネイティブ対応
• ...?
BuildKitの将来
- 27. 27
Copyright©2018 NTT Corp. All Rights Reserved.
• Dockerfileの各ステージを並列実行できる
• コンパイラやパッケージマネージャのキャッシュを使える
• AWSやSSHなどの鍵を安全に扱える
• Dockerfile以外の言語も使える (Buildpacksなど)
• root権限無しで実行できる
• 最新のDockerなら,`export DOCKER_BUILDKIT=1`するだけですぐに使える
まとめ
従来より30倍以上
速くなることも
Notas do Editor
- 20:30 - 21:10https://build.connpass.com/event/98947/