はじめに
MacでDocker使うの重いですよね?
手元のローカル開発環境のノートPCはMacで、Dockerコンテナという構成は、小さなアプリケーションであれば快適です。
が、そこそこ大きなモノリシックなアプリケーションとかを動かそうとすると、クッソ重くてストレスフルです。
Dockerは新しめのLinux Kernelで動かすと効率的なんだけど、Macで動かそうとするとIOとか遅いし、なんなのかもっさりします。
かと言って、LinuxをノートPCに使うのは茨の道です。(個人の見解です)
そんな今日このごろ、Docker CE 18.09からssh経由でリモートのdockerデーモンに接続できるようになるようです。
mobyメンテナの須田さん、マジ神
つまり、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版は以下からダウンロードできます。
検証時点の最新版の「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のコメントを読んでたら、
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だけ立てて報告しておいた。
というわけで、docker-compose(厳密に言うとdocker-py)がまだサポートしてなくて、docker-composeなローカル開発環境の負荷をリモートにオフロードするには、まだちょっとパーツが足りなそうなかんじです。しょんぼり(´・ω・`)