docker

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 云和虚拟化 > docker > Docker secret管理数据

docker-swarm之使用Docker secret管理敏感数据

作者:demo007x

就Docker Swarm集群服务而言,secret 是块状数据,例如密码、SSH私钥、SSL证书或其他不应通过网络传输或未加密存储在Dockerfile或应用程序源代码中的数据,我们可以使用Docker secret 集中管理这些数据,所以接下来就带大家了解一下如何使用Docker secret 管理敏感数据

关于secret

就Docker Swarm集群服务而言,secret 是块状数据,例如密码、SSH私钥、SSL证书或其他不应通过网络传输或未加密存储在Dockerfile或应用程序源代码中的数据。我们可以使用Docker secret 集中管理这些数据,并仅将其安全地传输到需要访问它的容器。在传输过程中被加密,并在Docker集群中保存。只有那些已获准明确访问它的服务才能访问给定 secret ,并且只有在这些服务任务正在运行时才能访问。

您可以使用secret 来管理容器在运行时需要的任何敏感数据。比如一下情况:

注意:Docker secret 仅适用于集群服务,不适用于独立的容器。要使用此功能,请考虑调整您的容器作为服务运行。有状态容器通常可以在不更改容器代码的情况下以1的比例运行。

使用secret 的另一个用例是在容器和一组凭据之间提供一层抽象。考虑一个场景,即您的应用程序有单独的开发、测试和生产环境。这些环境中的每一个都可以有不同的凭据,存储在具有相同secret 名称的开发、测试和生产群中。您的容器只需要知道secret 的名称,即可在所有三个环境中运行。

您还可以使用secret 来管理非敏感数据,例如配置文件。然而,Docker支持使用配置来存储非敏感数据。配置直接挂载到容器的文件系统中,而无需使用RAM磁盘。

对 Windows 支持

Docker 包括对Windows容器上secret 的支持。如果实现方面存在差异。有以下几方面的差异,在下面的示例中说明:

Docker如何管理secret

当您向集群中添加secret 时,Docker会通过相互的TLS连接将secret 发送给群管理器。secret 存储在Raft日志中,该日志是加密的。整个 Raft 日志在其他管理节点之间复制,确保了与其他蜂群管理数据相同的高可用性保证。

当您授予新创建或正在运行的服务对密钥的访问权限时,解密的密钥将安装在内存文件系统中的容器中。容器中挂载点的位置默认为Linux 容器中的/run/secrets/<secret_name>,或 Windows容器中的C:\ProgramData\Docker\secrets。您还可以指定自定义位置。

您可以随时更新服务,以授予其访问其他 secret 或撤销其对给定secret 的访问。

只有当节点是集群管理器或正在运行已获准访问secret 的服务任务时,节点才能访问(加密)secret 。当容器任务停止运行时,共享到它的解密机密将从该容器的内存文件系统中卸载,并从节点的内存中刷新。

如果节点在运行具有 secret 访问权限的任务容器时失去与群的连接,则任务容器仍然可以访问其 secret ,但在节点重新连接到群之前无法接收更新。

您可以随时添加或检查单个 secret ,或列出所有 secret 。您无法删除正在运行的服务正在使用的 secret

要更轻松地更新或回滚 secret ,请考虑在secret 名称中添加版本号或日期。控制给定容器中secret 的安装点的能力使这变得更容易。

docker secret 命令

示例

我们使用以下示例渐进的说明如何使用Docker secret 。这些示例中使用的镜像已更新,以便于使用Docker secret 。

注意:为了简单起见,这些示例使用单引擎集群和未缩放服务。这些示例使用Linux容器,但Windows容器也支持secret 。

在编写文件中定义和使用secret

docker-composedocker stack命令都支持在编写文件中定义 secret

示例一:开始使用secret

这个简单的示例展示了secret 如何在几个命令中发挥作用。

 echo "This is a secret" | docker secret create my_secret_data -
root@master:~# echo "this is a demo secret" | docker secret create my-secret -
yy7gnh0ji9wm64fs841yej5kv
root@master:~# docker secret ls
ID                          NAME        DRIVER    CREATED         UPDATED
yy7gnh0ji9wm64fs841yej5kv   my-secret             5 seconds ago   5 seconds ago
root@master:~# 
 docker service  create --name redis --secret my_secret_data redis:alpine

如果出现错误,并且任务失败并反复重新启动,您将看到以下内容:

 docker service ps redis

使用docker ps获取redis服务任务容器的ID,以便您可以使用docker container exec连接到容器并读取secret 数据文件的内容,该文件默认为可被所有人读取,并且与secret 的名称相同。

使用一下命令获取 redis 容器服务的 ID

 docker ps --filter name=redis -q

查看容器中 secret 的内容:

 docker container exec $(docker ps --filter name=redis -q) ls -l /run/secrets
 docker container exec $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data
root@master:~# docker exec $(docker ps --filter name=redis -q) ls -l /run/secrets
total 4
-r--r--r--    1 root     root            22 Aug  5 08:09 my-secret
root@master:~# docker exec $(docker ps --filter name=redis -q) cat /run/secrets
cat: read error: Is a directory
root@master:~# docker exec $(docker ps --filter name=redis -q) cat /run/secrets/my-secret
this is a demo secret
root@master:~# 
$ 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
 docker secret ls
 docker secret rm my_secret_data
 docker service update --secret-rm my_secret redis
$ 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
 docker service rm redis
 docker secret rm my_secret

示例二:在Nginx服务中使用 secret

这个例子分为两部分。第一部分是关于生成站点证书,不直接涉及 Docker secret ,但它设置了我们可以在其中存储和使用站点证书和Nginx配置作为 secret

生成站点证书

为您的站点生成根CA和TLS证书和密钥。对于生产站点,您可能希望使用Let’s Encrypt等服务来生成TLS证书和密钥,但此示例使用命令行工具。这个步骤有点复杂,但只是一个设置步骤,这样您就有一些东西可以存储为Dockersecret 。如果您想跳过这些子步骤,您可以使用Let's Encrypt ② 生成站点密钥和证书,为文件命名site.keysite.crt

 openssl genrsa -out "root-ca.key" 4096
 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'
[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
 openssl genrsa -out "site.key" 4096
 openssl req -new -key "site.key" -out "site.csr" -sha256 \
          -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
[server]
authorityKeyIdentifier=keyid,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage=serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
subjectAltName = DNS:localhost, IP:127.0.0.1
subjectKeyIdentifier=hash
 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

配置Nginx容器

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;
    }
}
 docker secret create site.key site.key
 docker secret create site.crt site.crt
 docker secret create site.conf site.conf
 docker secret ls

创建一个运行Nginx并可以访问三个secret 的服务。docker service create命令的最后一部分从site.confsecret 的位置创建一个符号链接到/etc/nginx.conf.d/,Nginx在其中查找额外的配置文件。此步骤发生在Nginx实际启动之前,因此如果您更改Nginx配置,则无需重建映像。

注意:通常情况下,您将创建一个Dockerfile,将site.conf复制到位,构建映像,并使用自定义映像运行容器。此示例不需要自定义图像。它将site.conf放置到位,并在一个步骤中运行容器。

默认情况下,secret 位于容器中的/run/secrets/目录中,这可能需要在容器中采取额外的步骤才能使secret在不同的路径中可用。下面的示例创建了一个指向site.conf文件真实位置的符号链接,从而 Nginx 可以读取它:

 docker service create \
        --name nginx \
        --secret site.key \
        --secret site.crt \
        --secret site.conf \
        --publish published=3000,target=443 \
        nginx:latest \
        sh -c "ln -s /run/secrets/site.conf /etc/nginx/conf.d/site.conf && exec nginx -g 'daemon off;'"

secret 允许您使用target选项指定自定义位置,而不是创建符号链接。下面的示例说明了如何在不使用符号链接的情况下在容器内的/etc/nginx/conf.d/site.conf上提供thesitesite.confsecret :

docker service create \
     --name nginx \
  --secret site.key \
     --secret site.crt \
     --secret source=site.conf,target=/etc/nginx/conf.d/site.conf \
     --publish published=3000,target=443 \
     nginx:latest \
     sh -c "exec nginx -g 'daemon off;'"

site.keysite.crtsecret 使用速记语法,没有自定义target位置设置。简短的语法将secret 挂载在`/run/secrets/中,与secret 同名。在正在运行的容器中,现在存在以下三个文件:

 docker service ls
 docker service ps nginx
curl --cacert root-ca.crt https://localhost:3000
<title>Welcome to nginx!<</title>
<h1>Welcome to nginx!</h1>
If you see this page, the nginx web server is successfully installed and
For online documentation and support. refer to
<a>nginx.org</a>.<br/>
<p><a>nginx.com</a></p>
<p><em>Thank you for using nginx.</em></p>
 openssl s_client -connect localhost:3000 -CAfile root-ca.crt
 docker service rm nginx
 docker secret rm site.crt site.key site.conf

在镜像中构建对Docker Secrets的支持

如果您开发了一个可以作为服务部署的容器,并且需要敏感数据(如凭据)作为环境变量,请考虑调整您的映像以利用Docker secret 。一种方法是确保您在创建容器时传递给图像的每个参数也可以从文件中读取。

Docker hub 中的许多Docker官方图像,都以这种方式进行了更新。

当您启动WordPress容器时,您可以通过将其设置为环境变量来为其提供所需的参数。WordPress图像已更新,因此包含WordPress重要数据的环境变量(如WORDPRESS_DB_PASSWORD)也具有可以从文件(WORDPRESS_DB_PASSWORD_FILE)中读取其值的变体。此策略可确保保持向后兼容性,同时允许您的容器从Docker管理的secret 中读取信息,而不是直接传递。

NOTE

Docker机密不会直接设置环境变量。这是一个有意识的决定,因为环境变量可能会无意中在容器之间泄露(例如,如果您使用--link)。

在docker-compose中使用secret

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:

此示例使用编写文件中的两个secret 创建一个简单的WordPress网站。

关键字secrets:定义两个secret db_password:db_root_password:

部署时,Docker会创建这两个secret ,并用编写文件中指定的文件中的内容填充它们。

db服务同时使用两个secret ,而wordpress正在使用一个secret 。

当您部署时,Docker会在服务的/run/secrets/<secret_name>下挂载一个文件。这些文件永远不会在磁盘上持久化,而是在内存中管理。

每个服务都使用环境变量来指定服务应该在哪里查找该secret 数据。

以上就是docker-swarm之使用Docker secret管理敏感数据的详细内容,更多关于Docker secret管理数据的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文