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
:
- Ubuntu:https://docs.docker.com/engine/installation/linux/ubuntu/
- CentOS:https://docs.docker.com/engine/installation/linux/centos/
- 更多,請至官網:https://docs.docker.com/engine/installation/
當我們的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
這里監聽了tcp
的2375
端口,現在我們就可以通過別的主機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.20
和127.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。
宿主機 模式:
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 remote api
:https://github.com/docker/docker/tree/master/client
etcd clientv3
:https://github.com/coreos/etcd/tree/master/clientv3
本文鏈接:https://deepzz.com/post/dockerd-and-docker-remote-api.html,參與評論 »
--EOF--