docker 远链接

4 docker 架构

Docker uses a client-server architecture. The Docker client talks to the Docker daemon, which does the heavy lifting of building, running, and distributing your Docker containers. The Docker client and daemon can run on the same system, or you can connect a Docker client to a remote Docker daemon. The Docker client and daemon communicate using a REST API, over UNIX sockets or a network interface. (Docker使用客户端 - 服务器架构。 Docker客户端与Docker守护进 程通信,后者负责构建,运行和分发Docker容器。 Docker客户端和守护程序可以在同一 系统上运行,也可以将Docker客户端连接到远程Docker守护程序。 Docker客户端和守 护程序使用REST API,通过UNIX套接字或网络接口进行通信。)

4.1 docker daemon

The Docker daemon ( dockerd ) listens for Docker API requests and manages Docker objects such as images, containers, networks, and volumes. A daemon can also communicate with other daemons to manage Docker services. (Docker守护程 序(dockerd)侦听Docker API请求并管理Docker对象,如图像,容器,网络和卷。 守 护程序还可以与其他守护程序通信以管理Docker服务。)

4.2 docker client

The Docker client ( docker ) is the primary way that many Docker users interact with Docker. When you use commands such as docker run , the client sends these commands to dockerd , which carries them out. The docker command uses the Docker API. The Docker client can communicate with more than one daemon. (Docker客户端(docker)是许多Docker用户与Docker交互的主要方式。 当您使用诸如 docker run之类的命令时,客户端会将这些命令发送到dockerd,后者将其执行。 docker命令使用Docker API。 Docker客户端可以与多个守护进程通信。)

4.3 docker registry

A Docker registry stores Docker images. Docker Hub is a public registry that anyone can use, and Docker is configured to look for images on Docker Hub by default. You can even run your own private registry. If you use Docker Datacenter (DDC), it includes Docker Trusted Registry (DTR). When you use the docker pull or docker run commands, the required images are pulled from your configured registry. When you use the docker push command, your image is pushed to your configured registry.(Docker注册表存储 Docker镜像。 Docker Hub是任何人都可以使用的公共注册中心,Docker配置为默认在 Docker Hub上查找图像。 您甚至可以运行自己的私人注册表。 如果您使用Docker Datacenter(DDC),它包括Docker Trusted Registry(DTR)。使用docker pull或 docker run命令时,将从配置的注册表中提取所需的映像。 使用docker push命令时, 图像将被推送到配置的注册表。)

 

 

配置 TLS 实现安全的 Docker 远程连接。

GitHub:https://github.com/khs1994-docker/dockerd-tls

本机: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 客户端与服务端不在同一主机上。

 

Docker为C/S架构,服务端为docker daemon,客户端为docker.service. 默认不会监听任何端口,只能在本地使用docker客户端或者使用Docker API进行操作。要支持远程客户端访问需要做如下设置(不安全,因为开了监听端口,任何人都可以远程连接到docker daemon服务器进行操作):

docker.service 中 dockerd 的 -H 参数不能与 daemon.json 中的 hosts 键值对冲突。(其他参数同理)
/etc/docker/daemon.json会被docker.service的配置文件覆盖,直接添加daemon.json不起作用;

方法1、

vim /lib/systemd/system/docker.service

将管理地址写入 /etc/profile  :  

echo 'export DOCKER_HOST=tcp://0.0.0.0:2375' >> /etc/profile

source /etc/profile

 

然后重启:

systemctl daemon-reload && systemctl restart docker

 

方法2、

systemctl edit docker.service  写入以下几行内容:

  [Service]
  ExecStart=
  ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

保存、退出;

重启: systemctl daemon-reload && systemctl restart docker

 

方法3、

新建 /etc/systemd/system/docker.service.d/docker.conf 文件,写入以下几行内容:
  [Service]
  ExecStart=
  ExecStart=/usr/bin/dockerd

在 /etc/docker/daemon.json 中写入以下内容:
{
"hosts":[
"unix:///var/run/docker.sock",
"tcp://0.0.0.0:2375"
]
}

然后重启: systemctl daemon-reload && systemctl restart docker

 

在另外一台docker服务器上远程连接测试:

docker -H tcp://192.168.3.201:2375 ps  #192.168.3.201:是开启允许远程连接的那一台服务器,2375:端口   ps:docker命令

非安全的连接方式

先介绍 非安全 的连接方式。

服务端配置

CoreOS 请使用第二种方法,其他 Linux 系统配置时选择以下两种方法之一

通常的配置方法

docker.servicedockerd-H 参数不能与 daemon.json 中的 hosts 键值对冲突。(其他参数同理)

新建 /etc/systemd/system/docker.service.d/docker.conf 文件。

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

/etc/docker/daemon.json (下文统一简称 daemon.json)中写入以下内容

{
  "hosts":[
    "unix:///var/run/docker.sock",
    "tcp://0.0.0.0:2375"
  ]
}

该文件必须符合 json 规范写法,否则 Docker 将不能启动。

重新启动 Docker。

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

CoreOS 官方文档提供的方法

官方文档:https://coreos.com/os/docs/latest/customizing-docker.html

新建 /etc/systemd/system/docker-tcp.socket 文件

[Unit]
Description=Docker Socket for the API

[Socket]
# ListenStream=127.0.0.1:2375
ListenStream=2375
BindIPv6Only=both
Service=docker.service

[Install]
WantedBy=sockets.target

重新启动服务

$ sudo systemctl daemon-reload
$ sudo systemctl enable docker-tcp.socket
$ sudo systemctl stop docker
$ sudo systemctl start docker-tcp.socket
$ sudo systemctl start docker

注意:这种方法必须先启动 docker-tcp.socket,再启动 Docker,一定要注意启动顺序!

systemd socket 详情请查看:http://www.jinbuguo.com/systemd/systemd.socket.html

在客户端测试连接

macOS (下文中 macOS一律代指 Docker 客户端)上使用以下命令

$ docker -H 192.168.57.110:2375 info

成功输出信息,证明客户端可以成功连接到远程的服务端。

macOS 上远程操作 CoreOS 上的 Docker 每次执行命令时必须加上 -H 参数(这样太麻烦,我们可以通过将 Docker 命令 参数 配置成 环境变量 来简化命令)。

macOS 上执行如下命令。

$ export DOCKER_HOST="tcp://0.0.0.0:2375"

$ docker info

这里写入的变量是临时生效的,重新登录环境变量就消失了(下文同理,之后不再赘述),让环境变量永久生效请写入 ~/.bashrc

fish shell

本人 macOS 上使用的 shell 是 fish,这里记录一下 fish 中的操作,使用 bash 的读者请忽略 fish 相关内容。

$ set -Ux DOCKER_HOST "tcp://0.0.0.0:2375"

# 以上命令写入的环境变量是永久存在的,通过以下命令删除环境变量

$ set -Ue DOCKER_HOST

配置安全连接

官方文档:https://docs.docker.com/engine/security/https/

上面我们配置的远程连接是不安全的,只能用于测试环境中。在生产环境中需要配置 TLS 安全连接,只有拥有密钥的客户端,才能连接到远程的服务端。

服务端配置

只能使用 Linux 下的 openssl 生成密钥,macOS 下的不可以。在 CoreOS 下执行以下操作

手动执行命令生成证书(不推荐)

这一步较复杂,你可以跳过这一方法,使用容器生成证书。此方法来自 Docker 官方文档 https://docs.docker.com/engine/security/https/。

文件总览

├── ca-key.pem       # 妥善保管,连接时用不到
├── ca.pem           # clent & server
├── ca.srl           # 用不到
├── cert.pem         # client
├── client.csr       # 请求文件
├── extfile.cnf      # 配置文件
├── key.pem          # client
├── server-cert.pem  # server
├── server.csr       # 请求文件
└── server-key.pem   # server
# 生成 CA 私钥

$ openssl genrsa -aes256 -out ca-key.pem 4096

# 需要输入两次密码(自定义)

# 生成 CA 公钥

$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

# 输入上一步中设置的密码,然后需要填写一些信息

# 下面是服务器证书生成

# 生成服务器私钥

$ openssl genrsa -out server-key.pem 4096

# 用私钥生成证书请求文件

$ openssl req -subj "/CN=localhost" -sha256 -new -key server-key.pem -out server.csr

$ echo subjectAltName = DNS:localhost,DNS:www.khs1994.com,DNS:tencent,IP:192.168.199.100,IP:192.168.57.110,IP:127.0.0.1 >> extfile.cnf

# 允许服务端哪些 IP 或 host 能被客户端连接,下文会进行测试。

# DNS 我也不是很理解,这里配置 localhost ,公共 DNS 解析的域名,/etc/hosts 文件中的列表进行测试。

$ echo extendedKeyUsage = serverAuth >> extfile.cnf

# 用 CA 来签署证书

$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem -extfile extfile.cnf

# 再次输入第一步设置的密码

# 下面是客户端证书文件生成

# 生成客户端私钥

$ openssl genrsa -out key.pem 4096

# 用私钥生成证书请求文件  

$ openssl req -subj '/CN=client' -new -key key.pem -out client.csr

$ echo extendedKeyUsage = clientAuth >> extfile.cnf

# 用 CA 来签署证书

$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out cert.pem -extfile extfile.cnf

# 再次输入第一步设置的密码

# 删除文件,更改文件权限

$ rm -v client.csr server.csr

$ chmod -v 0400 ca-key.pem key.pem server-key.pem

$ chmod -v 0444 ca.pem server-cert.pem cert.pem

ca.pem server-cert.pem server-key.pem 三个文件移动到 /etc/docker/ 文件夹中。

使用容器生成证书(推荐)

GitHub:https://github.com/khs1994-docker/dockerd-tls

方法来自 CoreOS 官方文档:https://coreos.com/os/docs/latest/generate-self-signed-certificates.html

既然使用容器那就可以在任何系统运行,只要把生成的证书文件对应的放到 Docker 客户端和服务端即可。

$ git clone --depth=1 https://github.com/khs1994-docker/dockerd-tls.git
$ cd dockerd-tls

./cfssl/*.json 中配置好 CN hosts

$ docker-compose up cfssl

命令执行完毕之后在 ./cfssl/cert 文件夹中可以看到证书文件,修改文件权限。

$ chmod -v 0400 ca-key.pem key.pem server-key.pem

$ chmod -v 0444 ca.pem server-cert.pem cert.pem

ca.pem server-cert.pem server-key.pem 三个文件移动到服务端 /etc/docker/ 文件夹中。

CoreOS 请使用第二种方法,其他 Linux 系统根据上文选择的方法,这里选择对应的方法

通常的配置方法

修改 daemon.json 文件。

注意:非安全连接使用的是 2375 端口,安全连接使用的是 2376 端口。当然这是推荐的端口配置,你可以配置任何端口!

{
  "tlsverify": true,
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "tlscacert": "/etc/docker/ca.pem",
  "hosts":[
    "unix:///var/run/docker.sock",
    "tcp://0.0.0.0:2376"
  ]
}

重新启动 Docker

$ sudo systemctl restart docker

CoreOS 官方文档的方法

首先需要修改 /etc/systemd/system/docker-tcp.socket 文件内容

ListenStream=2375

# 修改为

ListenStream=2376

修改 CoreOS 上的 daemon.json 文件。

{
  "tlsverify": true,
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "tlscacert": "/etc/docker/ca.pem"
}

重新启动服务。

$ sudo systemctl daemon-reload
$ sudo systemctl stop docker
$ sudo systemctl restart docker-tcp.socket
$ sudo systemctl restart docker

上文已经提到了启动顺序,这里提示一下,不再赘述。

客户端远程安全连接

ca.pem cert.pem key.pem 三个文件通过 scp 下载到 macOS

macOS 执行以下命令,密钥路径请根据实际情况填写。

$ docker --tlsverify \
  --tlscacert=/Users/khs1994/test/ca.pem \
  --tlscert=/Users/khs1994/test/cert.pem \
  --tlskey=/Users/khs1994/test/key.pem \
  -H=192.168.57.110:2376 \
  info

把密钥放入 ~/.docker 文件夹中

每次操作需要跟那么多参数,太麻烦了。我们可以把 ca.pem cert.pem key.pem 三个文件放入客户端 ~/.docker 中,然后配置环境变量就可以简化命令了。

$ export DOCKER_HOST=tcp://192.168.57.110:2376 DOCKER_TLS_VERIFY=1

$ docker info

你也可以选择其他路径,请通过环境变量 DOCKER_CERT_PATH 指定。

报错详情

不使用安全连接

$ docker -H 192.168.57.110:2376 info
Get http://192.168.57.110:2376/v1.34/containers/json?all=1: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS?

在非允许列表 IP 中登录

假如远程服务器还有一个 IP 10.141.20.83 ,现在我们尝试使用这个 IP 作为服务端地址,看看客户端能否连接到。

$ docker -H 10.141.20.83:2376 info
error during connect: Get https://10.141.20.83:2376/v1.34/info: x509: certificate is valid for 192.168.57.110, 192.168.199.100, 127.0.0.1, not 10.141.20.83

在非允许列表 Host 中登录

$ docker -H localhost:2376 info
error during connect: Get https://localhost:2375/v1.34/info: x509: certificate is valid for coreos1, not localhost

fish shell

$ set -Ux DOCKER_HOST tcp://192.168.57.110:2376
$ set -Ux DOCKER_TLS_VERIFY 1

# 以上命令写入环境变量是永久存在的,通过以下命令删除环境变量

$ set -Ue DOCKER_HOST ; set -Ue DOCKER_TLS_VERIFY

服务端验证模式

  • tlsverify, tlscacert, tlscert, tlskey set: Authenticate clients
  • tls, tlscert, tlskey: Do not authenticate clients

客户端验证模式

  • tls: Authenticate server based on public/default CA pool
  • tlsverify, tlscacert: Authenticate server based on given CA
  • tls, tlscert, tlskey: Authenticate with client certificate, do not authenticate server based on given CA
  • tlsverify, tlscacert, tlscert, tlskey: Authenticate with client certificate and authenticate server based on given CA

测试远程构建 Docker 镜像

macOS 新建 demo 文件夹并进入。

我们首先建一个文本文件 test.txt

hello!

然后新建一个简单的 Dockerfile 文件

FROM busybox

COPY ./test.txt /

CMD cat /test.txt

按照前面的方法设置好环境变量,这里不再赘述。

$ docker -H 192.168.57.110:2375 --tlsverify build -t khs1994/busybox .

在远程服务端查看

SSH 登录到 CoreOS(这里为了便于理解,SSH 到远程服务器操作)。

$ docker image ls
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
khs1994/busybox                        latest              368d23df8500        10 seconds ago      1.13MB

我们已经查看到了镜像。

$ docker run -it --rm khs1994/busybox
hello!

运行成功。

客户端恢复原状

你如果想在 macOS 操作本地的服务端,请将上面配置的环境变量删除,这里不再赘述。

More Information

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值