1. 程式人生 > 其它 >Docker 遠端連線 -- dockerd 命令詳解

Docker 遠端連線 -- dockerd 命令詳解

配置 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 客戶端與服務端不在同一主機上。

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.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 "x15x03x01x00x02x02".
* 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