Docker 19.03新機能 (root権限不要化、GPU対応強化、CLIプラグイン…)

Akihiro Suda
nttlabs
Published in
15 min readJul 23, 2019

NTTの須田です。2019年7月23日に公開された、Docker 19.03の新機能をお伝えします。2018年11月8日にリリースされたDocker 18.09以来、8ヶ月ぶりのリリースです。

root権限不要化

従来のDockerは、ホストのroot権限でデーモン(dockerd)を動作させる必要があったため、脆弱性や設定ミスを突かれると、ホストのroot権限を奪われる恐れがありました。

Docker 19.03では、非rootユーザでデーモンを実行できるようになりました(Rootlessモード)。 Rootlessモードを有効化することで、万一Dockerに脆弱性や設定ミスがあっても、攻撃者にホストのroot権限を奪取されることを防ぐことが出来ます。ただし、現時点ではcgroupを利用できないなどの制約があります。

RootlessモードのDockerは, curl -fsSL https://get.docker.com/rootless | sh コマンド1行で、ユーザのホームディレクトリ内に sudo無しで簡単にインストール出来ます。Webブラウザ内で試用することも可能です。

$ curl -fsSL https://get.docker.com/rootless | sh$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock$ docker run ...

Rootlessモードの詳細は、5月に執筆した記事 RootlessモードでDockerをより安全にする[DockerCon発表レポート] をご覧ください。

GPU対応強化

従来のDockerでNVIDIAのGPUを用いるには、 docker コマンドの代わりに nvidia-docker コマンドを用いたり、OCIランタイムとして --runtime=nvidia (nvidia-docker2) を指定したりする必要がありました。

Docker 19.03では、Docker自体にGPU連携機能 docker run --gpus …が組み込まれました。

$ docker run --gpus all
$ docker run --gpus 2,driver=nvidia,capabilities=compute

現時点では nvidia ドライバのみが実装されていますが、将来的にはNVIDIA以外のベンダのGPU向けのドライバも実装されることが期待されます。

なお、 nvidia ドライバを利用するには、 nvidia-container-cli がホスト上にインストールされている必要があります。

docker buildの強化

Docker 18.06にて試験的に、Docker 18.09にて正式に採用されたBuildKitモード ( DOCKER_BUILDKIT=1 docker build ) が、一層強化されています。

docker build --cache-from

docker buildは、レジストリ上のイメージをキャッシュとして用いる( --cache-from )ことが出来ます。しかしながら、Docker 18.06・18.09では、BuildKitモードが有効である場合、 --cache-from にイメージを指定することが出来ませんでした。

Docker 19.03では、BuildKitモードが有効な場合でも、--cache-from にイメージを指定出来ます。ただし、 --cache-from に指定するイメージは、 --build-arg BUILDKIT_INLINE_CACHE=true を付けてビルドされている必要があります。

docker build --output

ビルドしたイメージの内容を、 --output で指定したディレクトリ内に書き出せるようになりました。

$ cat Dockerfile
FROM alpine
RUN apk add --no-cache figlet
RUN figlet hello > /hello
FROM scratch
COPY --from=0 /hello /hello
$ docker build --output ./out .$ ls -l out/
total 4
-rw-r--r-- 1 suda suda 138 Jul 1 20:41 hello
$ cat out/hello
_ _ _
| |__ ___| | | ___
| '_ \ / _ \ | |/ _ \
| | | | __/ | | (_) |
|_| |_|\___|_|_|\___/

docker context

docker コマンドの接続先ホストを、”context”として管理できるようになりました。kubectl のcontextと似ています。

$ docker context create foo --docker "host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file"
foo
Successfully created context "foo"
$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ...
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
foo tcp://myserver:2376
$ docker --context=foo run ...

CLIプラグイン

docker コマンドをプラグインで拡張できるようになりました。 /usr/lib/docker/cli-plugins または ~/.docker/cli-plugins に、プラグインバイナリ docker-foo を配置すると、 docker foo として実行できるようになります。

既に数多くのプラグインが実装・公開されています。

docker buildx

docker buildx プラグインをインストールすると、BuildKitを用いて docker build コマンドの機能を強化した docker buildx コマンドが利用できるようになります。

docker buildx は、BuildKitモードの docker build ( export DOCKER_BUILDKIT=1 )とよく似ていますが、より先進的な機能を備えています。

例えば、 docker buildx を用いると、 amd64arm64 など複数のアーキテクチャに対応したイメージを簡単にビルドすることが出来ます。複数アーキテクチャに対応したイメージをビルドするには、次の2つの方法があります。

  1. 先述の docker context コマンドを用いて、アーキテクチャ毎にリモートのDockerホストを登録する
  2. QEMU user-mode emulationを用いて、1台のDockerホストで複数アーキテクチャをエミュレートする

性能面では1.の方法が優れていますが、本記事では簡単な2.の方法を紹介します。

まず、 amd64 アーキテクチャのホストにて linuxkit/binfmt イメージをprivilegedモードで起動し、ホストの /proc/sys/fs/binfmt_misc に、QEMU user-mode emulationのバイナリを登録します。

$ docker run --rm --privileged linuxkit/binfmt:v0.7
$ ls -l /proc/sys/fs/binfmt_misc/
total 0
-rw-r--r-- 1 root root 0 Jul 2 17:04 qemu-aarch64
-rw-r--r-- 1 root root 0 Jul 2 17:04 qemu-arm
-rw-r--r-- 1 root root 0 Jul 2 17:04 qemu-ppc64le
-rw-r--r-- 1 root root 0 Jul 2 17:04 qemu-s390x
--w------- 1 root root 0 Jul 2 17:04 register
-rw-r--r-- 1 root root 0 Jul 2 17:04 status

これで、Linuxカーネルは、 amd64 以外のアーキテクチャのバイナリを、QEMU user-mode emulationを用いてCPUをエミュレートしながら実行できるようになります。なお、一般的に「QEMU」として認知されているQEMU full-system emulationと異なり、VMは作成されません。

続いて、 docker buildx create 及び docker buildx inspect --bootstrapを用いて、BuildKitバックエンドを起動します。

$ docker buildx create --use
epic_blackburn
$ docker buildx inspect --bootstrap
...
Name: epic_blackburn0
...
Platforms: linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6

これで、docker buildx buildを用いて、複数アーキテクチャに対応したイメージをビルド・プッシュできるようになります。

$ docker buildx build -t example.com/foo --push --platform linux/amd64,linux/arm64 ...

docker buildx プラグインは、Docker社により https://github.com/docker/buildx にて提供されています。Docker for Mac/Winには標準で付属します。

docker app

docker app プラグインを使うと、 docker-compose.yml 及びイメージを、1つのCloud Native Application Bundle (CNAB)にまとめて、レジストリにプッシュしたり、プルしたりできるようになります。

例として、 example-voting-app.dockerapp をプッシュしてみます。

$ cat ./example-voting-app.dockerapp/docker-compose.yml
version: "3.6"
services:
redis:
image: redis:alpine
ports:
- "6379:6379"
db:
image: postgres:9.4
ports:
- "5432:5432"
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "${vote.port}:80"
deploy:
replicas: ${vote.replicas}
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "${result.port}:80"
worker:
image: dockersamples/examplevotingapp_worker
$ docker app push ./example-voting-app.dockerapp --platform linux/amd64 -t example.com/foo.dockerapp

プッシュしたアプリケーションバンドルは、 docker app render を用いて、 docker-compose.yml に復元することができます。 ただし、元の docker-compose.yml で指定されていたDocker Hub上のイメージではなく、バンドルにコピーされたイメージが用いられます。

$ docker app render example.com/foo.dockerapp
version: "3.6"
services:
db:
image: example.com/foo.dockerapp@sha256:4d915cbb7d4f93a8b1d73fc62496d0e1757599b0e1c567fd349fa9e47720f868
ports:
- mode: ingress
target: 5432
published: 5432
protocol: tcp
redis:
image: example.com/foo.dockerapp@sha256:98547c3529f6b02e3c789c8f4a96d6bb8469b9119150c955370753b93f9a67f2
ports:
- mode: ingress
target: 6379
published: 6379
protocol: tcp
result:
image: example.com/foo.dockerapp@sha256:83b568996e930c292a6ae5187fda84dd6568a19d97cdb933720be15c757b7463
ports:
- mode: ingress
target: 80
published: 60081
protocol: tcp
vote:
deploy:
replicas: 2
image: example.com/foo.dockerapp@sha256:8e64b18b2c87de902f2b72321c89b4af4e2b942d76d0b772532ff27ec4c6ebf6
ports:
- mode: ingress
target: 80
published: 60080
protocol: tcp
worker:
image: example.com/foo.dockerapp@sha256:55753a7b7872d3e2eb47f146c53899c41dcbe259d54e24b3da730b9acbff50a1

アプリケーションバンドルは、 docker app installを用いて、SwarmやKubernetesにデプロイすることも可能です。ただし、Kubernetesへデプロイするには、Compose on Kubernetesがインストールされている必要があります。

$ docker app install --orchestrator kubernetes example.com/foo.dockerapp

docker appプラグインは、Docker社により https://github.com/docker/app にて提供されています。Docker for Mac/Winには標準で付属します。

docker wasm

docker wasm プラグインを使うと、WASMアプリケーションをDockerコンテナのように扱うことができます。

例えば、 tonistiigi/hello イメージは、 docker run コマンドで起動すると通常のコンテナとして実行され、docker wasm run コマンドで起動するとWASMランタイム(wasmtimeまたはwasmer)上で実行されます。(前述の docker buildx プラグインを用いて、マルチプラットフォームイメージとしてビルドされています。)

$ docker run tonistiigi/hello
Hello world, I am linux/amd64!
$ docker wasm run tonistiigi/hello
Hello world, I am wasi/wasm!

また、docker wasm run tonistiigi/viu:docker を実行すると、面白いデモ画像が表示されます。

docker wasm run tonistiigi/viu:docker

docker wasm プラグインは、Tõnis Tiigi氏により https://github.com/tonistiigi/wasm-cli-plugin にて配布されています。

docker expose

docker expose プラグインを使うと、ngrokを用いて簡単にコンテナをインターネットに公開できます。

$ docker run --name nginx -d nginx 
$ docker expose nginx 80
...
https://deadbeef.ngrok.io
...

docker expose プラグインは、 Łukasz Lach氏により https://github.com/lukaszlach/clip にて配布されています。

docker microscan

docker microscan プラグインを使うと、Aqua MicroScannerを用いてイメージ中の脆弱性をスキャンできます。

$ docker microscan debian
No critical vulnerabilities found in debian

docker microscanプラグインは、 docker expose プラグインと同じくŁukasz Lach氏により、 https://github.com/lukaszlach/clip にて配布されています。

Enterprise Editionのプラグイン

Docker 19.03をベースとしたエンタープライズ製品であるDocker Enterprise 3.0には、 docker assembledocker templatedocker clusterdocker gmsadocker registry など多くのプラグインが付属するようです。

https://www.slideshare.net/ajeetraina/dockercon-2019-updates-announcements/26

おわりに

私たちNTTはオープンソースコミュニティで共に活動する仲間を募集しています。ぜひ弊社 ソフトウェアイノベーションセンタ紹介ページや、採用情報ページをご覧ください。

--

--