目录搜索
ComposeAbout versions and upgrading (Compose)ASP.NET Core + SQL Server on Linux (Compose)CLI environment variables (Compose)Command-line completion (Compose)Compose(组成)Compose command-line reference(组合命令行参考)Control startup order (Compose)Django and PostgreSQL (Compose)Docker stacks and distributed application bundles (Compose)docker-compose build(docker-compose构建)docker-compose bundledocker-compose configdocker-compose createdocker-compose downdocker-compose eventsdocker-compose execdocker-compose helpdocker-compose imagesdocker-compose killdocker-compose logsdocker-compose pausedocker-compose portdocker-compose psdocker-compose pulldocker-compose pushdocker-compose restartdocker-compose rmdocker-compose rundocker-compose scaledocker-compose startdocker-compose stopdocker-compose topdocker-compose unpausedocker-compose upEnvironment file (Compose)Environment variables in ComposeExtend services in ComposeFrequently asked questions (Compose)Getting started (Compose)Install ComposeLink environment variables (deprecated) (Compose)Networking in ComposeOverview of Docker ComposeOverview of docker-compose CLIQuickstart: Compose and WordPressRails and PostgreSQL (Compose)Sample apps with ComposeUsing Compose in productionUsing Compose with SwarmEngine.NET Core application (Engine)About images, containers, and storage drivers (Engine)Add nodes to the swarm (Engine)Apply custom metadata (Engine)Apply rolling updates (Engine)apt-cacher-ngBest practices for writing Dockerfiles (Engine)Binaries (Engine)Bind container ports to the host (Engine)Breaking changes (Engine)Build your own bridge (Engine)Configure container DNS (Engine)Configure container DNS in user-defined networks (Engine)CouchDB (Engine)Create a base image (Engine)Create a swarm (Engine)Customize the docker0 bridge (Engine)Debian (Engine)Default bridge networkDelete the service (Engine)Deploy a service (Engine)Deploy services to a swarm (Engine)Deprecated Engine featuresDocker container networking (Engine)Docker overview (Engine)Docker run reference (Engine)Dockerfile reference (Engine)Dockerize an applicationDrain a node (Engine)EngineFAQ (Engine)Fedora (Engine)Get started (Engine)Get started with macvlan network driver (Engine)Get started with multi-host networking (Engine)How nodes work (Engine)How services work (Engine)Image management (Engine)Inspect the service (Engine)Install Docker (Engine)IPv6 with Docker (Engine)Join nodes to a swarm (Engine)Legacy container links (Engine)Lock your swarm (Engine)Manage nodes in a swarm (Engine)Manage sensitive data with Docker secrets (Engine)Manage swarm security with PKI (Engine)Manage swarm service networks (Engine)Migrate to Engine 1.10Optional Linux post-installation steps (Engine)Overview (Engine)PostgreSQL (Engine)Raft consensus in swarm mode (Engine)Riak (Engine)Run Docker Engine in swarm modeScale the service (Engine)SDKs (Engine)Select a storage driver (Engine)Set up for the tutorial (Engine)SSHd (Engine)Storage driver overview (Engine)Store service configuration data (Engine)Swarm administration guide (Engine)Swarm mode key concepts (Engine)Swarm mode overlay network security model (Engine)Swarm mode overview (Engine)Understand container communication (Engine)Use multi-stage builds (Engine)Use swarm mode routing mesh (Engine)Use the AUFS storage driver (Engine)Use the Btrfs storage driver (Engine)Use the Device mapper storage driver (Engine)Use the OverlayFS storage driver (Engine)Use the VFS storage driver (Engine)Use the ZFS storage driver (Engine)Engine: Admin GuideAmazon CloudWatch logs logging driver (Engine)Bind mounts (Engine)Collect Docker metrics with Prometheus (Engine)Configuring and running Docker (Engine)Configuring logging drivers (Engine)Control and configure Docker with systemd (Engine)ETW logging driver (Engine)Fluentd logging driver (Engine)Format command and log output (Engine)Google Cloud logging driver (Engine)Graylog Extended Format (GELF) logging driver (Engine)Journald logging driver (Engine)JSON File logging driver (Engine)Keep containers alive during daemon downtime (Engine)Limit a container's resources (Engine)Link via an ambassador container (Engine)Log tags for logging driver (Engine)Logentries logging driver (Engine)PowerShell DSC usage (Engine)Prune unused Docker objects (Engine)Run multiple services in a container (Engine)Runtime metrics (Engine)Splunk logging driver (Engine)Start containers automatically (Engine)Storage overview (Engine)Syslog logging driver (Engine)tmpfs mountsTroubleshoot volume problems (Engine)Use a logging driver plugin (Engine)Using Ansible (Engine)Using Chef (Engine)Using Puppet (Engine)View a container's logs (Engine)Volumes (Engine)Engine: CLIDaemon CLI reference (dockerd) (Engine)dockerdocker attachdocker builddocker checkpointdocker checkpoint createdocker checkpoint lsdocker checkpoint rmdocker commitdocker configdocker config createdocker config inspectdocker config lsdocker config rmdocker containerdocker container attachdocker container commitdocker container cpdocker container createdocker container diffdocker container execdocker container exportdocker container inspectdocker container killdocker container logsdocker container lsdocker container pausedocker container portdocker container prunedocker container renamedocker container restartdocker container rmdocker container rundocker container startdocker container statsdocker container stopdocker container topdocker container unpausedocker container updatedocker container waitdocker cpdocker createdocker deploydocker diffdocker eventsdocker execdocker exportdocker historydocker imagedocker image builddocker image historydocker image importdocker image inspectdocker image loaddocker image lsdocker image prunedocker image pulldocker image pushdocker image rmdocker image savedocker image tagdocker imagesdocker importdocker infodocker inspectdocker killdocker loaddocker logindocker logoutdocker logsdocker networkdocker network connectdocker network createdocker network disconnectdocker network inspectdocker network lsdocker network prunedocker network rmdocker nodedocker node demotedocker node inspectdocker node lsdocker node promotedocker node psdocker node rmdocker node updatedocker pausedocker plugindocker plugin createdocker plugin disabledocker plugin enabledocker plugin inspectdocker plugin installdocker plugin lsdocker plugin pushdocker plugin rmdocker plugin setdocker plugin upgradedocker portdocker psdocker pulldocker pushdocker renamedocker restartdocker rmdocker rmidocker rundocker savedocker searchdocker secretdocker secret createdocker secret inspectdocker secret lsdocker secret rmdocker servicedocker service createdocker service inspectdocker service logsdocker service lsdocker service psdocker service rmdocker service scaledocker service updatedocker stackdocker stack deploydocker stack lsdocker stack psdocker stack rmdocker stack servicesdocker startdocker statsdocker stopdocker swarmdocker swarm cadocker swarm initdocker swarm joindocker swarm join-tokendocker swarm leavedocker swarm unlockdocker swarm unlock-keydocker swarm updatedocker systemdocker system dfdocker system eventsdocker system infodocker system prunedocker tagdocker topdocker unpausedocker updatedocker versiondocker volumedocker volume createdocker volume inspectdocker volume lsdocker volume prunedocker volume rmdocker waitUse the Docker command line (Engine)Engine: ExtendAccess authorization plugin (Engine)Docker log driver pluginsDocker network driver plugins (Engine)Extending Engine with pluginsManaged plugin system (Engine)Plugin configuration (Engine)Plugins API (Engine)Volume plugins (Engine)Engine: SecurityAppArmor security profiles for Docker (Engine)Automation with content trust (Engine)Content trust in Docker (Engine)Delegations for content trust (Engine)Deploying Notary (Engine)Docker security (Engine)Docker security non-events (Engine)Isolate containers with a user namespace (Engine)Manage keys for content trust (Engine)Play in a content trust sandbox (Engine)Protect the Docker daemon socket (Engine)Seccomp security profiles for Docker (Engine)Secure EngineUse trusted imagesUsing certificates for repository client verification (Engine)Engine: TutorialsEngine tutorialsNetwork containers (Engine)Get StartedPart 1: OrientationPart 2: ContainersPart 3: ServicesPart 4: SwarmsPart 5: StacksPart 6: Deploy your appMachineAmazon Web Services (Machine)Digital Ocean (Machine)docker-machine activedocker-machine configdocker-machine createdocker-machine envdocker-machine helpdocker-machine inspectdocker-machine ipdocker-machine killdocker-machine lsdocker-machine provisiondocker-machine regenerate-certsdocker-machine restartdocker-machine rmdocker-machine scpdocker-machine sshdocker-machine startdocker-machine statusdocker-machine stopdocker-machine upgradedocker-machine urlDriver options and operating system defaults (Machine)Drivers overview (Machine)Exoscale (Machine)Generic (Machine)Get started with a local VM (Machine)Google Compute Engine (Machine)IBM Softlayer (Machine)Install MachineMachineMachine CLI overviewMachine command-line completionMachine concepts and helpMachine overviewMicrosoft Azure (Machine)Microsoft Hyper-V (Machine)Migrate from Boot2Docker to MachineOpenStack (Machine)Oracle VirtualBox (Machine)Provision AWS EC2 instances (Machine)Provision Digital Ocean Droplets (Machine)Provision hosts in the cloud (Machine)Rackspace (Machine)VMware Fusion (Machine)VMware vCloud Air (Machine)VMware vSphere (Machine)NotaryClient configuration (Notary)Common Server and signer configurations (Notary)Getting started with NotaryNotary changelogNotary configuration filesRunning a Notary serviceServer configuration (Notary)Signer configuration (Notary)Understand the service architecture (Notary)Use the Notary client
文字

关于机密

就Docker Swarm服务而言,秘密是一组数据,如密码,SSH私钥,SSL证书或另一部分数据,这些数据不应通过网络传输或在Dockerfile或应用程序中未加密存储源代码。在Docker 1.13及更高版本中,您可以使用Docker 机密来集中管理这些数据,并将其安全地传输给需要访问的那些容器。在运输过程中密码被加密,并在Docker群中休息。给定的秘密只能被那些被授予明确访问权限的服务访问,并且只有在这些服务任务正在运行时才能访问。

您可以使用秘密来管理容器在运行时需要的任何敏感数据,但不想将其存储在映像或源代码管理中,例如:

  • 用户名和密码

  • TLS证书和密钥

  • SSH密钥

  • 其他重要数据,如数据库或内部服务器的名称

  • 通用字符串或二进制内容(最大为500 kb)

注意:Docker机密仅适用于群集服务,而不适用于独立容器。要使用此功能,请考虑将您的容器作为1级服务运行。

另一个使用秘密的用例是在容器和一组证书之间提供一个抽象层。考虑一个场景,您可以为应用程序分别开发,测试和生产环境。这些环境中的每一个都可以拥有不同的凭证,并以相同的秘密名称存储在开发,测试和生产群中。您的容器只需要知道秘密的名称,以便在三种环境中都能正常工作。

您还可以使用机密来管理非敏感数据,例如配置文件。但是,Docker 17.06和更高版本支持使用configs来存储非敏感数据。配置直接安装到容器的文件系统中,而不使用RAM磁盘。

Windows支持

Docker 17.06和更高版本包含对Windows容器上的秘密的支持。在实现中存在差异的地方,它们在下面的例子中被调用。牢记以下显着差异:

  • Microsoft Windows没有用于管理RAM磁盘的内置驱动程序,因此在运行Windows容器中,秘密以明文形式保存到容器的根磁盘。但是,当容器停止时,秘密将被明确删除。另外,Windows不支持将正在运行的容器作为使用图像docker commit或类似命令的图像。

  • 在Windows上,我们建议在主机上包含Docker根目录的卷上启用BitLocker(https://technet.microsoft.com/en-us/library/cc732774(v = ws.11%29.aspx)以确保运行容器的秘密在休息时被加密。

  • 自定义目标的秘密文件不直接绑定到Windows容器中,因为Windows不支持非目录文件绑定挂载。相反,容器的秘密都安装在C:\ProgramData\Docker\internal\secrets容器内的(应用程序不应该依赖的实现细节中)。符号链接用于指向容器内的秘密所需的目标。默认目标是C:\ProgramData\Docker\secrets

  • 在创建使用Windows容器的服务时,用于指定UID,GID和模式的选项不受秘密支持。当前只能由管理员和system容器内的访问权限的用户访问秘密。

Docker如何管理机密

当您为swarm添加秘密时,Docker会通过相互TLS连接将密钥发送给swarm管理器。秘密存储在加密的Raft日志中。整个Raft日志被复制到其他管理者中,确保与其他群管理数据相同的高可用性保证。

警告:Raft数据在Docker 1.13和更高版本中被加密。如果您的任何Swarm管理人员运行早期版本,并且其中一位经理成为群体经理,则秘密将以未加密方式存储在该节点的Raft日志中。在添加任何秘密之前,将所有管理器节点更新到Docker 1.13或更高版本,以防止将秘密写入纯文本的Raft日志。

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

您可以更新服务,授权其访问其他机密或随时撤销对指定机密的访问权限。

如果节点是群管理器或者它正在运行已被授权访问秘密的服务任务,那么节点只能访问(加密的)秘密。当容器任务停止运行时,共享给它的解密秘密将从该容器的内存中文件系统卸载,并从节点的内存刷新。

如果节点在运行可访问秘密的任务容器时失去与群集的连接,则任务容器仍可访问其秘密,但在节点重新连接群集之前无法接收更新。

您可以随时添加或检查个人密码,或列出所有密码。您无法删除正在运行的服务正在使用的秘密。请参阅旋转秘密以在不中断正在运行的服务的情况下移除秘密。

为了更容易地更新或回滚秘密,请考虑在秘密名称中添加版本号或日期。通过控制给定容器内秘密的安装点的能力使这变得更容易。

阅读更多关于docker secret命令的信息

使用这些链接阅读有关特定命令的内容,或继续关于在服务中使用秘密的示例。

  • docker secret create

  • docker secret inspect

  • docker secret ls

  • docker secret rm

  • --secret 标志为 docker service create

  • --secret-add--secret-rm标志docker service update

例子

本节包含三个演示如何使用Docker机密的毕业示例。这些示例中使用的图像已更新,以便于使用Docker机密。要了解如何以类似的方式修改自己的图像,请参阅将Docker机密支持构建到图像中。

注意:为简单起见,这些示例使用单引擎群和非标度服务。这些示例使用Linux容器,但Windows容器也支持Docker 17.06和更高版本中的秘密。请参阅Windows支持。

简单的例子:开始秘密

这个简单的例子展示了秘密如何在几个命令中工作。对于真实世界的例子,继续到中级例子:使用Nginx服务的秘密。

  1. 给Docker添加一个秘密。该docker secret create命令读取标准输入,因为最后一个参数表示要读取密钥的文件设置为-。$ echo "This is a secret" | docker secret create my_secret_data -

  2. 创建一个redis服务并授予它访问该秘密的权限。默认情况下,容器可以访问该密码/run/secrets/<secret_name>,但您可以使用该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.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)"

  4. 获取redis使用的服务任务容器的ID docker ps,以便您可以使用docker exec连接到容器并读取秘密数据文件的内容,该内容默认为全部可读,并且与秘密的名称相同。下面的第一条命令说明了如何找到容器ID,第二个和第三个命令使用shell完成来自动执行此操作。$ 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

  5. 验证如果您提交容器,秘密不可用。$ 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. 尝试删除秘密。删除失败,因为该redis服务正在运行并可以访问该秘密。$ 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

  7. redis通过更新服务,从正在运行的服务中移除对秘密的访问权限。$ docker service update --secret-rm my_secret_data redis

  8. 重复步骤3和4,验证该服务不再有权访问该秘密。容器ID将不同,因为该service update命令重新部署服务。$ 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

  9. 停止并删除服务,并从Docker中删除密钥。$ docker service rm redis $ docker secret rm my_secret_data

简单的例子:在Windows服务中使用秘密

这是一个非常简单的例子,它展示了如何使用运行在Microsoft Windows Server 2016上的Docker 17.06 EE或Microsoft Windows 10上的Docker for Mac 17.06上运行的Microsoft IIS服务的秘密。这是一个理想的例子,它将网页存储在一个秘密中。

此示例假定您已安装PowerShell。

  1. 将以下内容保存到一个新文件中:index.html<html> <head> <title> Hello Docker </ title> </ head> <body> <p> Hello Docker!您已经部署了一个HTML页面。</ p> </ body> </ html>

  2. 如果你还没有这样做,请初始化或加入群。PS> docker swarm init

  3. 将该index.html文件保存为名为swarm的秘密homepage。PS> docker secret创建主页index.html

  4. 创建一个IIS服务并授予它对homepage秘密的访问权限。PS> docker service create --name my-iis -p 8000:8000 --secret src = homepage,target =“\ inetpub \ wwwroot \ index.html”microsoft / iis:nanoserver 注意:技术上没有理由使用机密对于这个例子。使用Docker 17.06或更高版本,configs更适合。这个例子仅用于说明。

  5. 访问IIS服务http://localhost:8000/。它应该从第一步开始提供HTML内容。

  6. 删除服务和秘密。PS> docker service rm my-iis  PS> docker secret rm homepage PS> docker image remove secret-test

中级示例:使用Nginx服务的秘密

这个例子分为两部分。第一部分是关于生成站点证书的内容,并不直接涉及Docker机密,但是它建立了第二部分,在那里存储和使用站点证书和Nginx配置作为秘密。

生成站点证书

为您的站点生成根CA和TLS证书和密钥。对于生产站点,您可能希望使用服务Let’s Encrypt来生成TLS证书和密钥,但此示例使用命令行工具。这一步有点复杂,但只是一个设置步骤,以便您可以将某些内容存储为Docker的秘密。如果你想跳过这些子步骤,您可以使用我们的加密生成网站密钥和证书,命名文件site.keysite.crt,并跳过配置Nginx的容器。

  1. 生成一个根密钥。$ openssl genrsa -out“root-ca.key”4096

  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”4096

  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.csrsite.cnf文件不需要由Nginx的服务,但你需要他们,如果你想生成一个新的站点证书。保护root-ca.key文件。

配置Nginx容器

  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. 创建三个机密,代表密钥,证书和密钥 site.conf。只要小于500 KB,您就可以将任何文件存储为秘密文件。这使您可以将密钥,证书和配置与将使用它们的服务分离。在每一个这些命令中,最后一个参数代表从主机文件系统读取密钥的文件路径。在这些示例中,秘密名称和文件名是相同的。$ 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

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

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

在Docker 17.05及更早版本中,机密总是位于/run/secrets/目录中。Docker 17.06及更高版本允许您为容器中的秘密指定自定义位置。下面的两个例子说明了它们的区别。该命令的较早版本要求您创建一个到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 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;'"

第一个示例显示秘密的短语和长语,而第二个示例仅显示短语法。简短语法创建/run/secrets/与机密具有相同名称的文件。在正在运行的容器中,现在存在以下三个文件:

- `/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)
  1. 验证Nginx服务正在运行。$ 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

  2. 验证服务是否可操作:您可以访问Nginx服务器,并且正在使用正确的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)

  3. 运行此示例后要清理,请删除nginx服务和存储的机密。$ docker service rm nginx $ docker secret rm site.crt site.key site.conf

高级示例:使用WordPress服务的秘密

在本例中,您使用自定义root密码创建单节点MySQL服务,将凭证添加为秘密,并创建使用这些凭证连接到MySQL的单节点WordPress服务。下一个示例基于这个示例,向您展示如何旋转MySQL密码并更新服务,以便WordPress服务仍然可以连接到MySQL。

此示例说明了一些使用Docker机密的技巧,以避免将敏感凭证保存在映像中或直接在命令行上传递它们。

注意:为简单起见,此示例使用单引擎群,并使用单节点MySQL服务,因为单个MySQL服务器实例无法通过简单地使用复制服务来扩展,并且设置MySQL群集超出了本示例的范围。另外,更改MySQL根密码并不像更改磁盘上的文件那么简单。您必须使用查询或mysqladmin命令来更改MySQL中的密码。

  1. 为MySQL生成一个随机的字母数字密码,并mysql_password使用该docker secret create命令将其作为Docker机密存储。要使密码更短或更长,请调整该openssl命令的最后一个参数。这只是创建相对随机密码的一种方式。如果您选择,您可以使用其他命令来生成密码。 注意:创建秘密后,您无法更新它。您只能删除并重新创建它,并且无法删除服务正在使用的秘密。但是,您可以使用授予或撤销正在运行的服务对秘密的访问权限docker service update。如果您需要更新密码的功能,请考虑在密码名称中添加一个版本组件,以便稍后添加新版本,更新服务以使用它,然后删除旧版本。

最后一个参数设置为-,表示输入是从标准输入读取的。

$ openssl rand -base64 20 | docker secret create mysql_password -  l1vinzevzhj4goakjap5ya409

返回的值不是密码,而是密码的ID。在本教程的其余部分中,ID输出被省略。

为MySQL root用户生成第二个秘密。此秘密不会与稍后创建的WordPress服务共享。它只需要引导mysql服务。

$ 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

秘密存储在群集的加密的Raft日志中。

  1. 创建用于MySQL和WordPress服务之间通信的用户定义覆盖网络。不需要将MySQL服务公开给任何外部主机或容器。$ docker network create -d overlay mysql_private

  2. 创建MySQL服务。MySQL服务将具有以下特征:

- 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
  1. 验证mysql容器是否正在使用该docker service ls命令运行。$ docker service ls  ID            NAME   MODE        REPLICAS  IMAGE wvnh0siktqr3  mysql  replicated  1/1       mysql:latest     在这一点上,你实际上可以撤销该mysql服务对访问mysql_passwordmysql_root_password秘密,因为密码已被保存在MySQL系统数据库。现在不要这样做,因为稍后我们会使用它们来方便旋转MySQL密码。

  2. 现在MySQL已经建立,创建一个连接到MySQL服务的WordPress服务。WordPress服务具有以下特点:

- 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

  1. 验证服务正在使用docker service lsdocker service ps命令运行。$ 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         此时,您实际上可以撤消WordPress服务对mysql_password秘密的访问,因为WordPress已将秘密复制到其配置文件中wp-config.php。现在不要这样做,因为我们稍后会使用它来方便旋转MySQL密码。

  2. http://localhost:30000/从任何swarm节点访问并使用基于Web的向导设置WordPress。所有这些设置都存储在MySQL wordpress数据库中。WordPress自动为您的WordPress用户生成密码,这与WordPress用于访问MySQL的密码完全不同。安全地存储此密码,例如在密码管理器中。旋转秘密后,您将需要它登录WordPress。继续撰写一篇或两篇博文,并安装一个WordPress插件或主题,以验证WordPress是否完全正常运行,并且在重新启动服务时保存其状态。

  3. 如果您打算继续下一个示例,演示如何旋转MySQL根密码,请不要清除任何服务或秘密。

例如:回旋机密

这个例子建立在前一个例子上。在这种情况下,您使用新的MySQL密码创建一个新密码,更新mysqlwordpress使用它的服务,然后删除旧密码。

注意:更改MySQL数据库的密码涉及运行额外的查询或命令,而不是仅仅更改单个环境变量或文件,因为如果数据库尚不存在,映像只设置MySQL密码,并且MySQL存储默认情况下,MySQL数据库中的密码。轮换密码或其他秘密可能涉及Docker之外的其他步骤。

  1. 创建新密码并将其存储为一个名为secret的密码mysql_password_v2。$ openssl rand -base64 20 | docker secret create mysql_password_v2 -

  2. 更新MySQL服务,使其能够访问旧的和新的秘密。请记住,您无法更新或重命名密钥,但可以撤销秘密并使用新的目标文件名授予对其的访问权限。$ 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          更新服务会导致它重新启动,并且当MySQL服务第二次重新启动时,它有权访问旧密钥/run/secrets/old_mysql_password和新密钥/run/secrets/mysql_password。尽管MySQL服务现在可以访问旧的和新的机密,但WordPress用户的MySQL密码尚未更改。  注意:这个例子不会旋转MySQL root密码。

  3. 现在,wordpress使用mysqladminCLI 更改用户的MySQL密码。该命令从文件中读取旧密码和新密码,/run/secrets但不在命令行上公开它们或将它们保存在shell历史记录中。快速做到这一点,并继续下一步,因为WordPress将失去连接到MySQL的能力。首先,找到mysql容器任务的ID 。$ docker ps --filter name = mysql -q c7705cf6176f                      在下面的命令中替换ID,或者使用第二个使用shell扩展的变体在一个步骤中完成所有操作。     $ 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“$(<运行/秘密/ mysql_password)“”

  4. 更新wordpress服务以使用新密码,保留目标路径/run/secrets/wp_db_secret并保持文件权限0400。这将触发WordPress服务的滚动重启,并且将使用新的秘密。$ docker service update \ --secret-rm mysql_password \ --secret-add source = mysql_password_v2,target = wp_db_password,mode = 0400 \ wordpress \ wordpress

  5. 通过再次浏览任何swarm节点上的http:// localhost:30000 /来验证WordPress是否工作正常。您需要使用在上一个任务中通过WordPress向导时使用的WordPress用户名和密码。验证您写的博文是否仍然存在,如果您更改了任何配置值,请确认它们仍然发生更改。

  6. 撤消对MySQL服务的旧密钥的访问权限,并从Docker中删除旧密钥。$ docker service update \      --secret-rm mysql_password \      mysql  $ docker secret rm mysql_password

  7. 如果您想要再次运行所有这些示例,或者只是想在运行完所有示例后进行清理,请使用这些命令来删除WordPress服务,MySQL容器,mydata和wpdata卷以及Docker机密。$ docker service rm wordpress mysql $ docker volume rm mydata wpdata $ docker secret rm mysql_password_v2 mysql_root_password

将Docker秘诀支持到您的图像中

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

Docker库中的许多官方图像,例如上面示例中使用的wordpress图像,都以这种方式进行了更新。

当你启动一个WordPress容器时,通过将它们设置为环境变量来提供它所需的参数。WordPress图片已经更新,因此包含WordPress重要数据的环境变量(如WORDPRESS_DB_PASSWORD变量)也可以从文件(WORDPRESS_DB_PASSWORD_FILE)中读取它们的值。这种策略可确保向后兼容性得到保留,同时允许容器从Docker管理的秘密中读取信息,而不是直接传递。

注意:Docker机密不会直接设置环境变量。这是一个有意识的决定,因为环境变量可能会无意中泄漏到容器之间(例如,使用--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:

本示例使用撰写文件中的两个秘密创建一个简单的WordPress网站。

关键字secrets:定义了两个秘密db_password:db_root_password:

部署时,Docker将创建这两个秘密,并使用撰写文件中指定的文件中的内容填充它们。

数据库服务使用两个秘密,并且wordpress使用一个。

在部署时,Docker将/run/secrets/<secret_name>在服务下安装一个文件。这些文件永远不会保存在磁盘中,而是在内存中进行管理。

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

有关秘密短语和长语法的更多信息可以在Compose文件版本3参考中找到。

上一篇:下一篇: