はじめに
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 の使い方を簡単に記載した。