?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
就Docker Swarm服務(wù)而言,秘密是一組數(shù)據(jù),如密碼,SSH私鑰,SSL證書或另一部分?jǐn)?shù)據(jù),這些數(shù)據(jù)不應(yīng)通過(guò)網(wǎng)絡(luò)傳輸或在Dockerfile或應(yīng)用程序中未加密存儲(chǔ)源代碼。在Docker 1.13及更高版本中,您可以使用Docker 機(jī)密來(lái)集中管理這些數(shù)據(jù),并將其安全地傳輸給需要訪問(wèn)的那些容器。在運(yùn)輸過(guò)程中密碼被加密,并在Docker群中休息。給定的秘密只能被那些被授予明確訪問(wèn)權(quán)限的服務(wù)訪問(wèn),并且只有在這些服務(wù)任務(wù)正在運(yùn)行時(shí)才能訪問(wèn)。
您可以使用秘密來(lái)管理容器在運(yùn)行時(shí)需要的任何敏感數(shù)據(jù),但不想將其存儲(chǔ)在映像或源代碼管理中,例如:
用戶名和密碼
TLS證書和密鑰
SSH密鑰
其他重要數(shù)據(jù),如數(shù)據(jù)庫(kù)或內(nèi)部服務(wù)器的名稱
通用字符串或二進(jìn)制內(nèi)容(最大為500 kb)
注意:Docker機(jī)密僅適用于群集服務(wù),而不適用于獨(dú)立容器。要使用此功能,請(qǐng)考慮將您的容器作為1級(jí)服務(wù)運(yùn)行。
另一個(gè)使用秘密的用例是在容器和一組證書之間提供一個(gè)抽象層??紤]一個(gè)場(chǎng)景,您可以為應(yīng)用程序分別開(kāi)發(fā),測(cè)試和生產(chǎn)環(huán)境。這些環(huán)境中的每一個(gè)都可以擁有不同的憑證,并以相同的秘密名稱存儲(chǔ)在開(kāi)發(fā),測(cè)試和生產(chǎn)群中。您的容器只需要知道秘密的名稱,以便在三種環(huán)境中都能正常工作。
您還可以使用機(jī)密來(lái)管理非敏感數(shù)據(jù),例如配置文件。但是,Docker 17.06和更高版本支持使用configs來(lái)存儲(chǔ)非敏感數(shù)據(jù)。配置直接安裝到容器的文件系統(tǒng)中,而不使用RAM磁盤。
Docker 17.06和更高版本包含對(duì)Windows容器上的秘密的支持。在實(shí)現(xiàn)中存在差異的地方,它們?cè)谙旅娴睦又斜徽{(diào)用。牢記以下顯著差異:
Microsoft Windows沒(méi)有用于管理RAM磁盤的內(nèi)置驅(qū)動(dòng)程序,因此在運(yùn)行Windows容器中,秘密以明文形式保存到容器的根磁盤。但是,當(dāng)容器停止時(shí),秘密將被明確刪除。另外,Windows不支持將正在運(yùn)行的容器作為使用圖像docker commit
或類似命令的圖像。
在Windows上,我們建議在主機(jī)上包含Docker根目錄的卷上啟用BitLocker(https://technet.microsoft.com/en-us/library/cc732774(v = ws.11%29.aspx)以確保運(yùn)行容器的秘密在休息時(shí)被加密。
自定義目標(biāo)的秘密文件不直接綁定到Windows容器中,因?yàn)閃indows不支持非目錄文件綁定掛載。相反,容器的秘密都安裝在C:\ProgramData\Docker\internal\secrets
容器內(nèi)的(應(yīng)用程序不應(yīng)該依賴的實(shí)現(xiàn)細(xì)節(jié)中)。符號(hào)鏈接用于指向容器內(nèi)的秘密所需的目標(biāo)。默認(rèn)目標(biāo)是C:\ProgramData\Docker\secrets
。
在創(chuàng)建使用Windows容器的服務(wù)時(shí),用于指定UID,GID和模式的選項(xiàng)不受秘密支持。當(dāng)前只能由管理員和system
容器內(nèi)的訪問(wèn)權(quán)限的用戶訪問(wèn)秘密。
當(dāng)您為swarm添加秘密時(shí),Docker會(huì)通過(guò)相互TLS連接將密鑰發(fā)送給swarm管理器。秘密存儲(chǔ)在加密的Raft日志中。整個(gè)Raft日志被復(fù)制到其他管理者中,確保與其他群管理數(shù)據(jù)相同的高可用性保證。
警告:Raft數(shù)據(jù)在Docker 1.13和更高版本中被加密。如果您的任何Swarm管理人員運(yùn)行早期版本,并且其中一位經(jīng)理成為群體經(jīng)理,則秘密將以未加密方式存儲(chǔ)在該節(jié)點(diǎn)的Raft日志中。在添加任何秘密之前,將所有管理器節(jié)點(diǎn)更新到Docker 1.13或更高版本,以防止將秘密寫入純文本的Raft日志。
當(dāng)您授予新創(chuàng)建或正在運(yùn)行的服務(wù)對(duì)秘密的訪問(wèn)權(quán)限時(shí),解密的秘密將被裝入容器中的內(nèi)存中文件系統(tǒng)。 容器中安裝點(diǎn)的位置默認(rèn)為L(zhǎng)inux容器中的/ run / secrets / <secret_name>,或Windows容器中的C:\ ProgramData \ Docker \ secrets。 您可以在Docker 17.06和更高版本中指定自定義位置。
您可以更新服務(wù),授權(quán)其訪問(wèn)其他機(jī)密或隨時(shí)撤銷對(duì)指定機(jī)密的訪問(wèn)權(quán)限。
如果節(jié)點(diǎn)是群管理器或者它正在運(yùn)行已被授權(quán)訪問(wèn)秘密的服務(wù)任務(wù),那么節(jié)點(diǎn)只能訪問(wèn)(加密的)秘密。當(dāng)容器任務(wù)停止運(yùn)行時(shí),共享給它的解密秘密將從該容器的內(nèi)存中文件系統(tǒng)卸載,并從節(jié)點(diǎn)的內(nèi)存刷新。
如果節(jié)點(diǎn)在運(yùn)行可訪問(wèn)秘密的任務(wù)容器時(shí)失去與群集的連接,則任務(wù)容器仍可訪問(wèn)其秘密,但在節(jié)點(diǎn)重新連接群集之前無(wú)法接收更新。
您可以隨時(shí)添加或檢查個(gè)人密碼,或列出所有密碼。您無(wú)法刪除正在運(yùn)行的服務(wù)正在使用的秘密。請(qǐng)參閱旋轉(zhuǎn)秘密以在不中斷正在運(yùn)行的服務(wù)的情況下移除秘密。
為了更容易地更新或回滾秘密,請(qǐng)考慮在秘密名稱中添加版本號(hào)或日期。通過(guò)控制給定容器內(nèi)秘密的安裝點(diǎn)的能力使這變得更容易。
docker secret
命令的信息使用這些鏈接閱讀有關(guān)特定命令的內(nèi)容,或繼續(xù)關(guān)于在服務(wù)中使用秘密的示例。
docker secret create
docker secret inspect
docker secret ls
docker secret rm
--secret
標(biāo)志為 docker service create
--secret-add
和--secret-rm
標(biāo)志docker service update
本節(jié)包含三個(gè)演示如何使用Docker機(jī)密的畢業(yè)示例。這些示例中使用的圖像已更新,以便于使用Docker機(jī)密。要了解如何以類似的方式修改自己的圖像,請(qǐng)參閱將Docker機(jī)密支持構(gòu)建到圖像中。
注意:為簡(jiǎn)單起見(jiàn),這些示例使用單引擎群和非標(biāo)度服務(wù)。這些示例使用Linux容器,但Windows容器也支持Docker 17.06和更高版本中的秘密。請(qǐng)參閱Windows支持。
這個(gè)簡(jiǎn)單的例子展示了秘密如何在幾個(gè)命令中工作。對(duì)于真實(shí)世界的例子,繼續(xù)到中級(jí)例子:使用Nginx服務(wù)的秘密。
給Docker添加一個(gè)秘密。該docker secret create
命令讀取標(biāo)準(zhǔn)輸入,因?yàn)樽詈笠粋€(gè)參數(shù)表示要讀取密鑰的文件設(shè)置為-
。$ echo "This is a secret" | docker secret create my_secret_data -
創(chuàng)建一個(gè)redis
服務(wù)并授予它訪問(wèn)該秘密的權(quán)限。默認(rèn)情況下,容器可以訪問(wèn)該密碼/run/secrets/<secret_name>
,但您可以使用該target
選項(xiàng)自定義容器上的文件名。$ docker service create --name redis --secret my_secret_data redis:alpine
驗(yàn)證任務(wù)是否正在運(yùn)行,且沒(méi)有事務(wù)在使用docker service ps
。如果一切正常,輸出如下所示:$ docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS bkna6bpn8r1a redis.1 redis:alpine ip-172-31-46-109 Running Running 8 seconds agoIf there were an error, and the task were failing and repeatedly restarting, you would see something like this: $ docker service ps redis NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS redis.1.siftice35gla redis:alpine moby Running Running 4 seconds ago \ redis.1.whum5b7gu13e redis:alpine moby Shutdown Failed 20 seconds ago "task: non-zero exit (1)" \ redis.1.2s6yorvd9zow redis:alpine moby Shutdown Failed 56 seconds ago "task: non-zero exit (1)" \ redis.1.ulfzrcyaf6pg redis:alpine moby Shutdown Failed about a minute ago "task: non-zero exit (1)" \ redis.1.wrny5v4xyps6 redis:alpine moby Shutdown Failed 2 minutes ago "task: non-zero exit (1)"
獲取redis
使用的服務(wù)任務(wù)容器的ID docker ps
,以便您可以使用docker exec
連接到容器并讀取秘密數(shù)據(jù)文件的內(nèi)容,該內(nèi)容默認(rèn)為全部可讀,并且與秘密的名稱相同。下面的第一條命令說(shuō)明了如何找到容器ID,第二個(gè)和第三個(gè)命令使用shell完成來(lái)自動(dòng)執(zhí)行此操作。$ docker ps --filter name=redis -q 5cb1c2348a59 $ docker exec $(docker ps --filter name=redis -q) ls -l /run/secrets total 4 -r--r--r-- 1 root root 17 Dec 13 22:48 my_secret_data $ docker exec $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data This is a secret
驗(yàn)證如果您提交容器,秘密不可用。$ docker commit $(docker ps --filter name=redis -q) committed_redis $ docker run --rm -it committed_redis cat /run/secrets/my_secret_data cat: can't open '/run/secrets/my_secret_data': No such file or directory
嘗試刪除秘密。刪除失敗,因?yàn)樵?code>redis服務(wù)正在運(yùn)行并可以訪問(wèn)該秘密。$ docker secret ls ID NAME CREATED UPDATED wwwrxza8sxy025bas86593fqs my_secret_data 4 hours ago 4 hours ago $ docker secret rm my_secret_data Error response from daemon: rpc error: code = 3 desc = secret 'my_secret_data' is in use by the following service: redis
redis
通過(guò)更新服務(wù),從正在運(yùn)行的服務(wù)中移除對(duì)秘密的訪問(wèn)權(quán)限。$ docker service update --secret-rm my_secret_data redis
重復(fù)步驟3和4,驗(yàn)證該服務(wù)不再有權(quán)訪問(wèn)該秘密。容器ID將不同,因?yàn)樵?code>service update命令重新部署服務(wù)。$ docker exec -it $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data cat: can't open '/run/secrets/my_secret_data': No such file or directory
停止并刪除服務(wù),并從Docker中刪除密鑰。$ docker service rm redis $ docker secret rm my_secret_data
這是一個(gè)非常簡(jiǎn)單的例子,它展示了如何使用運(yùn)行在Microsoft Windows Server 2016上的Docker 17.06 EE或Microsoft Windows 10上的Docker for Mac 17.06上運(yùn)行的Microsoft IIS服務(wù)的秘密。這是一個(gè)理想的例子,它將網(wǎng)頁(yè)存儲(chǔ)在一個(gè)秘密中。
此示例假定您已安裝PowerShell。
將以下內(nèi)容保存到一個(gè)新文件中:index.html
<html> <head> <title> Hello Docker </ title> </ head> <body> <p> Hello Docker!您已經(jīng)部署了一個(gè)HTML頁(yè)面。</ p> </ body> </ html>
如果你還沒(méi)有這樣做,請(qǐng)初始化或加入群。PS> docker swarm init
將該index.html
文件保存為名為swarm的秘密homepage
。PS> docker secret創(chuàng)建主頁(yè)index.html
創(chuàng)建一個(gè)IIS服務(wù)并授予它對(duì)homepage
秘密的訪問(wèn)權(quán)限。PS> docker service create --name my-iis -p 8000:8000 --secret src = homepage,target =“\ inetpub \ wwwroot \ index.html”microsoft / iis:nanoserver 注意:技術(shù)上沒(méi)有理由使用機(jī)密對(duì)于這個(gè)例子。使用Docker 17.06或更高版本,configs更適合。這個(gè)例子僅用于說(shuō)明。
訪問(wèn)IIS服務(wù)http://localhost:8000/
。它應(yīng)該從第一步開(kāi)始提供HTML內(nèi)容。
刪除服務(wù)和秘密。PS> docker service rm my-iis PS> docker secret rm homepage PS> docker image remove secret-test
這個(gè)例子分為兩部分。第一部分是關(guān)于生成站點(diǎn)證書的內(nèi)容,并不直接涉及Docker機(jī)密,但是它建立了第二部分,在那里存儲(chǔ)和使用站點(diǎn)證書和Nginx配置作為秘密。
為您的站點(diǎn)生成根CA和TLS證書和密鑰。對(duì)于生產(chǎn)站點(diǎn),您可能希望使用服務(wù)Let’s Encrypt
來(lái)生成TLS證書和密鑰,但此示例使用命令行工具。這一步有點(diǎn)復(fù)雜,但只是一個(gè)設(shè)置步驟,以便您可以將某些內(nèi)容存儲(chǔ)為Docker的秘密。如果你想跳過(guò)這些子步驟,您可以使用我們的加密生成網(wǎng)站密鑰和證書,命名文件site.key
和site.crt
,并跳過(guò)配置Nginx的容器。
生成一個(gè)根密鑰。$ openssl genrsa -out“root-ca.key”4096
使用根密鑰生成CSR。$ openssl req \ -new -key "root-ca.key" \ -out "root-ca.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA'
配置根CA. 編輯一個(gè)名為的新文件root-ca.cnf
并將以下內(nèi)容粘貼到其中。這限制了根CA只能簽署葉證書而不能簽署中間CA. root_ca basicConstraints = critical,CA:TRUE,pathlen:1 keyUsage = critical, nonRepudiation, cRLSign, keyCertSign subjectKeyIdentifier=hash
簽署證書。$ openssl x509 -req -days 3650 -in“root-ca.csr”\ -signkey“root-ca.key”-sha256 -out“root-ca.crt”\ -extfile“root-ca.cnf”-extensions \ root_ca
生成站點(diǎn)密鑰。$ openssl genrsa -out“site.key”4096
生成站點(diǎn)證書并使用站點(diǎn)密鑰對(duì)其進(jìn)行簽名。$ openssl req -new -key“site.key”-out“site.csr”-sha256 \ -subj'/ C = US / ST = CA / L = San Francisco / O = Docker / CN = localhost'
配置站點(diǎn)證書。編輯一個(gè)名為site.cnf
的新文件并將以下內(nèi)容粘貼到其中。這限制了站點(diǎn)證書,因此它只能用于對(duì)服務(wù)器進(jìn)行身份驗(yàn)證,并且不能用于簽名證書。server authorityKeyIdentifier = keyid,issuer basicConstraints = critical,CA:FALSE extendedKeyUsage = serverAuth keyUsage = critical,digitalSignature,keyEncipherment subjectAltName = DNS:localhost,IP:127.0.0.1 subjectKeyIdentifier = hash
簽署網(wǎng)站證書。$ openssl x509 -req -days 750 -in "site.csr" -sha256 \ -CA "root-ca.crt" -CAkey "root-ca.key" -CAcreateserial \ -out "site.crt" -extfile "site.cnf" -extensions server
在site.csr
和site.cnf
文件不需要由Nginx的服務(wù),但你需要他們,如果你想生成一個(gè)新的站點(diǎn)證書。保護(hù)root-ca.key
文件。
生成一個(gè)非?;镜腘ginx配置,通過(guò)HTTPS提供靜態(tài)文件。TLS證書和密鑰將作為Docker機(jī)密存儲(chǔ),以便它們可以輕松旋轉(zhuǎn)。在當(dāng)前目錄中,site.conf
使用以下內(nèi)容創(chuàng)建一個(gè)新文件:server { listen 443 ssl; server_name localhost; ssl_certificate /run/secrets/site.crt; ssl_certificate_key /run/secrets/site.key; location / { root /usr/share/nginx/html; index index.html index.htm; } }
創(chuàng)建三個(gè)機(jī)密,代表密鑰,證書和密鑰 site.conf
。只要小于500 KB,您就可以將任何文件存儲(chǔ)為秘密文件。這使您可以將密鑰,證書和配置與將使用它們的服務(wù)分離。在每一個(gè)這些命令中,最后一個(gè)參數(shù)代表從主機(jī)文件系統(tǒng)讀取密鑰的文件路徑。在這些示例中,秘密名稱和文件名是相同的。$ docker secret create site.key site.key $ docker secret create site.crt site.crt $ docker secret create site.conf site.conf $ docker secret ls ID NAME CREATED UPDATED 2hvoi9mnnaof7olr3z5g3g7fp site.key 58 seconds ago 58 seconds ago aya1dh363719pkiuoldpter4b site.crt 24 seconds ago 24 seconds ago zoa5df26f7vpcoz42qf2csth8 site.conf 11 seconds ago 11 seconds ago
創(chuàng)建一個(gè)運(yùn)行Nginx并可以訪問(wèn)這三個(gè)秘密的服務(wù)。 docker service create命令的最后一部分創(chuàng)建一個(gè)從site.conf秘密位置到/etc/nginx.conf.d/的符號(hào)鏈接,其中Nginx會(huì)查找額外的配置文件。 這一步發(fā)生在Nginx實(shí)際啟動(dòng)之前,因此如果您更改Nginx配置,則不需要重新生成映像。
注意:通常您會(huì)創(chuàng)建一個(gè)Dockerfile,將site.conf復(fù)制到適當(dāng)位置,構(gòu)建映像并使用自定義映像運(yùn)行容器。 此示例不需要自定義圖像。 它將site.conf放置到位,并且一步到位運(yùn)行容器。
在Docker 17.05及更早版本中,機(jī)密總是位于/run/secrets/
目錄中。Docker 17.06及更高版本允許您為容器中的秘密指定自定義位置。下面的兩個(gè)例子說(shuō)明了它們的區(qū)別。該命令的較早版本要求您創(chuàng)建一個(gè)到site.conf
文件的真實(shí)位置的符號(hào)鏈接,以便Nginx可以讀取它,但是較新的版本不需要這樣做。較舊的示例已保存,以便您可以看到差異。
- **Docker 17.06 and higher**: $ docker service create \ --name nginx \ --secret site.key \ --secret site.crt \ --secret source=site.conf,target=/etc/nginx/conf.d/site.conf \ --publish 3000:443 \ nginx:latest \ sh -c "exec nginx -g 'daemon off;'"
- **Docker 17.05 and earlier**: $ docker service create \ --name nginx \ --secret site.key \ --secret site.crt \ --secret site.conf \ --publish 3000:443 \ nginx:latest \ sh -c "ln -s /run/secrets/site.conf /etc/nginx/conf.d/site.conf && exec nginx -g 'daemon off;'"
第一個(gè)示例顯示秘密的短語(yǔ)和長(zhǎng)語(yǔ),而第二個(gè)示例僅顯示短語(yǔ)法。簡(jiǎn)短語(yǔ)法創(chuàng)建/run/secrets/
與機(jī)密具有相同名稱的文件。在正在運(yùn)行的容器中,現(xiàn)在存在以下三個(gè)文件:
- `/run/secrets/site.key`- `/run/secrets/site.crt`- `/etc/nginx/conf.d/site.conf` (or `/run/secrets/site.conf` if you used the second example)
驗(yàn)證Nginx服務(wù)正在運(yùn)行。$ docker service ls ID NAME MODE REPLICAS IMAGE zeskcec62q24 nginx replicated 1/1 nginx:latest $ docker service ps nginx NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS nginx.1.9ls3yo9ugcls nginx:latest moby Running Running 3 minutes ago
驗(yàn)證服務(wù)是否可操作:您可以訪問(wèn)Nginx服務(wù)器,并且正在使用正確的TLS證書。$ curl --cacert root-ca.crt https://localhost:3000 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> $ openssl s_client -connect localhost:3000 -CAfile root-ca.crt CONNECTED(00000003) depth=1 /C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA verify return:1 depth=0 /C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost verify return:1 --- Certificate chain 0 s:/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost i:/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA --- Server certificate -----BEGIN CERTIFICATE----- … -----END CERTIFICATE----- subject=/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost issuer=/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA --- No client certificate CA names sent --- SSL handshake has read 1663 bytes and written 712 bytes --- New, TLSv1/SSLv3, Cipher is AES256-SHA Server public key is 4096 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : AES256-SHA Session-ID: A1A8BF35549C5715648A12FD7B7E3D861539316B03440187D9DA6C2E48822853 Session-ID-ctx: Master-Key: F39D1B12274BA16D3A906F390A61438221E381952E9E1E05D3DD784F0135FB81353DA38C6D5C021CB926E844DFC49FC4 Key-Arg : None Start Time: 1481685096 Timeout : 300 (sec) Verify return code: 0 (ok)
運(yùn)行此示例后要清理,請(qǐng)刪除nginx
服務(wù)和存儲(chǔ)的機(jī)密。$ docker service rm nginx $ docker secret rm site.crt site.key site.conf
在本例中,您使用自定義root密碼創(chuàng)建單節(jié)點(diǎn)MySQL服務(wù),將憑證添加為秘密,并創(chuàng)建使用這些憑證連接到MySQL的單節(jié)點(diǎn)WordPress服務(wù)。下一個(gè)示例基于這個(gè)示例,向您展示如何旋轉(zhuǎn)MySQL密碼并更新服務(wù),以便WordPress服務(wù)仍然可以連接到MySQL。
此示例說(shuō)明了一些使用Docker機(jī)密的技巧,以避免將敏感憑證保存在映像中或直接在命令行上傳遞它們。
注意:為簡(jiǎn)單起見(jiàn),此示例使用單引擎群,并使用單節(jié)點(diǎn)MySQL服務(wù),因?yàn)閱蝹€(gè)MySQL服務(wù)器實(shí)例無(wú)法通過(guò)簡(jiǎn)單地使用復(fù)制服務(wù)來(lái)擴(kuò)展,并且設(shè)置MySQL群集超出了本示例的范圍。另外,更改MySQL根密碼并不像更改磁盤上的文件那么簡(jiǎn)單。您必須使用查詢或
mysqladmin
命令來(lái)更改MySQL中的密碼。
為MySQL生成一個(gè)隨機(jī)的字母數(shù)字密碼,并mysql_password
使用該docker secret create
命令將其作為Docker機(jī)密存儲(chǔ)。要使密碼更短或更長(zhǎng),請(qǐng)調(diào)整該openssl
命令的最后一個(gè)參數(shù)。這只是創(chuàng)建相對(duì)隨機(jī)密碼的一種方式。如果您選擇,您可以使用其他命令來(lái)生成密碼。 注意:創(chuàng)建秘密后,您無(wú)法更新它。您只能刪除并重新創(chuàng)建它,并且無(wú)法刪除服務(wù)正在使用的秘密。但是,您可以使用授予或撤銷正在運(yùn)行的服務(wù)對(duì)秘密的訪問(wèn)權(quán)限docker service update
。如果您需要更新密碼的功能,請(qǐng)考慮在密碼名稱中添加一個(gè)版本組件,以便稍后添加新版本,更新服務(wù)以使用它,然后刪除舊版本。
最后一個(gè)參數(shù)設(shè)置為-
,表示輸入是從標(biāo)準(zhǔn)輸入讀取的。
$ openssl rand -base64 20 | docker secret create mysql_password - l1vinzevzhj4goakjap5ya409
返回的值不是密碼,而是密碼的ID。在本教程的其余部分中,ID輸出被省略。
為MySQL root
用戶生成第二個(gè)秘密。此秘密不會(huì)與稍后創(chuàng)建的WordPress服務(wù)共享。它只需要引導(dǎo)mysql
服務(wù)。
$ openssl rand -base64 20 | docker secret create mysql_root_password -
列出由Docker管理的秘密docker secret ls
:
$ docker secret ls ID NAME CREATED UPDATED l1vinzevzhj4goakjap5ya409 mysql_password 41 seconds ago 41 seconds ago yvsczlx9votfw3l0nz5rlidig mysql_root_password 12 seconds ago 12 seconds ago
秘密存儲(chǔ)在群集的加密的Raft日志中。
創(chuàng)建用于MySQL和WordPress服務(wù)之間通信的用戶定義覆蓋網(wǎng)絡(luò)。不需要將MySQL服務(wù)公開(kāi)給任何外部主機(jī)或容器。$ docker network create -d overlay mysql_private
創(chuàng)建MySQL服務(wù)。MySQL服務(wù)將具有以下特征:
- Because the scale is set to `1`, only a single MySQL task runs. Load-balancing MySQL is left as an exercise to the reader and involves more than just scaling the service.- Only reachable by other containers on the `mysql_private` network.- Uses the volume `mydata` to store the MySQL data, so that it persists across restarts to the `mysql` service.- The secrets are each mounted in a `tmpfs` filesystem at `/run/secrets/mysql_password` and `/run/secrets/mysql_root_password`. They are never exposed as environment variables, nor can they be committed to an image if the `docker commit` command is run. The `mysql_password` secret is the one used by the non-privileged WordPress container to connect to MySQL.- Sets the environment variables `MYSQL_PASSWORD_FILE` and `MYSQL_ROOT_PASSWORD_FILE` to point to the files `/run/secrets/mysql_password` and `/run/secrets/mysql_root_password`. The `mysql` image reads the password strings from those files when initializing the system database for the first time. Afterward, the passwords are stored in the MySQL system database itself.- Sets environment variables `MYSQL_USER` and `MYSQL_DATABASE`. A new database called `wordpress` is created when the container starts, and the `wordpress` user will have full permissions for this database only. This user will not be able to create or drop databases or change the MySQL configuration. $ docker service create \ --name mysql \ --replicas 1 \ --network mysql_private \ --mount type=volume,source=mydata,destination=/var/lib/mysql \ --secret source=mysql_root_password,target=mysql_root_password \ --secret source=mysql_password,target=mysql_password \ -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \ -e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \ -e MYSQL_USER="wordpress" \ -e MYSQL_DATABASE="wordpress" \ mysql:latest
驗(yàn)證mysql
容器是否正在使用該docker service ls
命令運(yùn)行。$ docker service ls ID NAME MODE REPLICAS IMAGE wvnh0siktqr3 mysql replicated 1/1 mysql:latest 在這一點(diǎn)上,你實(shí)際上可以撤銷該mysql
服務(wù)對(duì)訪問(wèn)mysql_password
和mysql_root_password
秘密,因?yàn)槊艽a已被保存在MySQL系統(tǒng)數(shù)據(jù)庫(kù)?,F(xiàn)在不要這樣做,因?yàn)樯院笪覀儠?huì)使用它們來(lái)方便旋轉(zhuǎn)MySQL密碼。
現(xiàn)在MySQL已經(jīng)建立,創(chuàng)建一個(gè)連接到MySQL服務(wù)的WordPress服務(wù)。WordPress服務(wù)具有以下特點(diǎn):
- Because the scale is set to `1`, only a single WordPress task runs. Load-balancing WordPress is left as an exercise to the reader, because of limitations with storing WordPress session data on the container filesystem.- Exposes WordPress on port 30000 of the host machine, so that you can access it from external hosts. You can expose port 80 instead if you do not have a web server running on port 80 of the host machine.- Connects to the `mysql_private` network so it can communicate with the `mysql` container, and also publishes port 80 to port 30000 on all swarm nodes.- Has access to the `mysql_password` secret, but specifies a different target file name within the container. The WordPress container will use the mount point `/run/secrets/wp_db_password`. Also specifies that the secret is not group-or-world-readable, by setting the mode to `0400`.- Sets the environment variable `WORDPRESS_DB_PASSWORD_FILE` to the file path where the secret is mounted. The WordPress service will read the MySQL password string from that file and add it to the `wp-config.php` configuration file.- Connects to the MySQL container using the username `wordpress` and the password in `/run/secrets/wp_db_password` and creates the `wordpress` database if it does not yet exist.- Stores its data, such as themes and plugins, in a volume called `wpdata` so these files persist when the service restarts.
$ docker service create \ --name wordpress \ --replicas 1 \ --network mysql_private \ --publish 30000:80 \ --mount type=volume,source=wpdata,destination=/var/www/html \ --secret source=mysql_password,target=wp_db_password,mode=0400 \ -e WORDPRESS_DB_USER="wordpress" \ -e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password" \ -e WORDPRESS_DB_HOST="mysql:3306" \ -e WORDPRESS_DB_NAME="wordpress" \ wordpress:latest
驗(yàn)證服務(wù)正在使用docker service ls
和docker service ps
命令運(yùn)行。$ docker service ls ID NAME MODE REPLICAS IMAGE wvnh0siktqr3 mysql replicated 1/1 mysql:latest nzt5xzae4n62 wordpress replicated 1/1 wordpress:latest $ docker service ps wordpress ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS aukx6hgs9gwc wordpress.1 wordpress:latest moby Running Running 52 seconds ago 此時(shí),您實(shí)際上可以撤消WordPress服務(wù)對(duì)mysql_password
秘密的訪問(wèn),因?yàn)閃ordPress已將秘密復(fù)制到其配置文件中wp-config.php
。現(xiàn)在不要這樣做,因?yàn)槲覀兩院髸?huì)使用它來(lái)方便旋轉(zhuǎn)MySQL密碼。
http://localhost:30000/
從任何swarm節(jié)點(diǎn)訪問(wèn)并使用基于Web的向?qū)гO(shè)置WordPress。所有這些設(shè)置都存儲(chǔ)在MySQL wordpress
數(shù)據(jù)庫(kù)中。WordPress自動(dòng)為您的WordPress用戶生成密碼,這與WordPress用于訪問(wèn)MySQL的密碼完全不同。安全地存儲(chǔ)此密碼,例如在密碼管理器中。旋轉(zhuǎn)秘密后,您將需要它登錄WordPress。繼續(xù)撰寫一篇或兩篇博文,并安裝一個(gè)WordPress插件或主題,以驗(yàn)證WordPress是否完全正常運(yùn)行,并且在重新啟動(dòng)服務(wù)時(shí)保存其狀態(tài)。
如果您打算繼續(xù)下一個(gè)示例,演示如何旋轉(zhuǎn)MySQL根密碼,請(qǐng)不要清除任何服務(wù)或秘密。
這個(gè)例子建立在前一個(gè)例子上。在這種情況下,您使用新的MySQL密碼創(chuàng)建一個(gè)新密碼,更新mysql
和wordpress
使用它的服務(wù),然后刪除舊密碼。
注意:更改MySQL數(shù)據(jù)庫(kù)的密碼涉及運(yùn)行額外的查詢或命令,而不是僅僅更改單個(gè)環(huán)境變量或文件,因?yàn)槿绻麛?shù)據(jù)庫(kù)尚不存在,映像只設(shè)置MySQL密碼,并且MySQL存儲(chǔ)默認(rèn)情況下,MySQL數(shù)據(jù)庫(kù)中的密碼。輪換密碼或其他秘密可能涉及Docker之外的其他步驟。
創(chuàng)建新密碼并將其存儲(chǔ)為一個(gè)名為secret的密碼mysql_password_v2
。$ openssl rand -base64 20 | docker secret create mysql_password_v2 -
更新MySQL服務(wù),使其能夠訪問(wèn)舊的和新的秘密。請(qǐng)記住,您無(wú)法更新或重命名密鑰,但可以撤銷秘密并使用新的目標(biāo)文件名授予對(duì)其的訪問(wèn)權(quán)限。$ docker service update \ --secret-rm mysql_password mysql $ docker service update \ --secret-add source=mysql_password,target=old_mysql_password \ --secret-add source=mysql_password_v2,target=mysql_password \ mysql 更新服務(wù)會(huì)導(dǎo)致它重新啟動(dòng),并且當(dāng)MySQL服務(wù)第二次重新啟動(dòng)時(shí),它有權(quán)訪問(wèn)舊密鑰/run/secrets/old_mysql_password
和新密鑰/run/secrets/mysql_password
。盡管MySQL服務(wù)現(xiàn)在可以訪問(wèn)舊的和新的機(jī)密,但WordPress用戶的MySQL密碼尚未更改。 注意:這個(gè)例子不會(huì)旋轉(zhuǎn)MySQL root
密碼。
現(xiàn)在,wordpress
使用mysqladmin
CLI 更改用戶的MySQL密碼。該命令從文件中讀取舊密碼和新密碼,/run/secrets
但不在命令行上公開(kāi)它們或?qū)⑺鼈儽4嬖趕hell歷史記錄中。快速做到這一點(diǎn),并繼續(xù)下一步,因?yàn)閃ordPress將失去連接到MySQL的能力。首先,找到mysql
容器任務(wù)的ID 。$ docker ps --filter name = mysql -q c7705cf6176f 在下面的命令中替換ID,或者使用第二個(gè)使用shell擴(kuò)展的變體在一個(gè)步驟中完成所有操作。 $ docker exec <CONTAINER_ID> \ bash -c'mysqladmin --user = wordpress --password =“$(</ run / secrets / old_mysql_password)”password“$(</ run / secrets / mysql_password)” 或:$ docker exec $(docker ps --filter name = mysql -q)\ bash -c'mysqladmin --user = wordpress --password =“$(</ run / secrets / old_mysql_password)”password“$(<運(yùn)行/秘密/ mysql_password)“”
更新wordpress
服務(wù)以使用新密碼,保留目標(biāo)路徑/run/secrets/wp_db_secret
并保持文件權(quán)限0400
。這將觸發(fā)WordPress服務(wù)的滾動(dòng)重啟,并且將使用新的秘密。$ docker service update \ --secret-rm mysql_password \ --secret-add source = mysql_password_v2,target = wp_db_password,mode = 0400 \ wordpress \ wordpress
通過(guò)再次瀏覽任何swarm節(jié)點(diǎn)上的http:// localhost:30000 /來(lái)驗(yàn)證WordPress是否工作正常。您需要使用在上一個(gè)任務(wù)中通過(guò)WordPress向?qū)r(shí)使用的WordPress用戶名和密碼。驗(yàn)證您寫的博文是否仍然存在,如果您更改了任何配置值,請(qǐng)確認(rèn)它們?nèi)匀话l(fā)生更改。
撤消對(duì)MySQL服務(wù)的舊密鑰的訪問(wèn)權(quán)限,并從Docker中刪除舊密鑰。$ docker service update \ --secret-rm mysql_password \ mysql $ docker secret rm mysql_password
如果您想要再次運(yùn)行所有這些示例,或者只是想在運(yùn)行完所有示例后進(jìn)行清理,請(qǐng)使用這些命令來(lái)刪除WordPress服務(wù),MySQL容器,mydata和wpdata卷以及Docker機(jī)密。$ docker service rm wordpress mysql $ docker volume rm mydata wpdata $ docker secret rm mysql_password_v2 mysql_root_password
如果您開(kāi)發(fā)的容器可以作為服務(wù)進(jìn)行部署,并且需要敏感數(shù)據(jù)(如憑證)作為環(huán)境變量,那么可以考慮調(diào)整圖像以充分利用Docker機(jī)密。一種方法是確保在創(chuàng)建容器時(shí)傳遞給圖像的每個(gè)參數(shù)也可以從文件中讀取。
Docker庫(kù)中的許多官方圖像,例如上面示例中使用的wordpress圖像,都以這種方式進(jìn)行了更新。
當(dāng)你啟動(dòng)一個(gè)WordPress容器時(shí),通過(guò)將它們?cè)O(shè)置為環(huán)境變量來(lái)提供它所需的參數(shù)。WordPress圖片已經(jīng)更新,因此包含WordPress重要數(shù)據(jù)的環(huán)境變量(如WORDPRESS_DB_PASSWORD
變量)也可以從文件(WORDPRESS_DB_PASSWORD_FILE
)中讀取它們的值。這種策略可確保向后兼容性得到保留,同時(shí)允許容器從Docker管理的秘密中讀取信息,而不是直接傳遞。
注意:Docker機(jī)密不會(huì)直接設(shè)置環(huán)境變量。這是一個(gè)有意識(shí)的決定,因?yàn)榄h(huán)境變量可能會(huì)無(wú)意中泄漏到容器之間(例如,使用
--link
)。
version: '3.1'services: db: image: mysql:latest volumes: - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD_FILE: /run/secrets/db_password secrets: - db_root_password - db_password wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password secrets: - db_password secrets: db_password: file: db_password.txt db_root_password: file: db_root_password.txt volumes: db_data:
本示例使用撰寫文件中的兩個(gè)秘密創(chuàng)建一個(gè)簡(jiǎn)單的WordPress網(wǎng)站。
關(guān)鍵字secrets:
定義了兩個(gè)秘密db_password:
和db_root_password:
。
部署時(shí),Docker將創(chuàng)建這兩個(gè)秘密,并使用撰寫文件中指定的文件中的內(nèi)容填充它們。
數(shù)據(jù)庫(kù)服務(wù)使用兩個(gè)秘密,并且wordpress使用一個(gè)。
在部署時(shí),Docker將/run/secrets/<secret_name>
在服務(wù)下安裝一個(gè)文件。這些文件永遠(yuǎn)不會(huì)保存在磁盤中,而是在內(nèi)存中進(jìn)行管理。
每個(gè)服務(wù)使用環(huán)境變量來(lái)指定服務(wù)應(yīng)該在哪里查找該秘密數(shù)據(jù)。
有關(guān)秘密短語(yǔ)和長(zhǎng)語(yǔ)法的更多信息可以在Compose文件版本3參考中找到。