配置 TLS
实现安全的 Docker 远程连接。
GitHub:https://github.com/khs1994-docker/lnmp-k8s
本机:macOS
远程机:使用 VirtualBox
虚拟 CoreOS
(IP 192.168.57.110
)
目标:能在 macOS
远程操作 CoreOS
。(注意不是 SSH 远程登录)。dockerd
命令仅能在 Linux
下使用。
官方文档:https://docs.docker.com/edge/engine/reference/commandline/dockerd/
官方文档:https://docs.docker.com/engine/admin/
本文适合有一定 Linux 基础的读者阅读,如果出现错误,请将各种操作之前修改过的文件恢复原状并删除新增的环境变量。
我们已经知道 Docker 是客户端/服务端架构。一般情况下我们使用的 Docker 客户端/服务端都在本机(macOS、Windows 实际上是在本机启动了一个虚拟机,这里指 Linux)。本文所指的情况是 Docker 客户端与服务端不在同一主机上。
Dokcer 架构
Typically, you start Docker using operating system utilities. For debugging purposes, you can start Docker manually using the dockerd
command. You may need to use sudo
, depending on your operating system configuration. When you start Docker this way, it runs in the foreground and sends its logs directly to your terminal.
非安全的连接方式
先介绍 非安全
的连接方式。
服务端配置
CoreOS
请使用第二种方法,其他 Linux 系统配置时选择以下两种方法之一
通常的配置方法
docker.service
中 dockerd
的 -H
参数不能与 daemon.json
中的 hosts
键值对冲突。(其他参数同理)
新建 /etc/systemd/system/docker.service.d/docker.conf
文件。
1 | [Service] |
在 /etc/docker/daemon.json
(下文统一简称 daemon.json
)中写入以下内容
1 | { |
该文件必须符合 json 规范写法,否则 Docker 将不能启动。
重新启动 Docker。
1 | $ sudo systemctl daemon-reload |
CoreOS 官方文档提供的方法
官方文档:https://coreos.com/os/docs/latest/customizing-docker.html
新建 /etc/systemd/system/docker-tcp.socket
文件
1 | [Unit] |
重新启动服务
1 | $ sudo systemctl daemon-reload |
注意:这种方法必须先启动 docker-tcp.socket,再启动 Docker,一定要注意启动顺序!
systemd socket 详情请查看:http://www.jinbuguo.com/systemd/systemd.socket.html
在客户端测试连接
在 macOS
(下文中 macOS
一律代指 Docker 客户端)上使用以下命令
1 | $ docker -H 192.168.57.110:2375 info |
成功输出信息,证明客户端可以成功连接到远程的服务端。
在 macOS
上远程操作 CoreOS
上的 Docker
每次执行命令时必须加上 -H
参数(这样太麻烦,我们可以通过将 Docker 命令 参数
配置成 环境变量
来简化命令)。
在 macOS
上执行如下命令。
1 | $ export DOCKER_HOST="tcp://0.0.0.0:2375" |
这里写入的变量是临时生效的,重新登录环境变量就消失了(下文同理,之后不再赘述),让环境变量永久生效请写入 ~/.bashrc
。
fish shell
本人 macOS
上使用的 shell 是 fish,这里记录一下 fish 中的操作,使用 bash 的读者请忽略 fish 相关内容。
1 | $ set -Ux DOCKER_HOST "tcp://0.0.0.0:2375" |
配置安全连接
官方文档:https://docs.docker.com/engine/security/https/
上面我们配置的远程连接是不安全的,只能用于测试环境中。在生产环境中需要配置 TLS
安全连接,只有拥有密钥的客户端,才能连接到远程的服务端。
服务端配置
只能使用 Linux 下的 openssl
生成密钥,macOS 下的不可以。在 CoreOS
下执行以下操作
手动执行命令生成证书(不推荐)
这一步较复杂,你可以跳过这一方法,使用容器生成证书。此方法来自 Docker 官方文档 https://docs.docker.com/engine/security/https/。
文件总览
1 | ├── ca-key.pem # 妥善保管,连接时用不到 |
1 | # 生成 CA 私钥 |
把 ca.pem
server-cert.pem
server-key.pem
三个文件移动到 /etc/docker/
文件夹中。
使用容器生成证书(推荐)
GitHub:https://github.com/khs1994-docker/lnmp-k8s
方法来自 CoreOS
官方文档:https://coreos.com/os/docs/latest/generate-self-signed-certificates.html
既然使用容器那就可以在任何系统运行,只要把生成的证书文件对应的放到 Docker 客户端和服务端即可。
1 | $ git clone --depth=1 https://github.com/khs1994-docker/lnmp-k8s |
在 ./systemd/.env
中配置
1 | server_hosts=127.0.0.1,localhost,1.1.1.1 |
值为 Docker 服务端所在 IP 或 域名。多个值用逗号分隔
1 | $ docker-compose up cfssl-single |
命令执行完毕之后在 ./systemd/certs
文件夹中可以看到证书文件,修改文件权限。
1 | $ chmod -v 0400 ca-key.pem key.pem server-key.pem |
把 ca.pem
server-cert.pem
server-key.pem
三个文件移动到服务端 /etc/docker/
文件夹中。
CoreOS
请使用第二种方法,其他 Linux 系统根据上文选择的方法,这里选择对应的方法
通常的配置方法
修改 daemon.json
文件。
注意:非安全连接使用的是
2375
端口,安全连接使用的是2376
端口。当然这是推荐的端口配置,你可以配置任何端口!
1 | { |
重新启动 Docker
1 | $ sudo systemctl restart docker |
CoreOS 官方文档的方法
首先需要修改 /etc/systemd/system/docker-tcp.socket
文件内容
1 | ListenStream=2375 |
修改 CoreOS
上的 daemon.json
文件。
1 | { |
重新启动服务。
1 | $ sudo systemctl daemon-reload |
上文已经提到了启动顺序,这里提示一下,不再赘述。
客户端远程安全连接
将 ca.pem
cert.pem
key.pem
三个文件通过 scp
下载到 macOS
。
在 macOS
执行以下命令,密钥路径请根据实际情况填写。
1 | $ docker --tlsverify \ |
把密钥放入 ~/.docker
文件夹中
每次操作需要跟那么多参数,太麻烦了。我们可以把 ca.pem
cert.pem
key.pem
三个文件放入客户端 ~/.docker
中,然后配置环境变量就可以简化命令了。
1 | $ export DOCKER_HOST=tcp://192.168.57.110:2376 DOCKER_TLS_VERIFY=1 |
你也可以选择其他路径,请通过环境变量
DOCKER_CERT_PATH
指定。
报错详情
不使用安全连接
1 | $ docker -H 192.168.57.110:2376 info |
在非允许列表 IP 中登录
假如远程服务器还有一个 IP 10.141.20.83
,现在我们尝试使用这个 IP 作为服务端地址,看看客户端能否连接到。
1 | $ docker -H 10.141.20.83:2376 info |
在非允许列表 Host 中登录
1 | $ docker -H localhost:2376 info |
fish shell
1 | $ set -Ux DOCKER_HOST tcp://192.168.57.110:2376 |
服务端验证模式
tlsverify
,tlscacert
,tlscert
,tlskey
set: Authenticate clientstls
,tlscert
,tlskey
: Do not authenticate clients
客户端验证模式
tls
: Authenticate server based on public/default CA pooltlsverify
,tlscacert
: Authenticate server based on given CAtls
,tlscert
,tlskey
: Authenticate with client certificate, do not authenticate server based on given CAtlsverify
,tlscacert
,tlscert
,tlskey
: Authenticate with client certificate and authenticate server based on given CA
测试远程构建 Docker 镜像
在 macOS
新建 demo 文件夹并进入。
我们首先建一个文本文件 test.txt
1 | hello! |
然后新建一个简单的 Dockerfile
文件
1 | FROM busybox |
按照前面的方法设置好环境变量,这里不再赘述。
1 | $ docker -H 192.168.57.110:2376 --tlsverify build -t khs1994/busybox . |
在远程服务端查看
SSH 登录到 CoreOS
(这里为了便于理解,SSH 到远程服务器操作)。
1 | $ docker image ls |
我们已经查看到了镜像。
1 | $ docker run -it --rm khs1994/busybox |
运行成功。
客户端恢复原状
你如果想在 macOS
操作本地的服务端,请将上面配置的环境变量删除,这里不再赘述。