遠程連接docker daemon,Docker Remote API


https://deepzz.com/post/dockerd-and-docker-remote-api.html

不知道大家有沒有遇到這樣一種情形:每次構建好了鏡像,push到私有倉庫后。你還要ssh到服務器,進行pull,每次登錄服務器的過程非常的痛苦。如果服務器ip沒有映射域名,那記錄ip也是一個痛苦的過程。博主,開始關注到docker remote api,它可以讓你在本地就可以完成docker的所有操作,於是博主開發了基於etcd配置的docker管理工具,還蠻好用的。下面是我docker部分配置的一些經歷,分享給大家,希望對大家有幫助。

更新列表:

  • 2017/04/27:添加 /etc/docker/daemon.json 文件配置過程(version 在 1.12 之后可用),文檔地址

服務端搭建

首先,我們需要通過系統的包管理器安裝docker

當我們的docker安裝好之后,運行sudo docker ps查看是否運行成功。

$ sudo groupadd docker # 創建docker組
$ sudo usermod -aG docker whoami # 將當前用戶添加到docker組
重啟docker服務,注銷登錄,再次登錄,這樣就可以免去每次輸入sudo的煩惱了。

ok,我們安裝好之后,docker宿主程序默認是通過非網絡的Unix套接字運行,是只能夠進行本地通信(/var/run/docker.sock),是不能夠直接遠程連接docker的。需要修改其配置:

測試環境

ubuntu: 有host1,ubuntu系統,其配置文件路徑在/etc/default/docker

$ sudo vi /etc/default/docker
  DOCKER_OPTS="-H tcp://0.0.0.0:2375" $ sudo service docker restart # ubuntu docker的其它操作方式 $ sudo service docker start $ sudo service docker stop 

這里監聽了tcp2375端口,現在我們就可以通過別的主機host2訪問到這台主機的docker了(但是host1現在不能本地訪問了)。推薦DOCKER_OPTS寫成:

DOCKER_OPTS="-H unix:///var/run/docker.sock -H 0.0.0.0:2375" 

當然了這是不安全的,任何人都能夠訪問該端口,推薦測試用。

centos: 有host1,centos系統,其配置文件路徑在/etc/sysconfig/docker

$ sudo vi /etc/sysconfig/docker
  other_args="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock" $ sudo service docker restart # centos docker的其它操作方式 $ sudo service docker start $ sudo service docker stop $ /bin/systemctl start docker.service 

注:同樣這里也是不安全的。

daemon.json:1.12版本后, 用戶可以自行創建配置文件 /etc/docker/daemon.json,該文件不區分系統,是通用的,推薦使用。具體參考:官方文檔。不知道版本的可以通過 $ dockerd version 查看。

首先,你需要創建 /etc/docker/daemon.json 文件,文件內容如下:

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

然后,通過 dockerd 啟動守護進程:

$ dockerd
WARN[0000] [!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]
INFO[0000] libcontainerd: new containerd process, pid: 3952
WARN[0000] containerd: low RLIMIT_NOFILE changing to max  current=1024 max=4096
INFO[0001] [graphdriver] using prior storage driver "aufs"
INFO[0001] Graph migration to content-addressability took 0.00 seconds
WARN[0001] Your kernel does not support cgroup blkio weight
WARN[0001] Your kernel does not support cgroup blkio weight_device
INFO[0001] Loading containers: start.
......................INFO[0001] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address INFO[0001] Loading containers: done. INFO[0001] Daemon has completed initialization INFO[0001] Docker daemon commit=7392c3b graphdriver=aufs version=1.12.5 INFO[0001] API listen on /var/run/docker.sock INFO[0001] API listen on [::]:2375 

這里你可以看到警告 WARN[0000],在不使用 tlsverify 驗證的情況下,一定要注意 IP 的綁定!!!

更多 dockerd 命令的使用方法請參考:https://docs.docker.com/engine/reference/commandline/dockerd/

可以看到,上面所說的均沒有采取任何驗證方式。僅供測試使用或內部使用。千萬不要暴露到公網。

線上環境,安全環境

這里介紹,通過自簽名證書安全認證構建HTTPS encypted socket。上面測試環境用的2375端口,docker推薦2376作為安全端口。當然我們可以隨意設置端口,哈哈。

證書的生成: 詳細信息,移步官網:Protect the Docker daemon socket。其原理是通過指定tlsverify標志並將Docker的tlscacert標志指向受信任的CA證書來啟用TLS。在守護進程模式下,它只允許來自由該CA簽名的證書認證的客戶端的連接。 在客戶端模式下,它將只連接到具有由該CA簽名的證書的服務器。

警告:使用TLS和管理CA是一個高深的主題。在生產環境中使用OpenSSL,x509和TLS之前,請熟悉OpenSSL,x509和TLS。
警告:這些TLS命令將只在Linux上生成一組有效的證書。 macOS附帶的OpenSSL版本與Docker所需的證書不兼容。

首先,生成CA公鑰和私鑰:

$ openssl genrsa -aes256 -out ca-key.pem 4096 # 生成CA私鑰 Generating RSA private key, 4096 bit long modulus ............................................................................................................................................................................................++ ........++ e is 65537 (0x10001) Enter pass phrase for ca-key.pem: Verifying - Enter pass phrase for ca-key.pem: $ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem #生成CA公鑰,也就是證書 Enter pass phrase for ca-key.pem: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]: State or Province Name (full name) [Some-State]:Queensland Locality Name (eg, city) []:Brisbane Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc Organizational Unit Name (eg, section) []:Sales Common Name (e.g. server FQDN or YOUR name) []:$HOST Email Address []:Sven@home.org.au 

現在我們有了CA,就可以創建服務器私鑰和證書請求文件了,請確保Common Name (i.e., server FQDN or YOUR name)匹配你將要連接的docker主機。

注意,使用你docker宿主機的DNS name替換下面的$HOST

$ openssl genrsa -out server-key.pem 4096 # 生成服務器私鑰 Generating RSA private key, 4096 bit long modulus .....................................................................++ .................................................................................................++ e is 65537 (0x10001) $ openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr # 用私鑰生成證書請求文件 

現在,我們可以用CA來簽署證書了。這里我們可以填寫IP地址或則DNS name,如,我們需要允許10.10.10.20127.0.0.1連接:

$ echo subjectAltName = IP:10.10.10.20,IP:127.0.0.1 > extfile.cnf # 將Docker守護程序密鑰的擴展使用屬性設置為僅用於服務器身份驗證: $ echo extendedKeyUsage = serverAuth >> extfile.cnf $ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \ -CAcreateserial -out server-cert.pem -extfile extfile.cnf Signature ok subject=/CN=your.host.com Getting CA Private Key Enter pass phrase for ca-key.pem: 

客戶端證書:

$ openssl genrsa -out key.pem 4096 # 客戶端私鑰 Generating RSA private key, 4096 bit long modulus .........................................................++ ................++ e is 65537 (0x10001) $ openssl req -subj '/CN=client' -new -key key.pem -out client.csr # 客戶端證書請求文件 

CA為客戶端簽署證書文件:

# 要使密鑰適配客戶端身份驗證,請創建擴展配置文件:
$ echo extendedKeyUsage = clientAuth >> extfile.cnf $ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \ -CAcreateserial -out cert.pem -extfile extfile.cnf Signature ok subject=/CN=client Getting CA Private Key Enter pass phrase for ca-key.pem: 

刪除證書請求文件:

$ 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 

證書的部署:

# ubuntu
$ sudo vi /etc/default/docker 如:DOCKER_OPTS="-D --tlsverify=true --tlscert=/var/docker/server-cert.pem --tlskey=/var/docker/server-key.pem --tlscacert=/var/docker/ca.pem -H tcp://0.0.0.0:2376" $ sudo service docker restart # centos $ sudo vi /etc/sysconfig/docker 如:OPTIONS='--selinux-enabled --log-driver=journald --tlsverify=true' DOCKER_CERT_PATH=/etc/docker $ sudo service docker restart # daemon.json $ sudo vi /etc/docker/daemon.json { "tlsverify": true, "tlscert": "/var/docker/server-cert.pem", "tlskey": "/var/docker/server-key.pem", "tlscacert": "/var/docker/ca.pem", "hosts": [ "tcp://0.0.0.0:2376", "unix:///var/run/docker.sock" ] } $ dockerd INFO[0000] libcontainerd: new containerd process, pid: 4823 WARN[0000] containerd: low RLIMIT_NOFILE changing to max current=1024 max=4096 INFO[0001] [graphdriver] using prior storage driver "aufs" INFO[0001] Graph migration to content-addressability took 0.00 seconds WARN[0001] Your kernel does not support cgroup blkio weight WARN[0001] Your kernel does not support cgroup blkio weight_device INFO[0001] Loading containers: start. ......................INFO[0001] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address INFO[0001] Loading containers: done. INFO[0001] Daemon has completed initialization INFO[0001] Docker daemon commit=7392c3b graphdriver=aufs version=1.12.5 INFO[0001] API listen on /var/run/docker.sock INFO[0001] API listen on [::]:2376 

ok,可以看到沒有警告 WARN

警告:這些證書的保存非常重要,關系着你的服務器的安全,請妥善保管。

客戶端連接

普通連接:

$ docker -H tcp://127.0.0.1:2375 ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed7b8f338ad mongo:3.2 "/entrypoint.sh mo..." 11 days ago Up 3 hours 0.0.0.0:27017->27017/tcp eidb 

TLS連接:

$ docker --tlsverify --tlscacert=~/docker/ca.pem \ --tlscert=~/docker/cert.pem \ --tlskey=~/docker/key.pem \ -H=192.168.99.100:2376 version Client: Version: 1.13.0-rc1 API version: 1.25 Go version: go1.7.3 Git commit: 75fd88b Built: Fri Nov 11 22:32:34 2016 OS/Arch: darwin/amd64 Server: Version: 1.13.0-rc1 API version: 1.25 Minimum API version: 1.12 Go version: go1.7.3 Git commit: 75fd88b Built: Fri Nov 11 22:32:34 2016 OS/Arch: linux/amd64 Experimental: false # curl 連接測試 $ curl https://192.168.99.100:2376/images/json \ --cert ~/.docker/cert.pem \ --key ~/.docker/key.pem \ --cacert ~/.docker/ca.pem 

為了不每次都指定證書,我們可以指定默認連接:

$ mkdir -pv ~/.docker $ cp -v ~/{ca,cert,key}.pem ~/.docker $ export DOCKER_HOST=tcp://192.168.99.100:2376 DOCKER_TLS_VERIFY=1 # 這里只是臨時指定,永久請寫入*profile里面 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed7b8f338ad mongo:3.2 "/entrypoint.sh mo..." 11 days ago Up 3 hours 0.0.0.0:27017->27017/tcp eidb 

當然也可以指定證書文件路徑:

$ export DOCKER_CERT_PATH="~/docker" 

我的mac下的~/.bash_profile如下:

export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.100:2376" export DOCKER_API_VERSION="" export DOCKER_CERT_PATH="/Users/chen/.docker/machine/machines/default" 

特別說明以下,DOCKER_API_VERSION可以不設置,默認是docker/client/client.go中的const DefaultVersion string版本。

其它模式

如果你不想有完全的雙向認證,你可以通過混合標志來運行各種其他模式的Docker。

宿主機 模式:

  • tlsverifytlscacerttlscerttlskey set: Authenticate clients
  • tlstlscerttlskey: Do not authenticate clients

客戶度 模式:

  • tls: Authenticate server based on public/default CA pool
  • tlsverifytlscacert: Authenticate server based on given CA
  • tlstlscerttlskey: Authenticate with client certificate, do not authenticate server based on given CA
  • tlsverifytlscacerttlscerttlskey: Authenticate with client certificate and authenticate server based on given CA

附上:

docker remote apihttps://github.com/docker/docker/tree/master/client

etcd clientv3https://github.com/coreos/etcd/tree/master/clientv3

本文鏈接:https://deepzz.com/post/dockerd-and-docker-remote-api.html參與評論 »

--EOF--


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM