docker swarm英文文档学习-10-使用Docker密钥管理敏感数据
Manage sensitive data with Docker secrets使用Docker secrets管理敏感数据
About secrets
对于Docker Swarm服务来说,secret是一组数据,比如密码、SSH私钥、SSL证书或其他不应该在网络上传输或存储在Dockerfile或应用程序源代码中未加密的数据。在Docker 1.13及更高版本中,可以使用Docker secrets集中管理该数据,并将其安全地传输到需要访问它的容器。Secrets在传输过程中和在Docker集群中被加密。给定的secret只对那些已被授予显式访问权限的服务可访问,并且仅在这些服务任务运行时可访问。
你可以使用secret来管理容器运行时需要但不希望存储在镜像或源代码控制中的任何敏感数据,例如:
- 用户名和密码
- TLS证书和密钥
- SSH密钥
- 其他重要数据,如数据库或内部服务器的名称
- 通用字符串或二进制内容(大小不超过500 kb)
注意:Docker的secrets只适用于集群服务,而不适用于独立容器。要使用此特性,请考虑将容器调整为作为服务运行。有状态容器通常可以在不更改容器代码的情况下以1的比例运行。
使用secrets的另一个用例是在容器和一组凭证之间提供一个抽象层。考虑这样一个场景:你的应用程序有独立的开发、测试和生产环境。这些环境中的每一个都可以具有不同的凭证,这些凭证存储在具有相同secret名称的开发、测试和生产集群中。容器只需要知道在所有三个环境中运行的secret的名称。
你还可以使用secret来管理非敏感数据,比如配置文件。但是,Docker 17.06和更高版本支持使用configs存储非敏感数据。配置直接挂载到容器的文件系统中,不需要使用RAM磁盘。
How Docker manages secrets Docker如何管理secrets
当你向群中添加一个secret时,Docker通过一个相互的TLS连接将该secret发送给群管理器。这个secret存储在raft子日志中,日志是加密的。整个raft日志被复制到其他管理器中,确保机密的高可用性保证与集群管理数据的其他部分相同。
警告:raft数据在Docker 1.13或更高版本中加密。如果你的任何集群管理器运行较早的版本,并且其中一个管理器成为集群的管理器,则secret将未加密地存储在该节点的raft日志中。在添加任何secret之前,请将所有管理器节点更新到Docker 1.13或更高版本,以防止将秘密写入纯文本raft日志。
当你授予新创建或正在运行的服务对secret的访问权限时,解密的secret将挂载到内存文件系统中的容器中。在Linux容器中,挂载点的位置默认为/run/secrets/<secret_name>,或者在Windows容器中默认为C: ProgramData\Docker\secrets。你可以在Docker 17.06或更高版本中指定自定义位置。
你可以更新服务以授予其对其他secret的访问权,或者随时撤销其对给定secret的访问权。
只有当节点是集群管理器或正在运行已被授予secret访问权的服务任务时,节点才能访问(加密的)secret。当容器任务停止运行时,共享给它的解密secret将从该容器的内存文件系统中卸载,并从节点的内存中刷新。
如果节点在运行具有secret访问权的任务容器时失去了与集群的连接,那么任务容器仍然可以访问其secret,但是在节点重新连接到集群之前不能接收更新。
你可以在任何时候添加或检查单个secret,或者列出所有secret。你无法删除正在运行的服务正在使用的secret。有关在不中断正在运行的服务的情况下删除secret的方法,请参见Rotate a secret。
为了更容易地更新或回滚secret,可以考虑在secret名称中添加版本号或日期。通过在给定容器中控制secret的挂载点,可以更容易地做到这一点。
Read more about docker secret
commands更多有关docker secret
命令的信息
使用这些链接可以阅读有关特定命令的信息,或者继续阅读example about using secrets with a service。
docker secret create
docker secret inspect
docker secret ls
docker secret rm
--secret
flag fordocker service create
--secret-add
and--secret-rm
flags fordocker service update
Examples
本节包括三个分级示例,演示如何使用Docker secrets。这些示例中使用的镜像已经进行了更新,以便更容易地使用Docker secrets。要了解如何以类似的方式修改自己的镜像,请参见Build support for Docker Secrets into your images。
注意:为了简单起见,这些示例使用单引擎集群和未扩展的服务。示例使用Linux容器,但Windows容器也支持Docker 17.06及更高版本中的secrets。看Windows support.
Defining and using secrets in compose files在compose文件中定义并使用secrets
docker-compose
和
docker stack命令支持在compose文件中定义secrets。详情看the Compose file reference
Simple example: Get started with secrets 开始
这个简单的例子展示了secrets是如何在几个命令中工作的。对于真实的示例,请继续Intermediate example: Use secrets with a Nginx service.。
1.向Docker添加一个secrets。docker secret create命令读取标准输入,因为最后一个参数,表示从中读取秘密的文件被设置为-。
$ printf "This is a secret" | docker secret create my_secret_data -
2.创建一个redis服务,并授予它访问secret的权限。默认情况下,容器可以访问/run/secrets/上的secret,但是可以使用target选项定制容器上的文件名。
$ docker service create --name redis --secret my_secret_data redis:alpine
3.使用docker service ps检查任务是否正常运行。如果一切正常,输出如下:
$ docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
bkna6bpn8r1a redis. redis:alpine ip---- Running Running seconds ago
如果出现错误,并且任务失败并多次重新启动,你将看到如下内容:
$ docker service ps redis NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
redis..siftice35gla redis:alpine moby Running Running seconds ago
\_ redis..whum5b7gu13e redis:alpine moby Shutdown Failed seconds ago "task: non-zero exit (1)"
\_ redis..2s6yorvd9zow redis:alpine moby Shutdown Failed seconds ago "task: non-zero exit (1)"
\_ redis..ulfzrcyaf6pg redis:alpine moby Shutdown Failed about a minute ago "task: non-zero exit (1)"
\_ redis..wrny5v4xyps6 redis:alpine moby Shutdown Failed minutes ago "task: non-zero exit (1)"
4.使用docker ps命令得到redis的服务任务容器的ID,这样你可以使用docker container exec去连接到容器和阅读的secret数据文件的内容,其默认为所有人可读,并且有着和secret的名称相同的名称。下面的第一个命令演示了如何查找容器ID,第二个和第三个命令使用shell补全来自动查找容器ID。
$ docker ps --filter name=redis -q 5cb1c2348a59 $ docker container exec $(docker ps --filter name=redis -q) ls -l /run/secrets total
-r--r--r-- root root Dec : my_secret_data $ docker container exec $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data This is a secret
5.如果提交容器,请验证该secret不可用。
$ 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
6.移除这个secret。删除失败是因为redis服务正在运行,并且可以访问该secret。
$ docker secret ls ID NAME CREATED UPDATED
wwwrxza8sxy025bas86593fqs my_secret_data hours ago hours ago $ docker secret rm my_secret_data Error response from daemon: rpc error: code = desc = secret
'my_secret_data' is in use by the following service: redis
7.通过更新服务,从正在运行的redis服务中删除对该secret的访问。
$ docker service update --secret-rm my_secret_data redis
8.再次重复步骤3和步骤4,验证服务不再具有访问secret的权限。容器ID是不同的,因为service update命令重新部署服务。
$ docker container 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
9.停止并删除服务,并从Docker中删除秘密。
$ docker service rm redis $ docker secret rm my_secret_data
Intermediate example: Use secrets with a Nginx service
本例分为两部分。第一部分是关于生成站点证书的,完全不直接涉及Docker secret,但是它设置了第二部分,在其中存储和使用站点证书和Nginx配置作为secret。
GENERATE THE SITE CERTIFICATE生成站点证书
为你的站点生成根CA和TLS证书和密钥。对于生产站点,你可能希望使用Let’s Encrypt之类的服务来生成TLS证书和密钥,但是本示例使用命令行工具。这一步有点复杂,但只是一个设置步骤,以便你可以将某些内容存储为Docker secret。如果你想跳过这些子步骤,可以使用Let 's Encrypt生成站点密钥和证书,命名文件site.key
和
site.crt
,然后跳到 Configure the Nginx container
1.生成一个根密钥:
$ openssl genrsa -out "root-ca.key"
2.使用根密钥生成一个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'
3.配置根CA.编辑一个名为root-ca.cnf的新文件,并将以下内容粘贴到其中。这限制根CA只签名叶证书,而不签名中间CA。
[root_ca]
basicConstraints = critical,CA:TRUE,pathlen:1
keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
subjectKeyIdentifier=hash
4.签名证书
$ 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
5.生成站点密钥
$ openssl genrsa -out "site.key"
6.生成站点证书并使用站点密钥签名
$ openssl req -new -key "site.key" -out "site.csr" -sha256 \
-subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
7.配置站点证书。编辑一个名为site.cnf的新文件,并将以下内容粘贴到其中。这限制了站点证书,因此它只能用于对服务器进行身份验证,而不能用于对证书进行签名。
[server]
authorityKeyIdentifier=keyid,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage=serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
subjectAltName = DNS:localhost, IP:127.0.0.1
subjectKeyIdentifier=hash
8.对站点证书签名
$ 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
9.site.csr
和site.cnf
文件不被Nginx服务需要,但是如果你想生成一个新的站点证书,则需要它们。保护root-ca.key文件。
CONFIGURE THE NGINX CONTAINER 配置Ngnix容器
1.生成一个非常基本的Nginx配置,它通过HTTPS提供静态文件。TLS证书和密钥存储为Docker密钥,这样可以方便地轮转它们。
在当前目录中,创建一个带着下面内容的名为site.conf的新文件
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;
}
}
2.创建两个秘密,分别表示密钥和证书。你可以将任何文件作为秘密存储,只要它小于500kb。这允许你将密钥和证书与使用它们的服务解耦。在这些示例中,密钥名称和文件名是相同的。
$ 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 seconds ago seconds ago
aya1dh363719pkiuoldpter4b site.crt seconds ago seconds ago
zoa5df26f7vpcoz42qf2csth8 site.conf seconds ago seconds ago
3.创建一个运行Nginx并可以访问这三个secret的服务。docker service create
命令的最后一部分从site.conf secret的位置创建一个符号链接到/etc/nginx.conf,其中Nginx查找额外的配置文件。这个步骤发生在Nginx实际启动之前,所以如果你更改了Nginx配置,就不需要重新构建镜像。
注意:通常你会创建一个复制site.conf到位置的Dockerfile,构建镜像,并使用自定义镜像运行容器。本例不需要自定义镜像。它把site.conf放到位置上,并在一步内运行容器。
在Docker 17.05和更早的版本中,secret总是位于/run/secrets/目录中。Docker 17.06及更高版本允许你为容器中的secret指定自定义位置。下面的两个例子说明了不同之处。这个命令的旧版本要求你创建指向site.conf真实位置的符号链接,以便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 published=,target= \
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 published=,target= \
nginx:latest \
sh -c "ln -s /run/secrets/site.conf /etc/nginx/conf.d/site.conf && exec nginx -g 'daemon off;'"
第一个示例同时显示了secret的短语法和长语法,第二个示例只显示了短语法。这个简短的语法在/run/secrets/中创建与secret同名的文件。在运行的容器中,现在存在以下三个文件:
/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)
4.查看Nginx服务是否正在运行
$ docker service ls ID NAME MODE REPLICAS IMAGE
zeskcec62q24 nginx replicated / nginx:latest $ docker service ps nginx NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
nginx..9ls3yo9ugcls nginx:latest moby Running Running minutes ago
5.核查服务是可操作的:你可以到达Ngnix服务端,并且正确的TLS证书正在被使用
$ curl --cacert root-ca.crt https://localhost:3000 <!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 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. 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: -CAfile root-ca.crt CONNECTED()
depth= /C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA
verify return:
depth= /C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost
verify return:
---
Certificate chain
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 bytes and written bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 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:
Timeout : (sec)
Verify return code: (ok)
6.在运行此示例之后,请通过删除nginx服务以及存储的secrets来清理。
Build support for Docker Secrets into your images
如果你开发的容器可以部署为服务,并且需要敏感数据(例如凭据)作为环境变量,那么可以考虑调整镜像以利用Docker的secrets。一种方法是确保在创建容器时传递给镜像的每个参数也可以从文件中读取。
Docker库中的许多官方镜像,比如上面例子中使用的wordpress镜像,都是用这种方式更新的。
启动WordPress容器时,通过将其设置为环境变量,为其提供所需的参数。WordPress镜像已经更新,因此包含WordPress重要数据的环境变量,如WORDPRESS_DB_PASSWORD,也有可以从文件(WORDPRESS_DB_PASSWORD_FILE)读取其值的变量。这种策略确保了向后兼容性,同时允许容器从docker管理的secret中读取信息,而不是直接传递。
注意:Docker secrets不直接设置环境变量。这是一个有意识的决定,因为环境变量可能在容器之间无意地泄漏(例如,如果使用--link)。
Use Secrets in Compose
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:
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:
这个例子使用一个compose文件中的两个secrets创建了一个简单的WordPress站点。
关键字secrets:定义两个secret db_password:和db_root_password:。
在部署时,Docker将创建这两个secrets,并用组成文件中指定的文件中的内容填充它们。
db服务同时使用这两个secrets,wordpress也在使用一个。
在部署时,Docker在服务中挂载/run/secrets/<secret_name>下的文件。</secret_name>这些文件从不保存在磁盘中,而是在内存中管理。
每个服务使用环境变量来指定服务应该在何处查找该secret数据。
有关secrets的短语法和长语法的更多信息,请参阅Compose file version 3 reference。
docker swarm英文文档学习-10-使用Docker密钥管理敏感数据的更多相关文章
- docker swarm英文文档学习-9-使用Docker Configs存储配置数据
Store configuration data using Docker Configs 使用Docker Configs存储配置数据 Docker 17.06引入了集群服务配置,允许你在服务镜像或 ...
- docker swarm英文文档学习-3-开始
https://docs.docker.com/engine/swarm/swarm-tutorial/ 1)Getting started with swarm mode 本教程向你介绍Docker ...
- docker swarm英文文档学习-8-在集群中部署服务
Deploy services to a swarm在集群中部署服务 集群服务使用声明式模型,这意味着你需要定义服务的所需状态,并依赖Docker来维护该状态.该状态包括以下信息(但不限于): 应该运 ...
- docker swarm英文文档学习-5-在swarm模式中运行Docker引擎
Run Docker Engine in swarm mode在swarm模式中运行Docker引擎 当你第一次安装并开始使用Docker引擎时,默认情况下禁用swarm模式.在启用集群模式时,需要处 ...
- docker swarm英文文档学习-1-概述
参考https://docs.docker.com/engine/swarm/ Swarm mode overview群模式概述 Docker的当前版本包括集群模式,用于本地管理称为集群的Docker ...
- docker swarm英文文档学习-11-上锁你的集群来保护你的加密密钥
Lock your swarm to protect its encryption key上锁你的集群来保护你的加密密钥 在Docker 1.13及更高版本中,默认情况下,群管理器使用的Raft日志在 ...
- docker swarm英文文档学习-12-在集群模式中的Raft共识
Raft consensus in swarm mode 在集群模式中的Raft共识 当Docker引擎在集群模式下运行时,manager节点实现Raft 共识算法来管理全局集群状态.Docker s ...
- docker swarm英文文档学习-6-添加节点到集群
Join nodes to a swarm添加节点到集群 当你第一次创建集群时,你将单个Docker引擎置于集群模式中.为了充分利用群体模式,可以在集群中添加节点: 添加工作节点可以增加容量.当你将服 ...
- docker swarm英文文档学习-7-在集群中管理节点
Manage nodes in a swarm在集群中管理节点 List nodes列举节点 为了查看集群中的节点列表,可以在管理节点中运行docker node ls: $ docker node ...
随机推荐
- [javaSE] 看博客学习多线程的创建方式和优劣比较和PHP多线程
通过实现Runnable接口创建线程 获取Thread对象,new出来,构造函数参数:Runnable对象 Runnable是一个接口,定义一个类MyRunnable实现Runnable接口,实现ru ...
- Spring Data Redis —— 快速入门
环境要求:Redis 2.6及以上,javase 8.0及以上: 一.Spring Data Redis 介绍 Spring-data-redis是spring的一部分,提供了在srping应用中通过 ...
- python+redis简单实现发红包程序
redis是什么? Redis 是一个高性能的key-value数据库! 想进一步了解请移步搜索引擎自行查找. 编写这个小程序的目的就是对redis进行一个简单的小操作,对redis有一个初步的了解, ...
- Unexpected directive 'XXX' imported by the module 'AppMoode'
做angular demo报错: Uncaught Error: Unexpected directive 'ScrollSpyDirective' imported by the module 'A ...
- css3 content 特殊字符和符号
基本形状 ▲ 9650 25B2 ► 9658 25BA ► 9658 25BA ▼ 9660 25BC◄ 9668 25C4 ❤ 10084 2764 ✈ 9992 2708 ★ 9733 2605 ...
- chrome-Firefox-IE浏览器兼容总结
作为一名WEB前端程序员,相信每个人对浏览器的兼容都"情有独钟",下面就一些常用的浏览器的兼容列举一二. 一.块级元素(block)一般不转化为inline-block,其实是因为 ...
- struts2、ajax实现前后端交互
跳过struts2环境搭建部分,或者可以看我的博客(http://www.cnblogs.com/zhangky/p/8436472.html),里面有写,很详细. 需要导入的jar包(struts官 ...
- SD配置步骤清单
定义销售组织 定义分销渠道 定义产品组 给公司代码分配销售组织 给销售组织分配销售渠道 给工厂分配销售组织.分销渠道 给销售组织分配产品组 定义销售范围 定义装运点 给工厂分配装运点 维护工厂的装运点 ...
- 准备开发一个运行在Android上的JavaME模拟器
在一个虚拟机A上运行另外一个虚拟机B看起来是挺不靠谱的一件事,在手机上运行某个虚拟机也不怎么靠谱.并且如果虚拟机A运行在手机上这个听起来就更不靠谱了.但是很多人就在做这样的事.比如在在手机上运行DOS ...
- 成为Java顶尖程序员,先过了下面问题!
一.数据结构与算法基础 说一下几种常见的排序算法和分别的复杂度. 用Java写一个冒泡排序算法 描述一下链式存储结构. 如何遍历一棵二叉树? 倒排一个LinkedList. 用Java写一个递归遍历目 ...