Edited at

Docker CE 18.09からssh経由でリモートのdockerデーモンに接続できるようになるってよ


はじめに

MacでDocker使うの重いですよね?

手元のローカル開発環境のノートPCはMacで、Dockerコンテナという構成は、小さなアプリケーションであれば快適です。

が、そこそこ大きなモノリシックなアプリケーションとかを動かそうとすると、クッソ重くてストレスフルです。

Dockerは新しめのLinux Kernelで動かすと効率的なんだけど、Macで動かそうとするとIOとか遅いし、なんなのかもっさりします。

かと言って、LinuxをノートPCに使うのは茨の道です。(個人の見解です)

そんな今日このごろ、Docker CE 18.09からssh経由でリモートのdockerデーモンに接続できるようになるようです。

https://github.com/docker/cli/pull/1014

mobyメンテナの須田さん、マジ神 :pray:

つまり、dockerコマンドだけ手元のMacで動かして、dockerデーモンはAWSのEC2上にLinux立てたところで動かすみたいなことができるのでわ???

って思って、これを書いてる 2018/10/26時点で、Docker CE 18.09はまだベータリリースですが、待ちきれないので、試してみた。

結論から言うと、docker単体なら動くんだけど、docker-compose(厳密に言うとdocker-py)がまだサポートしてなくて、docker-composeなローカル開発環境の負荷をリモートにオフロードするには、まだちょっとパーツが足りなそうなかんじです。しょんぼり(´・ω・`)


検証


環境


dockerクライアント


  • Mac OSX 10.14 (Mojave)

  • Docker for Mac Edge (2.0.0.0-beta1-mac75 2018-09-14)

  • Docker CE 18.09.0-ce-beta1

  • docker-compose 1.22.0


dockerデーモン


  • AWS EC2

  • Ubuntu 18.04 LTS

  • Docker CE 18.09.0-beta5


インストール


dockerクライアント

Docker for MacのEdge版を入れます。

Edge版は以下からダウンロードできます。

https://docs.docker.com/docker-for-mac/edge-release-notes/

検証時点の最新版の「Docker Community Edition 2.0.0.0-beta1-mac75 2018-09-14」をダウンロードしてインストールしました。

$ docker version

Client: Docker Engine - Community
Version: 18.09.0-ce-beta1
API version: 1.39
Go version: go1.10.4
Git commit: 78a6bdb
Built: Thu Sep 6 22:41:53 2018
OS/Arch: darwin/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 18.09.0-ce-beta1
API version: 1.39 (minimum version 1.12)
Go version: go1.10.3
Git commit: 78a6bdb
Built: Thu Sep 6 22:49:35 2018
OS/Arch: linux/amd64
Experimental: true

$ docker-compose version

docker-compose version 1.22.0, build f46880f
docker-py version: 3.4.1
CPython version: 3.6.4
OpenSSL version: OpenSSL 1.0.2o 27 Mar 2018


dockerデーモン

検証用にAWS EC2に適当にUbuntu 18.04のインスタンスを立てました。

$ cat /etc/lsb-release

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS"

$ uname -a
Linux ip-10-194-2-73 4.15.0-1021-aws #21-Ubuntu SMP Tue Aug 28 10:23:07 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

ベータリリースは test.docker.com から配信されているので、こいつを入れます。

$ curl -fsSL https://test.docker.com -o test-docker.sh

$ sudo sh test-docker.sh
# Executing docker install script, commit: 36b78b2
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic test" > /etc/apt/sources.list.d/docker.list
+ [ ubuntu = debian ]
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sh -c docker version
Client:
Version: 18.09.0-beta5
API version: 1.39
Go version: go1.10.4
Git commit: e1910c5
Built: Tue Oct 23 22:25:31 2018
OS/Arch: linux/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 18.09.0-beta5
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: e1910c5
Built: Tue Oct 23 21:50:22 2018
OS/Arch: linux/amd64
Experimental: false
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

sudo usermod -aG docker your-user

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
containers which can be used to obtain root privileges on the
docker host.
Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
for more information.

sshしているubuntuユーザでdockerソケットにアクセスできるように、dockerグループに入れておきます。

$ sudo usermod -aG docker ubuntu

グループに追加したら、一旦ログアウト/ログインしなおして、 sshしているユーザで、 docker ps コマンドが使えるか確認しておきます。


$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES


リモートdockerデーモンとssh経由で接続してみる

以下のPullRequestのコメントを読んでたら、

https://github.com/docker/cli/pull/1014

docker -H ssh://me@server という指定で、リモートのdockerデーモンに接続できるらしいんですが、SSH鍵の指定方法が分からず、

~/.ssh/config でのオプション指定は有効なようなので、 手元の ~/.ssh/config に以下を設定してみました。

Host docker-18-09-test

IdentityFile ~/.ssh/aws-dev.pem
User ubuntu
Hostname XXX.XXX.XXX.XXX

sshできるか念のため確認しておきます。

$ ssh docker-18-09-test

Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1021-aws x86_64)

$ exit

でわ、手元のdockerクライアントから、リモートのdockerデーモンに接続してみましょう。

$ docker -H ssh://docker-18-09-test version

Client: Docker Engine - Community
Version: 18.09.0-ce-beta1
API version: 1.39
Go version: go1.10.4
Git commit: 78a6bdb
Built: Thu Sep 6 22:41:53 2018
OS/Arch: darwin/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 18.09.0-beta5
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: e1910c5
Built: Tue Oct 23 21:50:22 2018
OS/Arch: linux/amd64
Experimental: false

お、リモートは 18.09.0-beta5 になってて、Ubuntu側につながってそうですね。

手元からリモートにdocker runしてみます。

$ docker -H ssh://docker-18-09-test run -d --name hoge nginx:alpine

Unable to find image 'nginx:alpine' locally
alpine: Pulling from library/nginx
4fe2ade4980c: Pull complete
c3f09dfaf47d: Pull complete
83283d0e9bb9: Pull complete
e2e530da9538: Pull complete
Digest: sha256:ae5da813f8ad7fa785d7668f0b018ecc8c3a87331527a61d83b3b5e816a0f03c
Status: Downloaded newer image for nginx:alpine
8eda9ca571dde9f752b12989fcdd7b344fec9f28e1a403bf46da4da457ae4794

リモート側で見てみると、たしかにコンテナが生まれています。よさそう。

$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8eda9ca571dd nginx:alpine "nginx -g 'daemon of…" 16 seconds ago Up 14 seconds 80/tcp hoge

手元からdocker execしてみます。

$ docker -H ssh://docker-18-09-test exec -it hoge /bin/sh

/ # ls
bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var
/ # exit

$

ちゃんとコンテナの標準入出力も取れますね。最高です。


DOCKER_HOSTの設定

毎回 dockerソケット指定するのめんどくさいですが、ローカルのdockerコマンドを使いたい場合もあるので、aliasかなんかを適当に設定しておくか、

$ alias rdocker="docker -H ssh://docker-18-09-test"

$ rdocker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8eda9ca571dd nginx:alpine "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 80/tcp hoge

もしくは、 DOCKER_HOST 環境変数でも設定できるようなので、 direnvかなにかで切り替えるとよんじゃないかな。

$ DOCKER_HOST=ssh://docker-18-09-test docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd79f640e557 nginx:alpine "nginx -g 'daemon of…" 17 minutes ago Up 17 minutes 0.0.0.0:80->80/tcp hoge


ポートフォワード

リモートのdocker上のnginxにHTTPで接続したい場合は、80番ポートをリモートでexposeしておいて、

$ docker -H ssh://docker-18-09-test run -d --name hoge -p 80:80 nginx:alpine

リモートのサーバに普通にHTTP接続するか、もしくはHTTP接続が通信許可されていない場合は、

SSHポートフォワードでトンネルを掘り、リモートの80番をローカルの8080番ポートにマッピングしておき、

$ ssh -L 8080:127.0.0.1:80 docker-18-09-test

ローカルの8080番ポートにアクセスすれば、おーけー。

$ curl -I http://127.0.0.1:8080/

HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Fri, 26 Oct 2018 05:01:19 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 02 Oct 2018 19:21:37 GMT
Connection: keep-alive
ETag: "5bb3c541-264"
Accept-Ranges: bytes


docker-composeと一緒に使う

普通にローカル開発していると、素のdockerコマンドだけじゃなくて docker-composeも使いたくなります。

結論から言うと、やってみたらエラーが出て、まだサポートされていないっぽい。

$ cat docker-compose.yml

version: '3'
services:
web:
image: nginx:alpine
ports:
- "80:80"

$ docker-compose -H ssh://docker-18-09-test up -d

Traceback (most recent call last):
File "docker-compose", line 6, in <module>
File "compose/cli/main.py", line 71, in main
File "compose/cli/main.py", line 124, in perform_command
File "compose/cli/command.py", line 41, in project_from_options
File "compose/cli/command.py", line 121, in get_project
File "compose/cli/command.py", line 92, in get_client
File "compose/cli/docker_client.py", line 127, in docker_client
File "site-packages/docker/api/client.py", line 118, in __init__
File "site-packages/docker/utils/utils.py", line 256, in parse_host
docker.errors.DockerException: Invalid bind address protocol: ssh://docker-18-09-test
[8412] Failed to execute script docker-compose

$ DOCKER_HOST=ssh://docker-18-09-test docker-compose up -d

Traceback (most recent call last):
File "docker-compose", line 6, in <module>
File "compose/cli/main.py", line 71, in main
File "compose/cli/main.py", line 124, in perform_command
File "compose/cli/command.py", line 41, in project_from_options
File "compose/cli/command.py", line 121, in get_project
File "compose/cli/command.py", line 92, in get_client
File "compose/cli/docker_client.py", line 127, in docker_client
File "site-packages/docker/api/client.py", line 118, in __init__
File "site-packages/docker/utils/utils.py", line 256, in parse_host
docker.errors.DockerException: Invalid bind address protocol: ssh://docker-18-09-test
[8460] Failed to execute script docker-compose

docker-compose が ssh:// をサポートしてないことに気づいて、調べたら依存している docker-py の問題っぽいので、とりあえずissueだけ立てて報告しておいた。

https://github.com/docker/docker-py/issues/2159

というわけで、docker-compose(厳密に言うとdocker-py)がまだサポートしてなくて、docker-composeなローカル開発環境の負荷をリモートにオフロードするには、まだちょっとパーツが足りなそうなかんじです。しょんぼり(´・ω・`)