はじめに
検索すると TCP で Docker Engine API (旧 Remote API) を利用する方法が出てきますが、平文のためポートへアクセスできれば誰でも Docker を操作できてしまいます。1
(ブラウザからの攻撃は Same-Origin Policy 等でブロックされると思っていましたが、レスポンスが取得できないだけで、リクエスト自体はサーバに送信されるようです2)
そのため TLS を利用する方法が望ましい3のですが、Linux 向けの dockerd 起動時に証明書を指定する方法しかなく、Mac 向けの情報は見当たりません。
手順
証明書の作成4
サーバのTLS証明書の他に、クライアントの証明書も作成します。
注意: 説明に不要な出力は省略しています。
# サーバ側の秘密鍵を作成
$ openssl genrsa -out server.key 4096
# サーバ側の公開鍵を作成
$ openssl req -new -key server.key -x509 -days 3653 -out server.crt
# Common Name は 127.0.0.1 などに設定してください
Common Name (eg, fully qualified host name) []:127.0.0.1
# サーバ側のpemを作成
$ cat server.key server.crt > server.pem
# クライアント側の秘密鍵を作成
$ openssl genrsa -out client.key 4096
# クライアント側の公開鍵を作成
$ openssl req -new -key client.key -x509
# 何も入力しないとエラーになってしまうので、Country Name を JP に設定するなどしてください
Country Name (2 letter code) []:JP
# クライアント側のpemを作成
cat client.key client.crt > client.pem
# パーミッションの設定
chmod 600 server.key server.pem client.key client.pem
プロキシの起動
Docker デーモンの Unix Socket をコンテナへマウントし、ソケットへ HTTPS 接続をプロキシします。45
docker run \
--rm -v /var/run/docker.sock:/var/run/docker.sock \
-v ${PWD}:/src \
-p 0.0.0.0:2376:2376 \
bobrik/socat \
openssl-listen:2376,reuseaddr,cert=/src/server.pem,cafile=/src/client.crt,fork UNIX-CONNECT:/var/run/docker.sock
-d
オブションなどをつけてもOKです。
確認
$ curl --cacert ./server.crt --key ./client.key --cert ./client.crt https://127.0.0.1:2376/containers/json
# JSON が出力されていれば成功です🎉
-
https://docs.docker.com/engine/security/https/
この記事では Docker for Mac で TLS 通信、クライアント証明書を用いた認証を行う方法を説明します。 ↩ -
http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html ↩ ↩2
-
https://forums.docker.com/t/remote-api-with-docker-for-mac-beta/15639/2
Macにsocat
入ってるよ、という人はそちらで実行しても大丈夫だと思います(未検証)。 ↩