dshimizu/blog

アルファ版

Docker コンテナ内で Docker デーモンを起動しようとするとどうなるかを見て、Docker outside of Docker を動かしてみた

はじめに

CI を動かす時、CI 側を Docker コンテナで動かしている場合、自分のアプリケーションも Docker コンテナで動かしてビルドする、といった場合に一工夫必要になる。

この場合の対応方法として、Docker コンテナの中で Docker を利用できるようにする、といったことができる。 以下の2つの方法がある。

  • Docker コンテナの中で Docker デーモンを動かす (Docker in Docker)
  • ホストの Docker デーモンのソケットファイルを、各 Docker コンテナで共有する (Docker outside of Docker)

Docker in Docker は色々問題点があり*1、やるにも結構手間がかかるので、 Docker outside of Docker をやってみる。

環境

% docker -v
Docker version 20.10.17, build 100c701

何もせず Docker から Docker を使おうとする場合

ホスト側の操作

% docker container run -it --rm --name dood-test -v /var/run/docker.sock:/var/run/docker.sock ubuntu

コンテナ側の操作

コンテナ側にも docker をインストールする。ちゃんとやる場合は Docker 公式のものをインストールするところだけど、とりあえず動作確認のため Ubuntu のパッケージのものをインストールする。

root@20b7df14b340:/ # apt update && apt install -y docker.io

Docker デーモンにアクセスできない、と言われる。

root@221eb7bbf979:/# docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

Docker コンテナ内で Docker デーモンを起動しようとすると、ストレージドライバやネットワーク周りの操作に失敗し、デーモンの起動に失敗する。この辺りの仕組みについてはまだよくわかっていないが、コンテナからカーネルに関係する部分の操作ができないためと思う。

root@221eb7bbf979:/# dockerd
INFO[2022-07-10T13:19:08.959606477+09:00] Starting up
INFO[2022-07-10T13:19:08.960336841+09:00] libcontainerd: started new containerd process  pid=4080
INFO[2022-07-10T13:19:08.960358071+09:00] parsed scheme: "unix"                         module=grpc
INFO[2022-07-10T13:19:08.960364727+09:00] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2022-07-10T13:19:08.960379332+09:00] ccResolverWrapper: sending update to cc: {[{unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2022-07-10T13:19:08.960385097+09:00] ClientConn switching balancer to "pick_first"  module=grpc
WARN[0000] deprecated version : `1`, please switch to version `2`
INFO[2022-07-10T13:19:08.973892503+09:00] starting containerd                           revision= version="1.5.9-0ubuntu1~20.04.4"
INFO[2022-07-10T13:19:08.989213285+09:00] loading plugin "io.containerd.content.v1.content"...  type=io.containerd.content.v1
INFO[2022-07-10T13:19:08.989271418+09:00] loading plugin "io.containerd.snapshotter.v1.aufs"...  type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989360114+09:00] loading plugin "io.containerd.snapshotter.v1.btrfs"...  type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989539433+09:00] skip loading plugin "io.containerd.snapshotter.v1.btrfs"...  error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.btrfs (overlay) must be a btrfs filesystem to be used with the btrfs snapshotter: skip plugin" type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989553182+09:00] loading plugin "io.containerd.snapshotter.v1.devmapper"...  type=io.containerd.snapshotter.v1
WARN[2022-07-10T13:19:08.989563685+09:00] failed to load plugin io.containerd.snapshotter.v1.devmapper  error="devmapper not configured"
INFO[2022-07-10T13:19:08.989570146+09:00] loading plugin "io.containerd.snapshotter.v1.native"...  type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989616642+09:00] loading plugin "io.containerd.snapshotter.v1.overlayfs"...  type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989727550+09:00] loading plugin "io.containerd.snapshotter.v1.zfs"...  type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989808917+09:00] skip loading plugin "io.containerd.snapshotter.v1.zfs"...  error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter: skip plugin" type=io.containerd.snapshotter.v1
INFO[2022-07-10T13:19:08.989819978+09:00] loading plugin "io.containerd.metadata.v1.bolt"...  type=io.containerd.metadata.v1
WARN[2022-07-10T13:19:08.989846668+09:00] could not use snapshotter devmapper in metadata plugin  error="devmapper not configured"
INFO[2022-07-10T13:19:08.989854445+09:00] metadata content store policy set             policy=shared
INFO[2022-07-10T13:19:09.005693666+09:00] loading plugin "io.containerd.differ.v1.walking"...  type=io.containerd.differ.v1
INFO[2022-07-10T13:19:09.005709185+09:00] loading plugin "io.containerd.gc.v1.scheduler"...  type=io.containerd.gc.v1
INFO[2022-07-10T13:19:09.005750892+09:00] loading plugin "io.containerd.service.v1.introspection-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005776234+09:00] loading plugin "io.containerd.service.v1.containers-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005785569+09:00] loading plugin "io.containerd.service.v1.content-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005792849+09:00] loading plugin "io.containerd.service.v1.diff-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005801751+09:00] loading plugin "io.containerd.service.v1.images-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005809527+09:00] loading plugin "io.containerd.service.v1.leases-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005817730+09:00] loading plugin "io.containerd.service.v1.namespaces-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005826105+09:00] loading plugin "io.containerd.service.v1.snapshots-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.005834033+09:00] loading plugin "io.containerd.runtime.v1.linux"...  type=io.containerd.runtime.v1
INFO[2022-07-10T13:19:09.005910278+09:00] loading plugin "io.containerd.runtime.v2.task"...  type=io.containerd.runtime.v2
INFO[2022-07-10T13:19:09.005983203+09:00] loading plugin "io.containerd.monitor.v1.cgroups"...  type=io.containerd.monitor.v1
INFO[2022-07-10T13:19:09.006182150+09:00] loading plugin "io.containerd.service.v1.tasks-service"...  type=io.containerd.service.v1
INFO[2022-07-10T13:19:09.006202426+09:00] loading plugin "io.containerd.internal.v1.restart"...  type=io.containerd.internal.v1
INFO[2022-07-10T13:19:09.006230819+09:00] loading plugin "io.containerd.grpc.v1.containers"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006240320+09:00] loading plugin "io.containerd.grpc.v1.content"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006250691+09:00] loading plugin "io.containerd.grpc.v1.diff"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006258760+09:00] loading plugin "io.containerd.grpc.v1.events"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006266514+09:00] loading plugin "io.containerd.grpc.v1.healthcheck"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006274823+09:00] loading plugin "io.containerd.grpc.v1.images"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006282813+09:00] loading plugin "io.containerd.grpc.v1.leases"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006290262+09:00] loading plugin "io.containerd.grpc.v1.namespaces"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006298818+09:00] loading plugin "io.containerd.internal.v1.opt"...  type=io.containerd.internal.v1
INFO[2022-07-10T13:19:09.006397506+09:00] loading plugin "io.containerd.grpc.v1.snapshots"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006410048+09:00] loading plugin "io.containerd.grpc.v1.tasks"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006417912+09:00] loading plugin "io.containerd.grpc.v1.version"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006426572+09:00] loading plugin "io.containerd.grpc.v1.introspection"...  type=io.containerd.grpc.v1
INFO[2022-07-10T13:19:09.006547669+09:00] serving...                                    address=/var/run/docker/containerd/containerd-debug.sock
INFO[2022-07-10T13:19:09.006587473+09:00] serving...                                    address=/var/run/docker/containerd/containerd.sock.ttrpc
INFO[2022-07-10T13:19:09.006623044+09:00] serving...                                    address=/var/run/docker/containerd/containerd.sock
INFO[2022-07-10T13:19:09.006640633+09:00] containerd successfully booted in 0.033593s
INFO[2022-07-10T13:19:09.012581779+09:00] parsed scheme: "unix"                         module=grpc
INFO[2022-07-10T13:19:09.012596336+09:00] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2022-07-10T13:19:09.012609483+09:00] ccResolverWrapper: sending update to cc: {[{unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2022-07-10T13:19:09.012616202+09:00] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2022-07-10T13:19:09.012981373+09:00] parsed scheme: "unix"                         module=grpc
INFO[2022-07-10T13:19:09.012990671+09:00] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2022-07-10T13:19:09.012998299+09:00] ccResolverWrapper: sending update to cc: {[{unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2022-07-10T13:19:09.013003905+09:00] ClientConn switching balancer to "pick_first"  module=grpc
ERRO[2022-07-10T13:19:09.013650576+09:00] failed to mount overlay: operation not permitted  storage-driver=overlay2
ERRO[2022-07-10T13:19:09.013689926+09:00] exec: "fuse-overlayfs": executable file not found in $PATH  storage-driver=fuse-overlayfs
WARN[2022-07-10T13:19:09.013871253+09:00] [graphdriver] WARNING: the aufs storage-driver is deprecated, and will be removed in a future release
WARN[2022-07-10T13:19:09.039645655+09:00] Your kernel does not support swap memory limit
WARN[2022-07-10T13:19:09.039658477+09:00] Your kernel does not support CPU realtime scheduler
WARN[2022-07-10T13:19:09.039663435+09:00] Your kernel does not support cgroup blkio weight
WARN[2022-07-10T13:19:09.039667506+09:00] Your kernel does not support cgroup blkio weight_device
INFO[2022-07-10T13:19:09.039793600+09:00] Loading containers: start.
WARN[2022-07-10T13:19:09.040965617+09:00] Running iptables --wait -t nat -L -n failed with message: `iptables v1.8.4 (legacy): can't initialize iptables table `nat': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.`, error: exit status 3
INFO[2022-07-10TT13:19:09.058222674+09:00] stopping event stream following graceful shutdown  error="<nil>" module=libcontainerd namespace=moby
INFO[2022-07-10TT13:19:09.058478516+09:00] stopping healthcheck following graceful shutdown  module=libcontainerd
INFO[2022-07-10TT13:19:09.058517532+09:00] stopping event stream following graceful shutdown  error="context canceled" module=libcontainerd namespace=plugins.moby
WARN[2022-07-10TT13:19:10.059763358+09:00] grpc: addrConn.createTransport failed to connect to {unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}. Err :connection error: desc = "transport: Error while dialing dial unix:///var/run/docker/containerd/containerd.sock: timeout". Reconnecting...  module=grpc
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables -t nat -N DOCKER: iptables v1.8.4 (legacy): can't initialize iptables table `nat': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
 (exit status 3)

Docker outside of Docker を試す

ホスト側の操作

普通に利用したいコンテナを起動する際に、ホスト側のDockerデーモンのソケットファイルを、コンテナ側にもマウントすれば良い。

% docker container run -it --rm --name dood-test -v /var/run/docker.sock:/var/run/docker.sock ubuntu

コンテナ側の操作

コンテナ側にも docker をインストールする。ちゃんとやる場合は Docker 公式のものをインストールするところだけど、とりあえず動作確認のため Ubuntu のパッケージのものをインストールする。

root@20b7df14b340:/ # apt update && apt install -y docker.io

コンテナからも docker コマンドが使えるようになった。 結果はホスト側から実行した場合と同じになる。

この場合はコンテナ内に Docker デーモンが起動している訳ではなく、ホスト側の Docker デーモンに対して /var/run/docker.sock を介して実行された Docker APIで取得された情報が返されているものと思う。Docker APIはデフォルトだと認証がないため、この場合だとホスト内からだと自由に実行できてしまうといった点ではセキュリティ上の懸念はある。

root@20b7df14b340:/ # docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
20b7df14b340   ubuntu    "bash"    4 minutes ago   Up 4 minutes             dood-test

Ubuntu コンテナ内で、docker イメージをビルドして起動してみると、うまく起動もできた。

root@20b7df14b340:/#  docker container run -it --rm --name dood-docker  docker
/ #

ホスト側の操作

ホスト側から見た場合は以下のような感じになる。

~ % docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
715a67e73c21   docker    "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes             dood-docker
20b7df14b340   ubuntu    "bash"                   9 minutes ago   Up 9 minutes             dood-test

まとめ

Docker outside of Docker の使い方を簡単に記載した。