Docker Daemon 连接方式详解

前言


在 Docker 常用详解指令 一文中粗粗提了一下, Docker 是分为客户端和服务端两部分的, 本文将介绍客户端是如何连接服务端的。

连接方式


1. UNIX域套接字

默认就是这种方式, 会生成一个 /var/run/docker.sock 文件, UNIX 域套接字用于本地进程之间的通讯, 这种方式相比于网络套接字效率更高, 但局限性就是只能被本地的客户端访问。

2. TCP 端口监听

服务端开启端口监听:dockerd -H IP:PORT

客户端通过指定的 IP端口 访问服务端:docker -H IP:PORT

通过这种方式, 任何人只要知道了你暴露的 IP端口 就能随意访问你的 Docker 服务了, 这是一件很危险的事, 因为 docker 的权限很高, 不法分子可以从这突破取得服务端 宿主机 的最高权限。

相关:一个回车键黑掉一台服务器
3. 可以同时监听多个 socket
ubuntu@VM-84-201-ubuntu:/usr/anyesu/docker$ sudo dockerd -H unix:///var/run/docker.sock -H tcp://127.0.0.1:2376 -H tcp://127.0.0.1:2377
...
INFO[0004] API listen on 127.0.0.1:2377
INFO[0004] API listen on /var/run/docker.sock
INFO[0004] API listen on 127.0.0.1:2376

启用 TLS 安全连接


上面介绍了普通的 HTTP 方式远程连接很不安全, 解决的办法很简单, 就是启用 TLS 证书实现客户端和服务端的双向认证, 以此来保证安全性。

创建 TLS 证书 ( 根证书、服务端证书、客户端证书 )
cd /usr/anyesu/docker
# 内容比较多, 就写成一个shell脚本, 将需要绑定的服务端ip或域名做参数传入即可
vi tlscert.sh

脚本内容如下:

#!/bin/bash
# @author: anyesu

if [ $# != 1 ] ; then 
echo "USAGE: $0 [HOST_IP]" 
exit 1; 
fi 

#============================================#
#   下面为证书密钥及相关信息配置,注意修改   #
#============================================#
PASSWORD="8#QBD2$!EmED&QxK"
COUNTRY=CN
PROVINCE=yourprovince
CITY=yourcity
ORGANIZATION=yourorganization
GROUP=yourgroup
NAME=yourname
HOST=$1
SUBJ="/C=$COUNTRY/ST=$PROVINCE/L=$CITY/O=$ORGANIZATION/OU=$GROUP/CN=$HOST"

echo "your host is: $1"

# 1.生成根证书RSA私钥,PASSWORD作为私钥文件的密码
openssl genrsa -passout pass:$PASSWORD -aes256 -out ca-key.pem 4096

# 2.用根证书RSA私钥生成自签名的根证书
openssl req -passin pass:$PASSWORD -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -subj $SUBJ

#============================================#
#          用根证书签发server端证书          #
#============================================#

# 3.生成服务端私钥
openssl genrsa -out server-key.pem 4096

# 4.生成服务端证书请求文件
openssl req -new -sha256 -key server-key.pem -out server.csr -subj "/CN=$HOST"

# 5.使tls连接能通过ip地址方式,绑定IP
echo subjectAltName = IP:127.0.0.1,IP:$HOST > extfile.cnf

# 6.使用根证书签发服务端证书
openssl x509 -passin pass:$PASSWORD -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf


#============================================#
#          用根证书签发client端证书          #
#============================================#

# 7.生成客户端私钥
openssl genrsa -out key.pem 4096

# 8.生成客户端证书请求文件
openssl req -subj '/CN=client' -new -key key.pem -out client.csr

# 9.客户端证书配置文件
echo extendedKeyUsage = clientAuth > extfile.cnf

# 10.使用根证书签发客户端证书
openssl x509 -passin pass:$PASSWORD -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf

#============================================#
#                    清理                    #
#============================================#
# 删除中间文件
rm -f client.csr server.csr ca.srl extfile.cnf

# 转移目录
mkdir client server
cp {ca,cert,key}.pem client
cp {ca,server-cert,server-key}.pem server
rm {cert,key,server-cert,server-key}.pem

# 设置私钥权限为只读
chmod -f 0400 ca-key.pem server/server-key.pem client/key.pem

执行服务端配置

# 给脚本添加运行权限
chmod +x tlscert.sh
HOST_IP=127.0.0.1
./tlscert.sh $HOST_IP
# 客户端需要的证书保存在client目录下, 服务端需要的证书保存在server目录下
sudo cp server/* /etc/docker
# 修改配置
sudo vi /etc/default/docker
# 改为 DOCKER_OPTS="--selinux-enabled --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pem -H=unix:///var/run/docker.sock -H=0.0.0.0:2375"

# 重启docker
sudo service docker restart

关于 Ubuntu 16.04.2 LTS 下DOCKER_OPTS 不生效的问题解决

接着按之前的方式连接服务端就出错了,说明 TLS 已经生效了。

ubuntu@VM-84-201-ubuntu:/usr/anyesu/docker$ docker -H tcp://127.0.0.1:2375 version
Get http://127.0.0.1:2375/v1.29/version: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS?

正确的访问方式:

# 客户端加tls参数访问
docker --tlsverify --tlscacert=client/ca.pem --tlscert=client/cert.pem --tlskey=client/key.pem -H tcp://127.0.0.1:2375 version

# Docker API方式访问
curl https://127.0.0.1:2375/images/json --cert client/cert.pem --key client/key.pem --cacert client/ca.pem

# 简化客户端调用参数配置
sudo cp client/* ~/.docker
# 追加环境变量
echo -e "export DOCKER_HOST=tcp://$HOST_IP:2375 DOCKER_TLS_VERIFY=1" >> ~/.bashrc

sudo docker version

切记, 要保护好客户端证书, 这是连接服务端的凭证。另外根证书私钥也要保存好, 泄漏之后就能签发客户端证书了。

认证模式


1. 服务端认证模式
选项 说明
tlsverify, tlscacert, tlscert, tlskey 向客户端发送服务端证书, 校验客户端证书是否由指定的 CA ( 自签名根证书 ) 签发
tls, tlscert, tlskey 向客户端发送服务端证书, 不校验客户端证书是否由指定的 CA ( 自签名根证书 ) 签发
2. 客户端认证模式
选项 说明
tls 校验服务端证书是否由 公共的 CA 机构签发
tlsverify, tlscacert 校验服务端证书是否由指定的 CA ( 自签名根证书 ) 签发
tls, tlscert, tlskey 使用客户端证书进行身份验证, 但不校验服务端证书是否由指定的 CA ( 自签名根证书 ) 签发
tlsverify, tlscacert, tlscert, tlskey 使用客户端证书进行身份验证且校验服务端证书是否由指定的 CA ( 自签名根证书 ) 签发

关于远程构建命令


在之前的文章中介绍了 使用 Docker Compose 构建容器 , 学了今天的内容之后可以连接远程 Docker Daemon 进行构建, 不过需要注意的一点是, 构建需要的配置文件、依赖文件等都需要在客户端准备好, 然后会把这些内容传输到服务端执行构建或运行容器。

另外, win10 下的 WSL 也可以安装 Docker ( 不过可能是因为早期版本子系统的缘故, Docker 服务端跑不起来, 只能运行 Docker 客户端, 前段时间的 创意者更新 中可能有所改进, 不过还未尝试 ), 通过 Docker 客户端连接远程 Docker 服务 假装 体验下 Docker 也是不错的。

参考文章


  • tls官方文档
  • centos下修改docker连接docker_host默认方式为tls方式
  • 以HTTPS的方式运行docker
  • OpenSSL证书生成方法
  • Docker API

系列文章


Docker 学习总结

Docker 常用指令详解

使用 Dockerfile 构建镜像

使用 Docker Compose 构建容器

Docker 下的网络模式


转载请注明出处:http://www.jianshu.com/p/7ba1a93e6de4

你可能感兴趣的:(Docker Daemon 连接方式详解)