Dockerコンテナ内でdockerコマンドを使う(dockerクライアントバイナリだけインストール方法)

首先

我想在Docker容器内使用docker命令。
这篇文章并不是关于想要在所谓的Docker in Docker中嵌套,而是想要创建共享相同docker守护程序的兄弟容器的情况。

具体是什么样的使用情景呢?

    • 社内Heroku的なアプリケーションをDockerコンテナで動かして、Web画面をポチポチするとdocker service createしたいとか

 

    • HubotをDockerコンテナで動かして、特定の発言に反応してdocker runしたいとか

 

    JenkinsをDockerコンテナで動かして、CIの実行でdocker runしたいとか

Dockerを使ってるとなんでもDockerにしたい病になるので、Dockerコンテナを起動するような必要があるアプリケーションもDockerで管理したい。

作戦としては必要なイメージにdockerクライアントのバイナリだけをインストールしておいて、
docker runするときにホスト側の/var/run/docker.sockをマウントする。

dockerクライアントだけをインストール

dockerコマンドだけ欲しいんだけど、普通にDockerをインストールするとデーモンも付いてくるし、インストール処理でいろいろ設定変更されるので、そういうのはして欲しくないんだ。

というわけで何か良い方法ないかなと思ってdockerのissueを眺めてたら同じような話があった
Release client-only binaries for Linux

要するにビルド済のバイナリはクライアントとデーモンで分かれたので、リリースページにダウンロードURL書いてあるからアーカイブを展開して必要なバイナリファイルだけコピーしてねということらしい。
https://github.com/docker/docker/releases

好的。我们来试试看。准备一小段简单的验证代码。下面是Dockerfile的内容。

FROM debian:jessie

RUN apt-get update && apt-get install -y \
  curl \
  && rm -rf /var/lib/apt/lists/*

ENV DOCKER_CLIENT_VERSION=1.12.3
ENV DOCKER_API_VERSION=1.24
RUN curl -fsSL https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_CLIENT_VERSION}.tgz \
  | tar -xzC /usr/local/bin --strip=1 docker/docker

最初没有安装curl,所以我安装了curl。
简单来说,我用curl下载所需的二进制文件,并通过管道将其传递给tar进行解压。
在此过程中,通过–strip=1参数禁止创建解压目录,并通过-C参数指定 docker/docker 中的文件,并将其解压到 /usr/local/bin路径下,以便直接将中间文件放置成一个文件,而不留下任何中间文件。

顺便说一下,设置DOCKER_API_VERSION环境变量是为了在docker守护程序版本过旧无法通信时,通过覆盖环境变量来降级API。docker版本和API版本的对应关系请参考以下内容。

确认工作状态

好的。让我们来验证一下是否可以正常运行。在启动时,通过 -v 选项挂载主机端的 docker.sock。由于容器允许主机访问,因此请注意安全上的风险。

$ docker build -t docker-client ./
$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker-client /bin/bash
root@68a109a5d6e2:/# docker version
Client:
 Version:      1.12.3
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   6b644ec
 Built:        Wed Oct 26 23:26:11 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 17:52:38 2016
 OS/Arch:      linux/amd64

root@68a109a5d6e2:/# docker run nginx nginx -V
nginx version: nginx/1.11.5
built by gcc 4.9.2 (Debian 4.9.2-10)
built with OpenSSL 1.0.1t  3 May 2016
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed'

嗯。看起来不错。

准备一个只包含Docker命令二进制文件的Dockerfile…啊,?

我在这里写了一个只包含Docker命令的二进制文件的Dockerfile,觉得这样做很方便。当我想要创建一个仓库的时候突然想到,先去Docker Hub上查查有没有人已经做过了。结果发现官方的Dockerfile也在做类似的事情。虽然它不是一行代码,并且还复制了除了客户端之外的其他二进制文件。

是吗,原来是官方的啊。事后想想应该是应该的,但是我没有考虑到那个角度。
因为官方的版本会进行校验和确认,所以是正规的。
那些像校验和一样的人可以参考官方的Dockefile,会更好吧。

そして、よくよく考えたら、何かのベースのイメージがあってそのなかでdockerコマンドが使いたいんであって、
dockerコマンドだけ使えるDockerfileあっても、ホストのdockerコマンド使えよってだけで、あんまりうれしくないよね。
Fromで継承するのはたぶんそのアプリケーションの言語のランタイムになるだろう。
というわけでdockerコマンドが必要なイメージにさっきのcurlのワンライナーをコピペする運用で十分な気がする。

总结

在Docker容器中,我已经了解了如何使用docker命令。这将使得容器化变得更加顺利。

广告
将在 10 秒后关闭
bannerAds