Backup DTR 2.6

This commit is contained in:
ollypom 2019-07-19 12:48:51 +00:00
parent 6a7cb335f7
commit aca8feb5b8
No known key found for this signature in database
GPG Key ID: 2E6D9F4EBCB6B160
238 changed files with 24398 additions and 0 deletions

View File

@ -2569,6 +2569,201 @@ manuals:
title: Release notes
- sectiontitle: Previous versions
section:
- sectiontitle: Docker Trusted Registry 2.6
section:
- path: /datacenter/dtr/2.6/guides/
title: Docker Trusted Registry overview
- path: /datacenter/dtr/2.6/guides/architecture/
title: Architecture
- sectiontitle: Administration
section:
- sectiontitle: Install
section:
- path: /datacenter/dtr/2.6/guides/admin/install/system-requirements/
title: System requirements
- path: /datacenter/dtr/2.6/guides/admin/install/
title: Install
- path: /datacenter/dtr/2.6/guides/admin/install/install-offline/
title: Install offline
- path: /datacenter/dtr/2.6/guides/admin/upgrade/
title: Upgrade
- path: /datacenter/dtr/2.6/guides/admin/install/uninstall/
title: Uninstall
- sectiontitle: Configure
section:
- path: /datacenter/dtr/2.6/guides/admin/configure/license-your-installation/
title: License your installation
- path: /datacenter/dtr/2.6/guides/admin/configure/use-your-own-tls-certificates/
title: Use your own TLS certificates
- path: /datacenter/dtr/2.6/guides/admin/configure/enable-single-sign-on/
title: Enable single sign-on
- sectiontitle: External storage
section:
- path: /datacenter/dtr/2.6/guides/admin/configure/external-storage/
title: Overview
- path: /datacenter/dtr/2.6/guides/admin/configure/external-storage/storage-backend-migration/
title: Switch storage backends
- path: /datacenter/dtr/2.6/guides/admin/configure/external-storage/s3/
title: S3
- path: /datacenter/dtr/2.6/guides/admin/configure/external-storage/nfs/
title: NFS
- path: /datacenter/dtr/2.6/guides/admin/configure/set-up-high-availability/
title: Set up high availability
- path: /datacenter/dtr/2.6/guides/admin/configure/use-a-load-balancer/
title: Use a load balancer
- path: /datacenter/dtr/2.6/guides/admin/configure/set-up-vulnerability-scans/
title: Set up vulnerability scans
- sectiontitle: Deploy caches
section:
- title: Cache overview
path: /datacenter/dtr/2.6/guides/admin/configure/deploy-caches/
- title: Cache deployment strategy
path: /datacenter/dtr/2.6/guides/admin/configure/deploy-caches/strategy/
- title: Deploy a DTR cache with Docker Swarm
path: /datacenter/dtr/2.6/guides/admin/configure/deploy-caches/simple/
- title: Deploy a DTR cache with Kubernetes
path: /datacenter/dtr/2.6/guides/admin/configure/deploy-caches/simple-kube/
- title: Configure caches for high availability
path: /datacenter/dtr/2.6/guides/admin/configure/deploy-caches/high-availability/
- title: Cache configuration reference
path: /datacenter/dtr/2.6/guides/admin/configure/deploy-caches/configuration-reference/
- path: /datacenter/dtr/2.6/guides/admin/configure/garbage-collection/
title: Garbage collection
- title: Allow users to create repositories when pushing
path: /datacenter/dtr/2.6/guides/admin/configure/allow-creation-on-push/
- path: /datacenter/dtr/2.6/guides/admin/configure/use-a-web-proxy/
title: Use a web proxy
- sectiontitle: Manage users
section:
- path: /datacenter/dtr/2.6/guides/admin/manage-users/
title: Authentication and authorization
- path: /datacenter/dtr/2.6/guides/admin/manage-users/create-and-manage-users/
title: Create and manage users
- path: /datacenter/dtr/2.6/guides/admin/manage-users/create-and-manage-teams/
title: Create and manage teams
- path: /datacenter/dtr/2.6/guides/admin/manage-users/create-and-manage-orgs/
title: Create and manage organizations
- path: /datacenter/dtr/2.6/guides/admin/manage-users/permission-levels/
title: Permission levels
- sectiontitle: Manage webhooks
section:
- title: Create and manage webhooks
path: /datacenter/dtr/2.6/guides/admin/manage-webhooks/
- title: Use the web interface
path: /datacenter/dtr/2.6/guides/admin/manage-webhooks/use-the-web-ui/
- title: Use the API
path: /datacenter/dtr/2.6/guides/admin/manage-webhooks/use-the-api/
- sectiontitle: Manage jobs
section:
- path: /datacenter/dtr/2.6/guides/admin/manage-jobs/job-queue/
title: Job Queue
- path: /datacenter/dtr/2.6/guides/admin/manage-jobs/audit-jobs-via-ui/
title: Audit Jobs with the Web Interface
- path: /datacenter/dtr/2.6/guides/admin/manage-jobs/audit-jobs-via-api/
title: Audit Jobs with the API
- path: /datacenter/dtr/2.6/guides/admin/manage-jobs/auto-delete-job-logs/
title: Enable Auto-Deletion of Job Logs
- sectiontitle: Monitor and troubleshoot
section:
- path: /datacenter/dtr/2.6/guides/admin/monitor-and-troubleshoot/
title: Monitor the cluster status
- path: /datacenter/dtr/2.6/guides/admin/monitor-and-troubleshoot/notary-audit-logs/
title: Check Notary audit logs
- path: /datacenter/dtr/2.6/guides/admin/monitor-and-troubleshoot/troubleshoot-dtr/
title: Troubleshoot Docker Trusted Registry
- sectiontitle: Disaster recovery
section:
- title: Overview
path: /datacenter/dtr/2.6/guides/admin/disaster-recovery/
- title: Repair a single replica
path: /datacenter/dtr/2.6/guides/admin/disaster-recovery/repair-a-single-replica/
- title: Repair a cluster
path: /datacenter/dtr/2.6/guides/admin/disaster-recovery/repair-a-cluster/
- title: Create a backup
path: /datacenter/dtr/2.6/guides/admin/disaster-recovery/create-a-backup/
- title: Restore from a backup
path: /datacenter/dtr/2.6/guides/admin/disaster-recovery/restore-from-backup/
- sectiontitle: CLI Reference
section:
- path: /reference/dtr/2.6/cli/
title: Overview
- path: /reference/dtr/2.6/cli/backup/
title: backup
- path: /reference/dtr/2.6/cli/destroy/
title: destroy
- path: /reference/dtr/2.6/cli/emergency-repair/
title: emergency-repair
- path: /reference/dtr/2.6/cli/install/
title: install
- path: /reference/dtr/2.6/cli/join/
title: join
- path: /reference/dtr/2.6/cli/reconfigure/
title: reconfigure
- path: /reference/dtr/2.6/cli/remove/
title: remove
- path: /reference/dtr/2.6/cli/restore/
title: restore
- path: /reference/dtr/2.6/cli/upgrade/
title: upgrade
- sectiontitle: User guides
section:
- sectiontitle: Access DTR
section:
- path: /datacenter/dtr/2.6/guides/user/access-dtr/
title: Configure your Docker daemon
- path: /datacenter/dtr/2.6/guides/user/access-dtr/configure-your-notary-client/
title: Configure your Notary client
- path: /datacenter/dtr/2.6/guides/user/access-dtr/use-a-cache/
title: Use a cache
- sectiontitle: Manage images
section:
- path: /datacenter/dtr/2.6/guides/user/manage-images/
title: Create a repository
- path: /datacenter/dtr/2.6/guides/user/manage-images/review-repository-info/
title: Review repository info
- path: /datacenter/dtr/2.6/guides/user/manage-images/pull-and-push-images/
title: Pull and push images
- path: /datacenter/dtr/2.6/guides/user/manage-images/delete-images/
title: Delete images
- path: /datacenter/dtr/2.6/guides/user/manage-images/scan-images-for-vulnerabilities/
title: Scan images for vulnerabilities
- title: Override a vulnerability
path: /datacenter/dtr/2.6/guides/user/manage-images/override-a-vulnerability/
- path: /datacenter/dtr/2.6/guides/user/manage-images/prevent-tags-from-being-overwritten/
title: Prevent tags from being overwritten
- sectiontitle: Sign images
section:
- path: /datacenter/dtr/2.6/guides/user/manage-images/sign-images/
title: Sign an image
- path: /datacenter/dtr/2.6/guides/user/manage-images/sign-images/trust-with-remote-ucp/
title: Trust with a Remote UCP
- sectiontitle: Promotion policies and mirroring
section:
- title: Overview
path: /datacenter/dtr/2.6/guides/user/promotion-policies/
- title: Promote an image using policies
path: /datacenter/dtr/2.6/guides/user/promotion-policies/internal-promotion/
- title: Mirror images to another registry
path: /datacenter/dtr/2.6/guides/user/promotion-policies/push-mirror/
- title: Mirror images from another registry
path: /datacenter/dtr/2.6/guides/user/promotion-policies/pull-mirror/
- title: Template reference
path: /datacenter/dtr/2.6/guides/user/promotion-policies/templates/
- sectiontitle: Manage repository events
section:
- title: Audit repository events
path: /datacenter/dtr/2.6/guides/user/audit-repository-events/
- title: Auto-delete repository events
path: /datacenter/dtr/2.6/guides/admin/configure/auto-delete-repo-events/
- title: Manage access tokens
path: /datacenter/dtr/2.6/guides/user/access-tokens/
- title: Tag pruning
path: /datacenter/dtr/2.6/guides/user/tag-pruning/
- title: API reference
path: /datacenter/dtr/2.6/reference/api/
nosync: true
- path: /datacenter/dtr/2.6/guides/release-notes/
title: Release notes
- sectiontitle: Docker Trusted Registry 2.5
section:
- path: /datacenter/dtr/2.5/guides/

View File

@ -0,0 +1,35 @@
---
title: Allow users to create repositories when pushing
description: By default Docker Trusted Registry only allows pushing images to
existing repositories. Learn how to change that.
keywords: dtr, repository
redirect_from:
- /datacenter/dtr/2.5/guides/admin/configure/allow-creation-on-push/
---
By default DTR only allows pushing images if the repository exists, and you
have write access to the repository.
As an example, if you try to push to `dtr.example.org/library/java:9`, and the
`library/java` repository doesn't exist yet, your push fails.
You can configure DTR to allow pushing to repositories that don't exist yet.
As an administrator, log into the **DTR web UI**, navigate to the **Settings**
page, and enable **Create repository on push**.
![DTR settings page](../../images/create-on-push-1.png){: .with-border}
From now on, when a user pushes to their personal sandbox
(`<user-name>/<repository>`), or if the user is an administrator for the
organization (`<org>/<repository>`), DTR will create a repository if it doesn't
exist yet. In that case, the repository is created as private.
## Use the CLI to enable pushing to repositories that don't exist yet
```bash
curl --user <admin-user>:<password> \
--request POST "<dtr-url>/api/v0/meta/settings" \
--header "accept: application/json" \
--header "content-type: application/json" \
--data "{ \"createRepositoryOnPush\": true}"
```

View File

@ -0,0 +1,43 @@
---
title: Enable Auto-Deletion of Repository Events
description: Enable auto-deletion of image events within a repository for maintenance.
keywords: registry, events, log, activity stream
---
## Overview
Docker Trusted Registry has a global setting for repository event auto-deletion. This allows event records to be removed as part of [garbage collection](../admin/configure/garbage-collection.md). DTR administrators can enable auto-deletion of repository events in DTR 2.6 based on specified conditions which are covered below.
## Steps
1. In your browser, navigate to `https://<dtr-url>` and log in with your admin credentials.
2. Select **System** from the left navigation pane which displays the **Settings** page by default.
3. Scroll down to **Repository Events** and turn on ***Auto-Deletion***.
![](../../images/auto-delete-repo-events-0.png){: .img-fluid .with-border}
4. Specify the conditions with which an event auto-deletion will be triggered.
![](../../images/auto-delete-repo-events-1.png){: .img-fluid .with-border}
DTR allows you to set your auto-deletion conditions based on the following optional repository event attributes:
| Name | Description | Example |
|:----------------|:---------------------------------------------------| :----------------|
| Age | Lets you remove events older than your specified number of hours, days, weeks or months| `2 months` |
| Max number of events | Lets you specify the maximum number of events allowed in the repositories. | `6000` |
If you check and specify both, events in your repositories will be removed during garbage collection if either condition is met. You should see a confirmation message right away.
5. Click **Start GC** if you're ready. Read more about [garbage collection](../admin/configure/garbage-collection/#under-the-hood) if you're unsure about this operation.
6. Navigate to **System > Job Logs** to confirm that `onlinegc` has happened.
![](../../images/auto-delete-repo-events-2.png){: .img-fluid .with-border}
## Where to go next
- [Manage job logs](/ee/dtr/admin/manage-jobs/audit-jobs-via-ui/)

View File

@ -0,0 +1,80 @@
---
title: DTR cache configuration reference
description: Learn about the different configuration options for DTR caches.
keywords: DTR, cache
---
DTR caches are based on Docker Registry, and use the same configuration
file format.
[Learn more about the configuration options](/registry/configuration.md).
The DTR cache extends the Docker Registry configuration file format by
introducing a new middleware called `downstream` that has three configuration
options: `blobttl`, `upstreams`, and `cas`:
```none
# Settings that you would include in a
# Docker Registry configuration file followed by
middleware:
registry:
- name: downstream
options:
blobttl: 24h
upstreams:
- <Externally-reachable address for upstream registry or content cache in format scheme://host:port>
cas:
- <Absolute path to next-hop upstream registry or content cache CA certificate in the container's filesystem>
```
Below you can find the description for each parameter, specific to DTR caches.
<table>
<tr>
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
<tr>
<td>
<code>blobttl</code>
</td>
<td>
no
</td>
<td>
A positive integer and an optional unit of time suffix to determine the TTL (Time to Live) value for blobs in the cache. If <code>blobttl</code> is configured, <code>storage.delete.enabled</code> must be set to <code>true</code>. Acceptable units of time are:
<ul>
<li><code>ns</code> (nanoseconds)</li>
<li><code>us</code> (microseconds)</li>
<li><code>ms</code> (milliseconds)</li>
<li><code>s</code> (seconds)</li>
<li><code>m</code> (minutes)</li>
<li><code>h</code> (hours)</li>
</ul>
If you omit the suffix, the system interprets the value as nanoseconds.
</td>
</tr>
<tr>
<td>
<code>cas</code>
</td>
<td>
no
</td>
<td>
An optional list of absolute paths to PEM-encoded CA certificates of upstream registries or content caches.
</td>
</tr>
<tr>
<td>
<code>upstreams</code>
</td>
<td>
yes
</td>
<td>
A list of externally-reachable addresses for upstream registries of content caches. If more than one host is specified, it will pull from registries in round-robin order.
</td>
</tr>
</table>

View File

@ -0,0 +1,76 @@
---
title: Configure caches for high availability
description: Learn how to deploy a DTR cache with fault tolerance and high
availability.
keywords: DTR, cache
---
If you're deploying a DTR cache in a zone with few users and with no uptime
SLAs, a [single cache service is enough for you](simple.md).
But if you want to make sure your DTR cache is always available to users
and is highly performant, you should configure your cache deployment for
high availability.
![Highly-available cache](../../../images/deploy-caches-ha-1.svg)
## System requirements
* Multiple nodes, one for each cache replica.
* A load balancer.
* Shared storage system that has read-after-write consistency.
The way you deploy a DTR cache is the same, whether you're deploying a single
replica or multiple ones. The difference is that you should configure the
replicas to store data using a shared storage system.
When using a shared storage system, once an image layer is cached, any replica
is able to serve it to users without having to fetch a new copy from DTR.
DTR caches support the following storage systems:
* Alibaba Cloud Object Storage Service
* Amazon S3
* Azure Blob Storage
* Google Cloud Storage
* NFS
* Openstack Swift
If you're using NFS as a shared storage system, make sure the shared
directory is configured with:
```
/dtr-cache *(rw,root_squash,no_wdelay)
```
This ensures read-after-write consistency for NFS.
You should also mount the NFS directory on each node where you'll deploy a
DTR cache replica.
## Label the DTR cache nodes
Use SSH to log in to a manager node of the swarm where you want to deploy
the DTR cache.
If you're using UCP to manage that swarm you can also use a client bundle to
configure your Docker CLI client to connect to that swarm.
Label each node that is going to run the cache replica, by running:
```
docker node update --label-add dtr.cache=true <node-hostname>
```
## Configure and deploy the cache
Create the cache configuration files by following the
[instructions for deploying a single cache replica](simple.md#prepare-the-cache-deployment).
Make sure you adapt the `storage` object, using the
[configuration options for the shared storage](/registry/configuration.md#storage)
of your choice.
## Configure your load balancer
The last step is to deploy a load balancer of your choice to load-balance
requests across the multiple replicas you deployed.

View File

@ -0,0 +1,72 @@
---
title: DTR cache overview
description: Deploy DTR caches in different geographical locations for users to
pull images faster.
keywords: DTR, cache
---
The further away you are from the geographical location where DTR is deployed,
the longer it will take to pull and push images.
This happens because the files being transferred from DTR to your machine
need to travel a longer distance, across multiple networks.
![Slow pull](../../../images/deploy-caches-1.svg)
To decrease the time to pull an image, you can deploy DTR caches geographically
closer to users.
Caches are transparent to users, since users still log in and pull images using
the DTR URL address. DTR checks if users are authorized to pull the image, and redirects the
request to the cache.
![Pull with cache](../../../images/deploy-caches-2.svg)
In this example, DTR is deployed on a datacenter in the United States, and
a cache is deployed in the Asia office.
Users in the Asia office update their user profile within DTR to fetch from
the cache in their office. They pull an image using:
```
# Log in to DTR
docker login dtr.example.org
# Pull image
docker image pull dtr.example.org/website/ui:3-stable
```
DTR authenticates the request and checks if the user has permission to pull the
image they are requesting. If they have permissions, they get an image
manifest containing the list of image layers to pull and redirecting them
to pull the images from the Asia cache.
When users request those image layers from the Asia cache, the cache pulls
them from DTR and keeps a copy that can be used to serve to other users without
having to pull the image layers from DTR again.
## Caches or mirroring policies
Use caches if you:
* Want to make image pulls faster for users in different geographical regions.
* Want to manage user permissions from a central place.
If you need users to be able to push images faster, or you want to implement
RBAC policies based on different regions, do not use caches.
Instead, deploy multiple DTR clusters and implement mirroring policies between
them.
![Mirroring policies](../../../images/deploy-caches-3.svg)
With mirroring policies you can set up a development pipeline where images
are automatically pushed between different DTR repositories, or across
DTR deployments.
As an example you can set up a development pipeline with three different stages.
Developers can push and pull images from the development environment,
only pull from QA, and have no access to Production.
With multiple DTR deployments you can control the permissions developers have
for each deployment, and you can create policies to automatically push images
from one deployment to the next.
[Learn more about deployment policies](../../../user/promotion-policies/index.md).

View File

@ -0,0 +1,343 @@
---
title: Deploy a DTR cache with Kubernetes
description: Deploy a DTR cache to allow users in remote geographical locations to pull images faster.
keywords: DTR, cache, kubernetes
---
This example guides you through deploying a DTR cache, assuming that you've got
a DTR deployment up and running. The below guide has been tested on
Universal Control Plane 3.1, however it should work on any Kubernetes Cluster
1.8 or higher.
The DTR cache is going to be deployed as a Kubernetes Deployment, so that
Kubernetes automatically takes care of scheduling and restarting the service if
something goes wrong.
We'll manage the cache configuration using a Kubernetes Config Map, and the TLS
certificates using Kubernetes secrets. This allows you to manage the
configurations securely and independently of the node where the cache is
actually running.
## Prepare the cache deployment
At the end of this exercise you should have the following file structure on your
workstation:
```
├── dtrcache.yaml # Yaml file to deploy cache with a single command
├── config.yaml # The cache configuration file
└── certs
   ├── cache.cert.pem # The cache public key certificate, including any intermediaries
   ├── cache.key.pem # The cache private key
   └── dtr.cert.pem # DTR CA certificate
```
### Create the DTR Cache certificates
The DTR cache will be deployed with a TLS endpoint. For this you will need to
generate a TLS ceritificate and key from a certificate authority. The way you
expose the DTR Cache will change the SANs required for
this certificate.
For example:
- If you are deploying the DTR Cache with an
[Ingress Object](https://kubernetes.io/docs/concepts/services-networking/ingress/)
you will need to use an external DTR cache address which resolves to your
ingress controller as part of your certificate.
- If you are exposing the DTR cache through a Kubernetes
[Cloud Provider](https://kubernetes.io/docs/concepts/services-networking/#loadbalancer)
then you will need the external Loadbalancer address as part of your
certificate.
- If you are exposing the DTR Cache through a
[Node Port](https://kubernetes.io/docs/concepts/services-networking/#nodeport)
or a Host Port you will need to use a node's FQDN as a SAN in your
certificate.
On your workstation, create a directory called `certs`. Within it place the
newly created certificate `cache.cert.pem` and key `cache.key.pem` for your DTR
cache. Also place the certificate authority (including any intermedite
certificate authorities) of the certificate from your DTR deployment. This could
be sourced from the main DTR deployment using curl.
```
$ curl -s https://<dtr-fqdn>/ca -o certs/dtr.cert.pem`.
```
### Create the DTR Config
The DTR Cache will take its configuration from a file mounted into the container.
Below is an example configuration file for the DTR Cache. This yaml should be
customised for your environment with the relevant external dtr cache, worker
node or external loadbalancer FQDN.
With this configuration, the cache fetches image layers from DTR and keeps a
local copy for 24 hours. After that, if a user requests that image layer, the
cache will fetch it again from DTR.
The cache, by default, is configured to store image data inside its container.
Therefore if something goes wrong with the cache service, and Kubernetes deploys
a new pod, cached data is not persisted. Data will not be lost as it is still
stored in the primary DTR. You can
[customize the storage parameters](/registry/configuration/#storage),
if you want the cached images to be backended by persistent storage.
> **Note**: Kubernetes Peristent Volumes or Persistent Volume Claims would have to be
> used to provide persistent backend storage capabilities for the cache.
```
cat > config.yaml <<EOF
version: 0.1
log:
level: info
storage:
delete:
enabled: true
filesystem:
rootdirectory: /var/lib/registry
http:
addr: 0.0.0.0:443
secret: generate-random-secret
host: https://<external-fqdn-dtrcache> # Could be DTR Cache / Loadbalancer / Worker Node external FQDN
tls:
certificate: /certs/cache.cert.pem
key: /certs/cache.key.pem
middleware:
registry:
- name: downstream
options:
blobttl: 24h
upstreams:
- https://<dtr-url> # URL of the Main DTR Deployment
cas:
- /certs/dtr.cert.pem
EOF
```
See [Configuration Options](/registry/configuration/#list-of-configuration-options) for a full list of registry configuration options.
### Define Kubernetes Resources
The Kubernetes Manifest file to deploy the DTR Cache is independent of how you
choose to expose the DTR cache within your environment. The below example has
been tested to work on Universal Control Plane 3.1, however it should work on
any Kubernetes Cluster 1.8 or higher.
```
cat > dtrcache.yaml <<EOF
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: dtr-cache
namespace: dtr
spec:
replicas: 1
selector:
matchLabels:
app: dtr-cache
template:
metadata:
labels:
app: dtr-cache
annotations:
seccomp.security.alpha.kubernetes.io/pod: docker/default
spec:
containers:
- name: dtr-cache
image: {{ page.dtr_org }}/{{ page.dtr_repo }}-content-cache:{{ page.dtr_version }}
command: ["bin/sh"]
args:
- start.sh
- /config/config.yaml
ports:
- name: https
containerPort: 443
volumeMounts:
- name: dtr-certs
readOnly: true
mountPath: /certs/
- name: dtr-cache-config
readOnly: true
mountPath: /config
volumes:
- name: dtr-certs
secret:
secretName: dtr-certs
- name: dtr-cache-config
configMap:
defaultMode: 0666
name: dtr-cache-config
EOF
```
## Create Kubernetes Resources
At this point you should have a file structure on your workstation which looks
like this:
```
├── dtrcache.yaml # Yaml file to deploy cache with a single command
├── config.yaml # The cache configuration file
└── certs
   ├── cache.cert.pem # The cache public key certificate
   ├── cache.key.pem # The cache private key
   └── dtr.cert.pem # DTR CA certificate
```
You will also need the `kubectl` command line tool configured to talk to your
Kubernetes cluster, either through a Kubernetes Config file or a [Universal
Control Plane client bundle](/ee/ucp/user-access/kubectl/).
First we will create a Kubernetes namespace to logically separate all of our
DTR cache components.
```
$ kubectl create namespace dtr
```
Create the Kubernetes Secrets, containing the DTR cache TLS certificates, and a
Kubernetes ConfigMap containing the DTR cache configuration file.
```
$ kubectl -n dtr create secret generic dtr-certs \
--from-file=certs/dtr.cert.pem \
--from-file=certs/cache.cert.pem \
--from-file=certs/cache.key.pem
$ kubectl -n dtr create configmap dtr-cache-config \
--from-file=config.yaml
```
Finally create the Kubernetes Deployment.
```
$ kubectl create -f dtrcache.yaml
```
You can check if the deployment has been successful by checking the running pods
in your cluster: `kubectl -n dtr get pods `
If you need to troubleshoot your deployment, you can use
`kubectl -n dtr describe pods <pods>` and / or `kubectl -n dtr logs <pods>`.
### Exposing the DTR Cache
For external access to the DTR cache we need to expose the Cache Pods to the
outside world. In Kubernetes there are multiple ways for you to expose a service,
dependent on your infrastructure and your environment. For more information,
see [Publishing services - service types
](https://kubernetes.io/docs/concepts/services-networking/#publishing-services-service-types) on the Kubernetes docs.
It is important though that you are consistent in exposing the cache through the
same interface you created a certificate for [previously](#create-the-dtr-cache-certificates).
Otherwise the TLS certificate may not be valid through this alternative
interface.
> #### DTR Cache Exposure
>
> You only need to expose your DTR cache through ***one*** external interface.
#### NodePort
The first example exposes the DTR cache through **NodePort**. In this example you would
have added a worker node's FQDN to the TLS Certificate in [step 1](#create-the-dtr-cache-certificates).
Here you will be accessing the DTR cache through an exposed port on a worker
node's FQDN.
```
cat > dtrcacheservice.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: dtr-cache
namespace: dtr
spec:
type: NodePort
ports:
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app: dtr-cache
EOF
kubectl create -f dtrcacheservice.yaml
```
To find out which port the DTR cache has been exposed on, you will need to run:
```
$ kubectl -n dtr get services
```
You can test that your DTR cache is externally reachable by using `curl` to hit
the API endpoint, using both a worker node's external address, and the **NodePort**.
```
curl -X GET https://<workernodefqdn>:<nodeport>/v2/_catalog
{"repositories":[]}
```
#### Ingress Controller
This second example will expose the DTR cache through an **ingress** object. In
this example you will need to create a DNS rule in your environment that will
resolve a DTR cache external FQDN address to the address of your ingress
controller. You should have also specified the same DTR cache external FQDN
address within the DTR cache certificate in [step 1](#create-the-dtr-cache-certificates).
> Note an ingress controller is a prerequisite for this example. If you have not
> deployed an ingress controller on your cluster, see [Layer 7 Routing for UCP](/ee/ucp/kubernetes/layer-7-routing). This
> ingress controller will also need to support SSL passthrough.
```
cat > dtrcacheservice.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
name: dtr-cache
namespace: dtr
spec:
selector:
app: dtr-cache
ports:
- protocol: TCP
port: 443
targetPort: 443
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dtr-cache
namespace: dtr
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/secure-backends: "true"
spec:
tls:
- hosts:
- <external-dtr-cache-fqdn> # Replace this value with your external DTR Cache address
rules:
- host: <external-dtr-cache-fqdn> # Replace this value with your external DTR Cache address
http:
paths:
- backend:
serviceName: dtr-cache
servicePort: 443
EOF
kubectl create -f dtrcacheservice.yaml
```
You can test that your DTR cache is externally reachable by using curl to hit
the API endpoint. The address should be the one you have defined above in the
serivce definition file.
```
curl -X GET https://external-dtr-cache-fqdn/v2/_catalog
{"repositories":[]}
```
## Next Steps
[Integrate your cache into DTR and configure users](simple#register-the-cache-with-dtr)

View File

@ -0,0 +1,272 @@
---
title: Deploy a DTR cache with Swarm
description: Deploy a DTR cache to make users in remove geographical locations
pull images faster.
keywords: DTR, cache
---
This example guides you in deploying a DTR cache, assuming that you've got
a DTR deployment up and running. It also assumes that you've provisioned
[multiple nodes and joined them into a swarm](strategy.md#system-requirements).
![Cache for Asia](../../../images/deploy-caches-simple-1.svg)
The DTR cache is going to be deployed as a Docker service, so that Docker
automatically takes care of scheduling and restarting the service if
something goes wrong.
We'll manage the cache configuration using a Docker configuration, and the TLS
certificates using Docker secrets. This allows you to manage the configurations
securely and independently of the node where the cache is actually running.
## Dedicate a node for the cache
To make sure the DTR cache is performant, it should be deployed on a node
dedicated just for it. Start by labelling the node where you want
to deploy the cache, so that you target the deployment to that node.
Use SSH to log in to a manager node of the swarm where you want to deploy
the DTR cache. If you're using UCP to manage that swarm, use a client bundle to
configure your Docker CLI client to connect to the swarm.
```
docker node update --label-add dtr.cache=true <node-hostname>
```
[Learn more about labelling nodes](/engine/swarm/manage-nodes.md#add-or-remove-label-metadata).
## Prepare the cache deployment
Create a file structure that looks like this:
```
├── docker-stack.yml # Stack file to deploy cache with a single command
├── config.yml # The cache configuration file
└── certs
   ├── cache.cert.pem # The cache public key certificate
   ├── cache.key.pem # The cache private key
   └── dtr.cert.pem # DTR CA certificate
```
Then add the following content to each of the files:
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" data-target="#tab1">docker-stack.yml</a></li>
<li><a data-toggle="tab" data-target="#tab2">config.yml</a></li>
<li><a data-toggle="tab" data-target="#tab3">cache.cert.pem</a></li>
<li><a data-toggle="tab" data-target="#tab4">cache.key.pem</a></li>
<li><a data-toggle="tab" data-target="#tab5">dtr.cert.pem</a></li>
</ul>
<div class="tab-content">
<div id="tab1" class="tab-pane fade in active">
<pre class="highlight">
<code>
version: "3.3"
services:
cache:
image: {{ page.dtr_org }}/{{ page.dtr_repo }}-content-cache:{{ page.dtr_version }}
entrypoint:
- /start.sh
- "/config.yml"
ports:
- 443:443
deploy:
replicas: 1
placement:
constraints: [node.labels.dtr.cache == true]
restart_policy:
condition: on-failure
configs:
- config.yml
secrets:
- dtr.cert.pem
- cache.cert.pem
- cache.key.pem
configs:
config.yml:
file: ./config.yml
secrets:
dtr.cert.pem:
file: ./certs/dtr.cert.pem
cache.cert.pem:
file: ./certs/cache.cert.pem
cache.key.pem:
file: ./certs/cache.key.pem
</code>
</pre>
<hr>
</div>
<div id="tab2" class="tab-pane fade">
<pre class="highlight">
<code>
version: 0.1
log:
level: info
storage:
delete:
enabled: true
filesystem:
rootdirectory: /var/lib/registry
http:
addr: 0.0.0.0:443
secret: generate-random-secret
host: https://&lt;cache-url&gt;
tls:
certificate: /run/secrets/cache.cert.pem
key: /run/secrets/cache.key.pem
middleware:
registry:
- name: downstream
options:
blobttl: 24h
upstreams:
- https://&lt;dtr-url&gt;:&lt;dtr-port&gt;
cas:
- /run/secrets/dtr.cert.pem
</code>
</pre>
<hr>
</div>
<div id="tab3" class="tab-pane fade" markdown="1">
Add the public key certificate for the cache here. If the certificate has been
signed by an intermediate certificate authority, append it's public key
certificate at the end of the file.
<hr>
</div>
<div id="tab4" class="tab-pane fade" markdown="1">
Add the unencrypted private key for the cache here.
<hr>
</div>
<div id="tab5" class="tab-pane fade" markdown="1">
The cache communicates with DTR using TLS. If you've customized DTR
to use TLS certificates issued by a globally trusted certificate authority,
the cache automatically trusts DTR.
But if you're using the default DTR configuration, or DTR is using TLS
certificates signed by your own certificate authority, you need to configure
the cache to trust DTR.
Add the DTR CA certificate to the `certs/dtr.cert.pem` file. You can
do this by running:
```
curl -sk https://<dtr-url>/ca > certs/dtr.cert.pem
```
<hr>
</div>
</div>
With this configuration, the cache fetches image layers from DTR and keeps
a local copy for 24 hours. After that, if a user requests that image layer,
the cache fetches it again from DTR.
The cache is configured to persist data inside its container.
If something goes wrong with the cache service, Docker automatically redeploys a
new container, but previously cached data is not persisted.
You can [customize the storage parameters](/registry/configuration.md#storage),
if you want to store the image layers using a persistent storage backend.
Also, the cache is configured to use port 443. If you're already using that
port in the swarm, update the deployment and configuration files to use another
port. Don't forget to create firewall rules for the port you choose.
## Deploy the cache
Now that everything is set up, you can deploy the cache by running:
```
docker stack deploy --compose-file docker-stack.yml dtr-cache
```
You can check if the cache has been successfully deployed by running:
```
docker stack ps dtr-cache
```
Docker should show the dtr-cache stack is running.
## Register the cache with DTR
Now that you've deployed a cache, you need to configure DTR to know about it.
This is done using the `POST /api/v0/content_caches` API. You can use the
DTR interactive API documentation to use this API.
In the DTR web UI, click the top-right menu, and choose **API docs**.
![](../../../images/deploy-caches-simple-2.png){: .with-border}
Navigate to the `POST /api/v0/content_caches` line and click it to expand.
In the **body** field include:
```
{
"name": "region-asia",
"host": "https://<cache-url>:<cache-port>"
}
```
Click the **Try it out!** button to make the API call.
![](../../../images/deploy-caches-simple-3.png){: .with-border}
## Configure your user account
Now that you've registered the cache with DTR, users can configure
their user profile to pull images from DTR or the cache.
In the DTR web UI, navigate to your **Account**, click the **Settings**
tab, and change the **Content Cache** settings to use the cache you deployed.
![](../../../images/deploy-caches-simple-4.png){: .with-border}
If you need to set this for multiple users at the same time, use the
`/api/v0/accounts/{username}/settings` API endpoint.
Now when you pull images, you'll be using the cache.
## Test that the cache is working
To validate that the cache is working as expected:
1. [Push an image to DTR](../../../user/manage-images/pull-and-push-images.md).
2. Make sure your user account is configured to use the cache.
3. Delete the image from your local system.
4. Pull the image from DTR.
To validate that the cache is actually serving your request, and to
troubleshoot misconfigurations, check the logs for the cache service
by running:
```
docker service logs --follow dtr-cache_cache
```
The most common causes of configuration are due to TLS authentication:
* DTR not trusting the cache TLS certificates.
* The cache not trusting DTR TLS certificates.
* Your machine not trusting DTR or the cache.
When this happens, check the cache logs to troubleshoot the
misconfiguration.
## Clean up sensitive files
The certificates and private keys are now managed by Docker in a secure way.
Don't forget to delete sensitive files you've created on disk, like the
private keys for the cache:
```
rm -rf certs
```

View File

@ -0,0 +1,58 @@
---
title: Cache deployment strategy
description: Learn how to deploy DTR caches across multiple datacenters to make
image pulls faster.
keywords: DTR, cache
---
The main reason to use a DTR cache is so that users can pull images from
a service that's geographically closer to them.
In this example a company has developers spread across three locations: United
States, Asia, and Europe. Developers working in the US office can pull their
images from DTR without problem, but developers in the Asia and Europe offices
complain that it takes them a long time to pulls images.
![Offices](../../../images/deploy-caches-strategy-1.svg)
To address that, you can deploy DTR caches in the Asia and Europe offices, so
that developers working from there can pull images much faster.
## Deployment overview
To deploy the DTR caches for this scenario, you need three datacenters:
* The US datacenter runs DTR configured for high availability.
* The Asia datacenter runs a DTR cache.
* The Europe datacenter runs another DTR cache.
![Offices](../../../images/deploy-caches-strategy-2.svg)
Both caches are configured to fetch images from DTR.
## System requirements
Before deploying a DTR cache in a datacenter, make sure you:
* Provision multiple nodes and install Docker on them.
* Join the nodes into a Swarm.
* Have one or more dedicated worker nodes just for running the DTR cache.
* Have TLS certificates to use for securing the cache.
* Have a shared storage system, if you want the cache to be highly available.
If you only plan on running a DTR cache on this datacenter, you just need
[Docker EE Basic](https://www.docker.com/pricing), which only includes the
Docker Engine.
If you plan on running other workloads on this datacenter, consider deploying
[Docker EE Standard or Advanced](https://www.docker.com/pricing).
This way you can enforce fine-grain control over cluster resources, and makes it
easier to monitor and manage your applications.
## Ports used
You can customize the port used by the DTR cache, so you'll have to configure
your firewall rules to make sure users can access the cache using the port
you chose.
By default the documentation guides you in deploying caches that are exposed
on port 443/TCP using the swarm routing mesh.

View File

@ -0,0 +1,45 @@
---
title: Enable single sign-on
description: Learn how to set up single sign-on between UCP and DTR, so that your users only have to authenticate once
keywords: dtr, login, sso
---
By default, users are shared between UCP and DTR, but you have to authenticate
separately on the web UI of both applications.
You can configure DTR to have single sign-on (SSO) with UCP, so that users only
have to authenticate once.
> **Note**: After configuring single sign-on with DTR, users accessing DTR via
> `docker login` should create an [access token](/ee/dtr/user/access-tokens/) and use it to authenticate.
## At installation time
When installing DTR, use the `docker/dtr install --dtr-external-url <url>`
option to enable SSO. When accessing the DTR web UI, users are redirected to the
UCP login page, and once they are authenticated, they're redirected to the URL
you provided to `--dtr-external-url`.
Use the domain name of DTR, or the domain name of a load balancer, if you're
using one, to load-balance requests across multiple DTR replicas.
## After install
In your browser, navigate to the DTR web UI, and choose **Settings**. In the
**General** tab, scroll to **Domain & proxies**.
Update the **Load balancer / public address** field to the url where users
should be redirected once they are logged in.
Use the domain name of DTR, or the domain name of a load balancer, if you're
using one, to load-balance requests across multiple DTR replicas.
Then enable **Use single sign-on**.
![](../../images/enable-sso-1.png){: .with-border}
Once you save, users are redirected to UCP for logging in, and redirected back to
DTR once they are authenticated.
## Where to go next
- [Use your own TLS certificates](use-your-own-tls-certificates.md)

View File

@ -0,0 +1,95 @@
---
title: Configure DTR image storage
description: Storage configuration for Docker Trusted Registry
keywords: dtr, storage drivers, NFS, Azure, S3
---
## Configure your storage backend
By default DTR uses the local filesystem of the node where it is running to
store your Docker images. You can configure DTR to use an external storage
backend, for improved performance or high availability.
![architecture diagram](../../../images/configure-external-storage-1.svg)
If your DTR deployment has a single replica, you can continue using the
local filesystem for storing your Docker images. If your DTR deployment has
multiple replicas, make sure all replicas are
using the same storage backend for high availability. Whenever a user pulls an image, the DTR
node serving the request needs to have access to that image.
DTR supports the following storage systems:
* Local filesystem
* [NFS](nfs.md)
* [Bind Mount](/storage/bind-mounts/)
* [Volume](/storage/volumes/)
* Cloud Storage Providers
* [Amazon S3](s3.md)
* [Microsoft Azure](/registry/storage-drivers/azure/)
* [OpenStack Swift](/registry/storage-drivers/swift/)
* [Google Cloud Storage](/registry/storage-drivers/gcs/)
> **Note**: Some of the previous links are meant to be informative and are not representative of DTR's implementation of these storage systems.
To configure the storage backend, log in to the DTR web interface
as an admin, and navigate to **System > Storage**.
![dtr settings](../../../images/configure-external-storage-2.png){: .with-border}
The storage configuration page gives you the most
common configuration options, but you have the option to upload a configuration file in `.yml`, `.yaml`, or `.txt` format.
See [Docker Registry Configuration](/registry/configuration.md) for configuration options.
## Local filesystem
By default, DTR creates a volume named `dtr-registry-<replica-id>` to store
your images using the local filesystem. You can customize the name and path of
the volume by using `docker/dtr install --dtr-storage-volume` or `docker/dtr reconfigure --dtr-storage-volume`.
> When running DTR 2.5 (with experimental online garbage collection) and 2.6.0 to 2.6.3, there is an issue with [reconfiguring DTR with `--nfs-storage-url`](/ee/dtr/release-notes#version-26) which leads to erased tags. Make sure to [back up your DTR metadata](/ee/dtr/admin/disaster-recovery/create-a-backup/#back-up-dtr-metadata) before you proceed. To work around the `--nfs-storage-url` flag issue, manually create a storage volume on each DTR node. If DTR is already installed in your cluster, [reconfigure DTR](https://success.docker.com/article/dtr-26-lost-tags-after-reconfiguring-storage#reconfigureusingalocalnfsvolume) with the `--dtr-storage-volume` flag using your newly-created volume.
{: .warning}
If you're deploying DTR with high-availability, you need to use NFS or any other
centralized storage backend so that all your DTR replicas have access to the
same images.
To check how much space your images are utilizing in the local filesystem, SSH into the DTR node and run:
```bash
{% raw %}
# Find the path to the volume
docker volume inspect dtr-registry-<replica-id>
# Check the disk usage
sudo du -hs \
$(dirname $(docker volume inspect --format '{{.Mountpoint}}' dtr-registry-<dtr-replica>))
{% endraw %}
```
### NFS
You can configure your DTR replicas to store images on an NFS partition, so that
all replicas can share the same storage backend.
[Learn how to configure DTR with NFS](nfs.md).
## Cloud Storage
### Amazon S3
DTR supports Amazon S3 or other storage systems that are S3-compatible like Minio.
[Learn how to configure DTR with Amazon S3](s3.md).
## Where to go next
- [Switch storage backends](storage-backend-migration.md)
- [Use NFS](nfs.md)
- [Use S3](s3.md)
- CLI reference pages
- [docker/dtr install](/reference/dtr/2.6/cli/install/)
- [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/)
- [docker/dtr restore](/reference/dtr/2.6/cli/restore/)

View File

@ -0,0 +1,87 @@
---
title: Use NFS
description: Learn how to integrate Docker Trusted Registry with NFS
keywords: registry, dtr, storage, nfs
---
You can configure DTR to store Docker images in an NFS directory. Starting in DTR 2.6,
changing storage backends involves initializing a new metadatastore instead of reusing an existing volume.
This helps facilitate [online garbage collection](/ee/dtr/admin/configure/garbage-collection/#under-the-hood).
See [changes to NFS reconfiguration below](/ee/dtr/admin/configure/external-storage/nfs/#reconfigure-dtr-to-use-nfs) if you have previously configured DTR to use NFS.
Before installing or configuring DTR to use an NFS directory, make sure that:
* The NFS server has been correctly configured
* The NFS server has a fixed IP address
* All hosts running DTR have the correct NFS libraries installed
To confirm that the hosts can connect to the NFS server, try to list the
directories exported by your NFS server:
```bash
showmount -e <nfsserver>
```
You should also try to mount one of the exported directories:
```bash
mkdir /tmp/mydir && sudo mount -t nfs <nfs server>:<directory> /tmp/mydir
```
## Install DTR with NFS
One way to configure DTR to use an NFS directory is at install time:
```bash
docker run -it --rm {{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} install \
--nfs-storage-url <nfs-storage-url> \
<other options>
```
Use the format `nfs://<nfs server>/<directory>` for the NFS storage URL. To support **NFS v4**, you can now specify additional options when running [docker/dtr install](/reference/dtr/2.6/cli/install/) with `--nfs-storage-url`.
When joining replicas to a DTR cluster, the replicas will pick up your storage
configuration, so you will not need to specify it again.
### Reconfigure DTR to use NFS
To support **NFS v4**, more NFS options have been added to the CLI. See [New Features for 2.6.0 - CLI](/ee/dtr/release-notes/#260) for updates to [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/).
> When running DTR 2.5 (with experimental online garbage collection) and 2.6.0 to 2.6.3, there is an issue with [reconfiguring and restoring DTR with `--nfs-storage-url`](/ee/dtr/release-notes#version-26) which leads to erased tags. Make sure to [back up your DTR metadata](/ee/dtr/admin/disaster-recovery/create-a-backup/#back-up-dtr-metadata) before you proceed. To work around the `--nfs-storage-url` flag issue, manually create a storage volume. If DTR is already installed in your cluster, [reconfigure DTR](/reference/dtr/2.6/cli/reconfigure/) with the `--dtr-storage-volume` flag using your newly-created volume.
>
> See [Reconfigure Using a Local NFS Volume]( https://success.docker.com/article/dtr-26-lost-tags-after-reconfiguring-storage#reconfigureusingalocalnfsvolume) for Docker's recommended recovery strategy.
{: .warning}
#### DTR 2.6.4
In DTR 2.6.4, a new flag, `--storage-migrated`, [has been added to `docker/dtr reconfigure`](/reference/dtr/2.6/cli/reconfigure/) which lets you indicate the migration status of your storage data during a reconfigure. [Upgrade to 2.6.4](/reference/dtr/2.6/cli/upgrade/) and follow [Best practice for data migration in 2.6.4](/ee/dtr/admin/configure/external-storage/storage-backend-migration/#best-practice-for-data-migration) when switching storage backends. The following shows you how to reconfigure DTR using an NFSv4 volume as a storage backend:
```bash
docker run --rm -it \
docker/dtr:{{ page.dtr_version}} reconfigure \
--ucp-url <ucp_url> \
--ucp-username <ucp_username> \
--nfs-storage-url <dtr-registry-nf>
--async-nfs
--storage-migrated
```
To reconfigure DTR to stop using NFS storage, leave the `--nfs-storage-url` option
blank:
```bash
docker run -it --rm {{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version}} reconfigure \
--nfs-storage-url ""
```
## Where to go next
- [Switch storage backends](storage-backend-migration.md)
- [Create a backup](/ee/dtr/admin/disaster-recovery/create-a-backup/)
- [Restore from a backup](/ee/dtr/admin/disaster-recovery/restore-from-backup/)
- [Configure where images are stored](index.md)
- CLI reference pages
- [docker/dtr install](/reference/dtr/2.6/cli/install/)
- [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/)
- [docker/dtr restore](/reference/dtr/2.6/cli/restore/)

View File

@ -0,0 +1,154 @@
---
title: Store images on Amazon S3
description: Learn how to configure Docker Trusted Registry to store Docker images on
Amazon S3
keywords: dtr, storage driver, s3
---
You can configure DTR to store Docker images on Amazon S3, or other file servers
with an S3-compatible API like Cleversafe or Minio.
Amazon S3 and compatible services store files in "buckets", and users have
permissions to read, write, and delete files from those buckets. When you
integrate DTR with Amazon S3, DTR sends all read and write operations to the
S3 bucket so that the images are persisted there.
## Create a bucket on Amazon S3
Before configuring DTR you need to create a bucket on Amazon S3.
To get faster pulls and pushes, you should create the S3 bucket on a region
that's physically close to the servers where DTR is running.
Start by
[creating a bucket](http://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html).
Then, as a best practice you should
[create a new IAM user](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html)
just for the DTR
integration and apply an IAM policy that ensures the user has limited permissions.
This user only needs permissions to access the bucket that you'll use to store
images, and be able to read, write, and delete files.
Here's an example of a policy like that:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListBucketMultipartUploads"
],
"Resource": "arn:aws:s3:::<bucket-name>"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucketMultipartUploads"
],
"Resource": "arn:aws:s3:::<bucket-name>/*"
}
]
}
```
## Configure DTR
Once you've created a bucket and user, you can configure DTR to use it.
In your browser, navigate to `https://<dtr-url`. Select **System > Storage**.
![](../../../images/configure-external-storage-2.png){: .with-border}
Select the **S3** option, and fill-in the information about the bucket and
user.
| Field | Description |
|:----------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Root directory | The path in the bucket where images are stored |
| AWS Region name | The region where the bucket is. [Learn more](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) |
| S3 bucket name | The name of the bucket to store the images |
| AWS access key | The access key to use to access the S3 bucket. This can be left empty if you're using an IAM policy. [Learn more](http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html) |
| AWS secret key | The secret key to use to access the S3 bucket. This can be left empty if you're using an IAM policy |
| Region endpoint | The endpoint name for the region you're using. [Learn more](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) |
There are also some advanced settings.
| Field | Description |
|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Signature version 4 auth | Authenticate the requests using AWS signature version 4. [Learn more](http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) |
| Use HTTPS | Secure all requests with HTTPS, or make requests in an insecure way |
| Skip TLS verification | Encrypt all traffic, but don't verify the TLS certificate used by the storage backend |
| Root CA certificate | The public key certificate of the root certificate authority that issued the storage backend certificate |
Once you click **Save**, DTR validates the configurations and saves the changes.
## Configure your clients
If you're using a TLS certificate in your storage backend that's not globally
trusted, you'll have to configure all Docker Engines that push or pull from DTR
to trust that certificate. When you push or pull an image DTR redirects the
requests to the storage backend, so if clients don't trust the TLS certificates
of both DTR and the storage backend, they won't be able to push or pull images.
[Learn how to configure the Docker client](../../../user/access-dtr/index.md).
And if you've configured DTR to skip TLS verification, you also need to
configure all Docker Engines that push or pull from DTR to skip TLS
verification. You do this by adding DTR to
the [list of insecure registries when starting Docker](/engine/reference/commandline/dockerd.md).
## Supported regions
DTR supports the following S3 regions:
| Region |
|:---------------|
| us-east-1 |
| us-east-2 |
| us-west-1 |
| us-west-2 |
| eu-west-1 |
| eu-west-2 |
| eu-central-1 |
| ap-south-1 |
| ap-southeast-1 |
| ap-southeast-2 |
| ap-northeast-1 |
| ap-northeast-2 |
| sa-east-1 |
| cn-north-1 |
| us-gov-west-1 |
| ca-central-1 |
## Update your S3 settings on the web interface
When running 2.5.x (with experimental garbage collection) or 2.6.0-2.6.4, there is an issue with [changing your S3 settings on the web interface](/ee/dtr/release-notes#version-26) which leads to erased metadata. Make sure to [back up your DTR metadata](/ee/dtr/admin/disaster-recovery/create-a-backup/#back-up-dtr-metadata) before you proceed.
## Restore DTR with S3
To [restore DTR using your previously configured S3 settings](https://success.docker.com/article/dtr-26-lost-tags-after-reconfiguring-storage#restoretocloudstorage), use `docker/dtr restore` with `--dtr-use-default-storage` to keep your metadata.
## Where to go next
- [Create a backup](/ee/dtr/admin/disaster-recovery/create-a-backup/)
- [Restore from a backup](/ee/dtr/admin/disaster-recovery/restore-from-backup/)
- [Configure where images are stored](index.md)
- CLI reference pages
- [docker/dtr install](/reference/dtr/2.6/cli/install/)
- [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/)
- [docker/dtr restore](/reference/dtr/2.6/cli/restore/)

View File

@ -0,0 +1,67 @@
---
title: Switch storage backends
description: Storage backend migration for Docker Trusted Registry
keywords: dtr, storage drivers, local volume, NFS, Azure, S3,
---
Starting in DTR 2.6, switching storage backends initializes a new metadata store and erases your existing tags. This helps facilitate online garbage collection, which has been introduced in 2.5 as an experimental feature. In earlier versions, DTR would subsequently start a `tagmigration` job to rebuild tag metadata from the file layout in the image layer store. This job has been discontinued for DTR 2.5.x (with garbage collection) and DTR 2.6, as your storage backend could get out of sync with your DTR metadata, like your manifests and existing repositories. As best practice, DTR storage backends and metadata should always be moved, backed up, and restored together.
## DTR 2.6.4 and above
In DTR 2.6.4, a new flag, `--storage-migrated`, [has been added to `docker/dtr reconfigure`](/reference/dtr/2.6/cli/reconfigure/) which lets you indicate the migration status of your storage data during a reconfigure. If you are not worried about losing your existing tags, you can skip the recommended steps below and [perform a reconfigure](/reference/dtr/2.6/cli/reconfigure/).
### Best practice for data migration
Docker recommends the following steps for your storage backend and metadata migration:
1. Disable garbage collection by selecting "Never" under **System > Garbage Collection**, so blobs referenced in the backup that you create continue to exist. See [Garbage collection](/ee/dtr/admin/configure/garbage-collection/) for more details. Make sure to keep it disabled while you're performing the metadata backup and migrating your storage data.
![](/ee/dtr/images/garbage-collection-0.png){: .img-fluid .with-border}
2. [Back up your existing metadata](/ee/dtr/admin/disaster-recovery/create-a-backup/#back-up-dtr-metadata). See [docker/dtr backup](/reference/dtr/2.6/cli/backup/) for CLI command description and options.
3. Migrate the contents of your current storage backend to the new one you are switching to. For example, upload your current storage data to your new NFS server.
4. [Restore DTR from your backup](/ee/dtr/admin/disaster-recovery/restore-from-backup/) and specify your new storage backend. See [docker/dtr destroy](/reference/dtr/2.6/cli/destroy/) and [docker/dtr restore](/reference/dtr/2.6/cli/backup/) for CLI command descriptions and options.
5. With DTR restored from your backup and your storage data migrated to your new backend, garbage collect any dangling blobs using the following API request:
```bash
curl -u <username>:$TOKEN -X POST "https://<dtr-url>/api/v0/jobs" -H "accept: application/json" -H "content-type: application/json" -d "{ \"action": \"onlinegc_blobs\" }"
```
On success, you should get a `202 Accepted` response with a job `id` and other related details. This ensures any blobs which are not referenced in your previously created backup get destroyed.
### Alternative option for data migration
If you have a long maintenance window, you can skip some steps from above and do the following:
1. Put DTR in "read-only" mode using the following API request:
```bash
curl -u <username>:$TOKEN -X POST "https://<dtr-url>/api/v0/meta/settings" -H "accept: application/json" -H "content-type: application/json" -d "{ \"readOnlyRegistry\": true }"
```
On success, you should get a `202 Accepted` response.
2. Migrate the contents of your current storage backend to the new one you are switching to. For example, upload your current storage data to your new NFS server.
3. [Reconfigure DTR](/reference/dtr/2.6/cli/reconfigure) while specifying the `--storage-migrated` flag to preserve your existing tags.
## DTR 2.6.0-2.6.4 and DTR 2.5 (with experimental garbage collection)
Make sure to [perform a backup](/ee/dtr/admin/disaster-recovery/create-a-backup/#back-up-dtr-data) before you change your storage backend when running DTR 2.5 (with online garbage collection) and 2.6.0-2.6.3. If you encounter an issue with lost tags, refer to the following resources:
* For changes to reconfigure and restore options in DTR 2.6, see [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/) and [docker/dtr restore](/reference/dtr/2.6/cli/restore).
* For Docker's recommended recovery strategies, see [DTR 2.6 lost tags after reconfiguring storage](https://success.docker.com/article/dtr-26-lost-tags-after-reconfiguring-storage).
* For NFS-specific changes, see [Use NFS](nfs.md).
* For S3-specific changes, see [Learn how to configure DTR with Amazon S3](s3.md).
Upgrade to [DTR 2.6.4](#dtr-264-and-above) and follow [best practice for data migration](#best-practice-for-data-migration) to avoid the wiped tags issue when moving from one NFS serverto another.
## Where to go next
- [Use NFS](nfs.md)
- [Use S3](s3.md)
- CLI reference pages
- [docker/dtr install](/reference/dtr/2.6/cli/install/)
- [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/)

View File

@ -0,0 +1,105 @@
---
title: Garbage collection
description: Save disk space by configuring the garbage collection settings in
Docker Trusted Registry
keywords: registry, online garbage collection, gc, space, disk space
---
You can configure the Docker Trusted Registry (DTR) to automatically delete unused image
layers, thus saving you disk space. This process is also known as garbage collection.
## How DTR deletes unused layers
First you configure DTR to run a garbage collection job on a fixed schedule. At
the scheduled time, DTR:
1. Identifies and marks unused image layers.
2. Deletes the marked image layers.
Starting in DTR 2.5, we introduced an experimental feature which lets you run garbage collection jobs
without putting DTR in read-only mode. As of v2.6, online garbage collection is no longer in
experimental mode. This means that the registry no longer has to be in read-only mode (or offline)
during garbage collection.
## Schedule garbage collection
In your browser, navigate to `https://<dtr-url>` and log in with your credentials. Select **System** on the left navigation pane, and then click
the **Garbage collection** tab to schedule garbage collection.
![](../../images/garbage-collection-0.png){: .img-fluid .with-border}
Select for how long the garbage collection job should run:
* Until done: Run the job until all unused image layers are deleted.
* For x minutes: Only run the garbage collection job for a maximum of x minutes
at a time.
* Never: Never delete unused image layers.
If you select ***Until done*** or ***For x minutes***, you can specify a recurring schedule in UTC (Coordinated Universal Time) with the following options:
* Custom cron schedule - (Hour, Day of Month, Month, Weekday)
* Daily at midnight UTC
* Every Saturday at 1am UTC
* Every Sunday at 1am UTC
* Do not repeat
![](../../images/garbage-collection-1.png){: .with-border}
Once everything is configured you can choose to **Save & Start** to
run the garbage collection job immediately, or just **Save** to run the job on the next
scheduled interval.
## Review the garbage collection job log
In v2.5, you were notified with a banner under main navigation that no one can push images while a garbage collection job is running. With v2.6, this is no longer the case since garbage collection now happens while DTR is online and writable.
If you clicked **Save & Start** previously, verify that the garbage collection routine started by navigating to **Job Logs**.
![](../../images/garbage-collection-2.png){: .with-border}
## Under the hood
Each image stored in DTR is made up of multiple files:
* A list of image layers that are unioned which represents the image filesystem
* A configuration file that contains the architecture of the image and other
metadata
* A manifest file containing the list of all layers and configuration file for
an image
All these files are tracked in DTR's metadata store in RethinkDB. These files
are tracked in a content-addressable way such that a file corresponds to
a cryptographic hash of the file's content. This means that if two image tags hold exactly the same content,
DTR only stores the image content once while making hash collisions nearly impossible,
even if the tag name is different.
As an example, if `wordpress:4.8` and `wordpress:latest` have the same content,
the content will only be stored once. If you delete one of these tags, the other won't
be deleted.
This means that when you delete an image tag, DTR cannot delete the underlying
files of that image tag since other tags may also use the same files.
To facilitate online garbage collection, DTR makes a couple of changes to how it uses the storage
backend:
1. Layer links &ndash; the references within repository directories to
their associated blobs &ndash; are no longer in the storage backend. That is because DTR stores these references in RethinkDB instead to enumerate through
them during the marking phase of garbage collection.
2. Any layers created after an upgrade to 2.6 are no longer content-addressed in
the storage backend. Many cloud provider backends do not give the sequential
consistency guarantees required to deal with the simultaneous deleting and
re-pushing of a layer in a predictable manner. To account for this, DTR assigns
each newly pushed layer a unique ID and performs the translation from content hash
to ID in RethinkDB.
To delete unused files, DTR does the following:
1. Establish a cutoff time
2. Mark each referenced manifest file with a timestamp. When manifest files
are pushed to DTR, they are also marked with a timestamp
3. Sweep each manifest file that does not have a timestamp after the cutoff time
4. If a file is never referenced &ndash; which means no image tag uses it &ndash; delete the file
5. Repeat the process for blob links and blob descriptors.
## Where to go next
- [Deploy DTR caches](deploy-caches/index.md)

View File

@ -0,0 +1,38 @@
---
title: License your installation
description: Learn how to license your Docker Trusted Registry installation.
keywords: dtr, install, license
---
By default, you don't need to license your Docker Trusted Registry. When
installing DTR, it automatically starts using the same license file used on
your Docker Universal Control Plane cluster.
However, there are some situations when you have to manually license your
DTR installation:
* When upgrading to a new major version,
* When your current license expires.
## Download your license
Go to [Docker Hub](https://hub.docker.com/editions/enterprise/docker-ee-trial)
to download a trial license.
![](../../images/license-1.png){: .with-border}
## License your installation
Once you've downloaded the license file, you can apply it to your DTR
installation. Navigate to the **DTR web UI**, and then go to the **Settings
page**.
![](../../images/license-2.png){: .with-border}
Click the **Apply new license** button, and upload your new license file.
## Where to go next
- [Enable single sign-on](enable-single-sign-on.md)

View File

@ -0,0 +1,92 @@
---
title: Set up high availability
description: Lean how to scale Docker Trusted Registry by adding and removing replicas.
keywords: dtr, install, deploy
---
Docker Trusted Registry is designed to scale horizontally as your usage
increases. You can add more replicas to make DTR scale to your demand and for
high availability.
All DTR replicas run the same set of services and changes to their configuration
are automatically propagated to other replicas.
![](../../images/set-up-high-availability-1.svg)
To make DTR tolerant to failures, add additional replicas to the DTR cluster.
| DTR replicas | Failures tolerated |
|:------------:|:------------------:|
| 1 | 0 |
| 3 | 1 |
| 5 | 2 |
| 7 | 3 |
When sizing your DTR installation for high-availability,
follow these rules of thumb:
* Don't create a DTR cluster with just two replicas. Your cluster
won't tolerate any failures, and it's possible that you experience performance
degradation.
* When a replica fails, the number of failures tolerated by your cluster
decreases. Don't leave that replica offline for long.
* Adding too many replicas to the cluster might also lead to performance
degradation, as data needs to be replicated across all replicas.
To have high-availability on UCP and DTR, you need a minimum of:
* 3 dedicated nodes to install UCP with high availability,
* 3 dedicated nodes to install DTR with high availability,
* As many nodes as you want for running your containers and applications.
You also need to configure the DTR replicas to share the
[same object storage](external-storage/index.md).
## Join more DTR replicas
To add replicas to an existing DTR deployment:
1. Use ssh to log into any node that is already part of UCP.
2. Run the DTR join command:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} join \
--ucp-node <ucp-node-name> \
--ucp-insecure-tls
```
Where the `--ucp-node` is the hostname of the UCP node where you want to
deploy the DTR replica. `--ucp-insecure-tls` tells the command to trust the
certificates used by UCP.
3. If you have a load balancer, add this DTR replica to the load balancing pool.
## Remove existing replicas
To remove a DTR replica from your deployment:
1. Use ssh to log into any node that is part of UCP.
2. Run the DTR remove command:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} remove \
--ucp-insecure-tls
```
You will be prompted for:
* Existing replica id: the id of any healthy DTR replica of that cluster
* Replica id: the id of the DTR replica you want to remove. It can be the id of an
unhealthy replica
* UCP username and password: the administrator credentials for UCP
If you're load-balancing user requests across multiple DTR replicas, don't
forget to remove this replica from the load balancing pool.
## Where to go next
- [Set up vulnerability scans](set-up-vulnerability-scans.md)

View File

@ -0,0 +1,192 @@
---
title: Set up Security Scanning in DTR
description: Enable and configure Docker Security Scanning for Docker Trusted Registry.
keywords: registry, scanning, security scan, vulnerability, CVE
redirect_from:
- /datacenter/dtr/2.2/guides/admin/configure/set-up-vulnerability-scans/
---
This page explains how to set up and enable Docker Security Scanning on an
existing installation of Docker Trusted Registry.
## Prerequisites
These instructions assume that you have already installed Docker Trusted
Registry, and have access to an account on the DTR instance with administrator
access.
Before you begin, make sure that you or your organization has purchased a DTR
license that includes Docker Security Scanning, and that your Docker ID can
access and download this license from the Docker Hub.
If you are using a license associated with an individual account, no additional
action is needed. If you are using a license associated with an organization
account, you may need to make sure your Docker ID is a member of the `Owners`
team. Only `Owners` team members can download license files for an Organization.
If you will be allowing the Security Scanning database to update itself
automatically, make sure that the server hosting your DTR instance can access
`https://dss-cve-updates.docker.com/` on the standard https port 443.
## Get the security scanning license.
If your DTR instance already has a license that includes Security Scanning, skip
this step and proceed to [enable DTR Security Scanning](#enable-dtr-security-scanning).
> **Tip**: To check if your existing DTR license includes scanning, navigate
> to the DTR **Settings** page, and click **Security**. If an "Enable scanning"
> toggle appears, the license includes scanning.
If your current DTR license doesn't include scanning, you must first download
the new license.
1. Log in to the Docker Hub using a Docker ID with access to the license you need.
2. In the top right corner, click your user account icon, and select **My Content**.
3. Locate **Docker Enterprise Edition** in the content list, and click **Setup**.
4. Click **License Key** to download the license.
![](../../images/security-scanning-setup-1.png){: .with-border}
Next, install the new license on the DTR instance.
7. Log in to your DTR instance using an administrator account.
8. Click **Settings** in the left navigation.
9. On the **General** tab click **Apply new license**.
A file browser dialog appears.
10. Navigate to where you saved the license key (`.lic`) file, select it, and click **Open**.
![](../../images/security-scanning-setup-2.png){: .with-border}
Proceed to [enable DTR Security Scanning](#enable-dtr-security-scanning).
## Enable DTR security scanning
To enable security scanning in DTR:
1. Log in to your DTR instance with an administrator account.
2. Click **Settings** in the left navigation.
3. Click the **Security** tab.
> **Note**: If you see a message on this tab telling you to contact your Docker sales representative, then the license installed on this DTR instance does not include Docker Security Scanning. Check that you have purchased Security Scanning, and that the DTR instance is using the latest license file.
4. Click the **Enable scanning** toggle so that it turns blue and says "on".
![](../../images/security-scanning-setup-3.png){: .with-border}
5. Next, provide a security database for the scanner. **Security scanning will not function until DTR has a security database to use.**
By default, security scanning is enabled in **Online** mode. In this mode,
DTR attempts to download a security database from a Docker server. If your
installation cannot access `https://dss-cve-updates.docker.com/` you must
manually upload a `.tar` file containing the security database.
- If you are using `Online` mode, the DTR instance will contact a Docker server, download the latest vulnerability database, and install it. Scanning can begin once this process completes.<!--(TODO: no completion or confirmation message?) -->
- If you are using `Offline` mode, use the instructions in [Update scanning database - offline mode](#update-cve-database---offline-mode) to upload an initial security database.
By default when Security Scanning is enabled, new repositories will automatically scan on `docker push`. If you had existing repositories before you enabled security scanning, you might want to [change repository scanning behavior](#set-repository-scanning-mode).
## Set repository scanning mode
Two modes are available when Security Scanning is enabled:
- `Scan on push & Scan manually`: the image is re-scanned on each `docker push` to the repository, and whenever a user with `write` access clicks the **Start Scan** links or **Scan** button.
- `Scan manually`: the image is scanned only when a user with `write` access clicks the **Start Scan** links or **Scan** button.
By default, _new_ repositories are set to `Scan on push & Scan manually`, but
you can change this setting during repository creation.
![](../../images/security-scanning-setup-4.png){: .with-border}
Any repositories that existed before scanning was enabled are set to `Scan manually` mode by default. If these repositories are still in use, you can change this setting from each repository's **Settings** page.
> **Note**: To change an individual repository's scanning mode, you must have
`write` or `admin` access to the repo.
To change an individual repository's scanning mode:
1. Navigate to the repository, and click the **Settings** tab.
2. Scroll down to the **Image scanning** section.
3. Select the desired scanning mode.
![](../../images/security-scanning-setup-5.png){: .with-border}
## Update the CVE scanning database
Docker Security Scanning indexes the components in your DTR images and compares
them against a known CVE database. When new vulnerabilities are reported, Docker
Security Scanning matches the components in new CVE reports to the indexed
components in your images, and quickly generates an updated report.
Users with administrator access to DTR can check when the CVE database was last updated from the **Security** tab in the DTR **Settings** pages.
### Update CVE database - online mode
By default Docker Security Scanning checks automatically for updates to the
vulnerability database, and downloads them when available. If your installation
does not have access to the public internet, use the [Offline mode instructions below](#update-cve-database-offline-mode).
To ensure that DTR can access these updates, make sure that the host can reach
`https://dss-cve-updates.docker.com/` on port 443 using https.
DTR checks for new CVE database updates at 3:00 AM UTC every day. If an update
is found it is downloaded and applied without interrupting any scans in
progress. Once the update is complete, the security scanning system looks for
new vulnerabilities in the indexed components.
To set the update mode to Online:
1. Log in to DTR as a user with administrator rights.
2. Click **Settings** in the left navigation and click **Security**.
3. Click **Online**.
Your choice is saved automatically.
> **Tip**: DTR also checks for CVE database updates when scanning is first enabled, and when you switch update modes. If you need to check for a CVE database update immediately, you can briefly switch modes from online to offline and back again.
### Update CVE database - offline mode
To update the CVE database for your DTR instance when it cannot contact the update server, you download and install a `.tar` file that contains the database updates. To download the file:
1. Log in to [Docker Hub](https://hub.docker.com/).
If you are a member of an Organization managing licenses using Docker Hub,
make sure your account is a member of the `Owners` team. Only Owners can
view and manage licenses and other entitlements for Organizations from
Docker Hub.
2. In the top right corner, click your user account icon, and select **My Content**.
3. If necessary, select an organization account from the **Accounts** menu at the upper right.
4. Locate your Docker EE Advanced subscription or trial.
5. Click **Setup** button.
![](../../images/security-scanning-setup-6.png){: .with-border}
6. Click **Download CVE Vulnerability Database** link to download the database file.
![](../../images/security-scanning-setup-7.png){: .with-border}
If you run into problems, contact us at nautilus-feedback@docker.com for the file.
To manually update the DTR CVE database from a `.tar` file:
1. Log in to DTR as a user with administrator rights.
2. Click **Settings** in the left navigation and click **Security**.
4. Click **Upload .tar database file**.
5. Browse to the latest `.tar` file that you received, and click **Open**.
DTR installs the new CVE database, and begins checking already indexed images
for components that match new or updated vulnerabilities.
> **Tip**: The Upload button is unavailable while DTR applies CVE database updates.
## Enable or disable automatic database updates
To change the update mode:
1. Log in to DTR as a user with administrator rights.
2. Click **Settings** in the left navigation and click **Security**.
3. Click **Online/Offline**.
Your choice is saved automatically.
## Where to go next
- [Deploy DTR caches](deploy-caches/index.md)

View File

@ -0,0 +1,280 @@
---
title: Use a load balancer
description: Learn how to configure a load balancer to balance user requests across multiple Docker Trusted Registry replicas.
keywords: dtr, load balancer
---
Once youve joined multiple DTR replicas nodes for
[high-availability](set-up-high-availability.md), you can configure your own
load balancer to balance user requests across all replicas.
![](../../images/use-a-load-balancer-1.svg)
This allows users to access DTR using a centralized domain name. If a replica
goes down, the load balancer can detect that and stop forwarding requests to
it, so that the failure goes unnoticed by users.
DTR exposes several endpoints you can use to assess if a DTR replica is healthy
or not:
* `/_ping`: Is an unauthenticated endpoint that checks if the DTR replica is
healthy. This is useful for load balancing or other automated health check tasks.
* `/nginx_status`: Returns the number of connections being handled by the
NGINX front-end used by DTR.
* `/api/v0/meta/cluster_status`: Returns extensive information about all DTR
replicas.
## Load balance DTR
DTR does not provide a load balancing service. You can use an on-premises
or cloud-based load balancer to balance requests across multiple DTR replicas.
> Additional load balancer requirements for UCP
>
> If you are also using UCP, there are [additional requirements](https://docs.docker.com/ee/ucp/admin/configure/join-nodes/use-a-load-balancer/#load-balancing-ucp-and-dtr) if you plan to load balance both UCP and DTR using the same load balancer.
>
>{: .important}
You can use the unauthenticated `/_ping` endpoint on each DTR replica,
to check if the replica is healthy and if it should remain in the load balancing
pool or not.
Also, make sure you configure your load balancer to:
* Load balance TCP traffic on ports 80 and 443.
* Not terminate HTTPS connections.
* Not buffer requests.
* Forward the `Host` HTTP header correctly.
* Have no timeout for idle connections, or set it to more than 10 minutes.
The `/_ping` endpoint returns a JSON object for the replica being queried of
the form:
```json
{
"Error": "error message",
"Healthy": true
}
```
A response of `"Healthy": true` means the replica is suitable for taking
requests. It is also sufficient to check whether the HTTP status code is 200.
An unhealthy replica will return 503 as the status code and populate `"Error"`
with more details on any one of these services:
* Storage container (registry)
* Authorization (garant)
* Metadata persistence (rethinkdb)
* Content trust (notary)
Note that this endpoint is for checking the health of a single replica. To get
the health of every replica in a cluster, querying each replica individually is
the preferred way to do it in real time.
## Configuration examples
Use the following examples to configure your load balancer for DTR.
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" data-target="#nginx" data-group="nginx">NGINX</a></li>
<li><a data-toggle="tab" data-target="#haproxy" data-group="haproxy">HAProxy</a></li>
<li><a data-toggle="tab" data-target="#aws">AWS LB</a></li>
</ul>
<div class="tab-content">
<div id="nginx" class="tab-pane fade in active" markdown="1">
```conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
stream {
upstream dtr_80 {
server <DTR_REPLICA_1_IP>:80 max_fails=2 fail_timeout=30s;
server <DTR_REPLICA_2_IP>:80 max_fails=2 fail_timeout=30s;
server <DTR_REPLICA_N_IP>:80 max_fails=2 fail_timeout=30s;
}
upstream dtr_443 {
server <DTR_REPLICA_1_IP>:443 max_fails=2 fail_timeout=30s;
server <DTR_REPLICA_2_IP>:443 max_fails=2 fail_timeout=30s;
server <DTR_REPLICA_N_IP>:443 max_fails=2 fail_timeout=30s;
}
server {
listen 443;
proxy_pass dtr_443;
}
server {
listen 80;
proxy_pass dtr_80;
}
}
```
</div>
<div id="haproxy" class="tab-pane fade" markdown="1">
```conf
global
log /dev/log local0
log /dev/log local1 notice
defaults
mode tcp
option dontlognull
timeout connect 5s
timeout client 50s
timeout server 50s
timeout tunnel 1h
timeout client-fin 50s
### frontends
# Optional HAProxy Stats Page accessible at http://<host-ip>:8181/haproxy?stats
frontend dtr_stats
mode http
bind 0.0.0.0:8181
default_backend dtr_stats
frontend dtr_80
mode tcp
bind 0.0.0.0:80
default_backend dtr_upstream_servers_80
frontend dtr_443
mode tcp
bind 0.0.0.0:443
default_backend dtr_upstream_servers_443
### backends
backend dtr_stats
mode http
option httplog
stats enable
stats admin if TRUE
stats refresh 5m
backend dtr_upstream_servers_80
mode tcp
option httpchk GET /_ping HTTP/1.1\r\nHost:\ <DTR_FQDN>
server node01 <DTR_REPLICA_1_IP>:80 check weight 100
server node02 <DTR_REPLICA_2_IP>:80 check weight 100
server node03 <DTR_REPLICA_N_IP>:80 check weight 100
backend dtr_upstream_servers_443
mode tcp
option httpchk GET /_ping HTTP/1.1\r\nHost:\ <DTR_FQDN>
server node01 <DTR_REPLICA_1_IP>:443 weight 100 check check-ssl verify none
server node02 <DTR_REPLICA_2_IP>:443 weight 100 check check-ssl verify none
server node03 <DTR_REPLICA_N_IP>:443 weight 100 check check-ssl verify none
```
</div>
<div id="aws" class="tab-pane fade" markdown="1">
```json
{
"Subnets": [
"subnet-XXXXXXXX",
"subnet-YYYYYYYY",
"subnet-ZZZZZZZZ"
],
"CanonicalHostedZoneNameID": "XXXXXXXXXXX",
"CanonicalHostedZoneName": "XXXXXXXXX.us-west-XXX.elb.amazonaws.com",
"ListenerDescriptions": [
{
"Listener": {
"InstancePort": 443,
"LoadBalancerPort": 443,
"Protocol": "TCP",
"InstanceProtocol": "TCP"
},
"PolicyNames": []
}
],
"HealthCheck": {
"HealthyThreshold": 2,
"Interval": 10,
"Target": "HTTPS:443/_ping",
"Timeout": 2,
"UnhealthyThreshold": 4
},
"VPCId": "vpc-XXXXXX",
"BackendServerDescriptions": [],
"Instances": [
{
"InstanceId": "i-XXXXXXXXX"
},
{
"InstanceId": "i-XXXXXXXXX"
},
{
"InstanceId": "i-XXXXXXXXX"
}
],
"DNSName": "XXXXXXXXXXXX.us-west-2.elb.amazonaws.com",
"SecurityGroups": [
"sg-XXXXXXXXX"
],
"Policies": {
"LBCookieStickinessPolicies": [],
"AppCookieStickinessPolicies": [],
"OtherPolicies": []
},
"LoadBalancerName": "ELB-DTR",
"CreatedTime": "2017-02-13T21:40:15.400Z",
"AvailabilityZones": [
"us-west-2c",
"us-west-2a",
"us-west-2b"
],
"Scheme": "internet-facing",
"SourceSecurityGroup": {
"OwnerAlias": "XXXXXXXXXXXX",
"GroupName": "XXXXXXXXXXXX"
}
}
```
</div>
</div>
You can deploy your load balancer using:
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" data-target="#nginx-2" data-group="nginx">NGINX</a></li>
<li><a data-toggle="tab" data-target="#haproxy-2" data-group="haproxy">HAProxy</a></li>
</ul>
<div class="tab-content">
<div id="nginx-2" class="tab-pane fade in active" markdown="1">
```conf
# Create the nginx.conf file, then
# deploy the load balancer
docker run --detach \
--name dtr-lb \
--restart=unless-stopped \
--publish 80:80 \
--publish 443:443 \
--volume ${PWD}/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx:stable-alpine
```
</div>
<div id="haproxy-2" class="tab-pane fade" markdown="1">
```conf
# Create the haproxy.cfg file, then
# deploy the load balancer
docker run --detach \
--name dtr-lb \
--publish 443:443 \
--publish 80:80 \
--publish 8181:8181 \
--restart=unless-stopped \
--volume ${PWD}/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro \
haproxy:1.7-alpine haproxy -d -f /usr/local/etc/haproxy/haproxy.cfg
```
</div>
</div>
## Where to go next
- [Backups and disaster recovery](../disaster-recovery/index.md)
- [Monitor and troubleshoot](../monitor-and-troubleshoot/index.md)

View File

@ -0,0 +1,46 @@
---
title: Use a web proxy
description: Learn how to configure Docker Content Trust to use a web proxy to
reach external services.
keywords: dtr, configure, http, proxy
---
Docker Trusted Registry makes outgoing connections to check for new versions,
automatically renew its license, and update its vulnerability database.
If DTR can't access the internet, then you'll have to manually apply updates.
One option to keep your environment secure while still allowing DTR access to
the internet is to use a web proxy. If you have an HTTP or HTTPS proxy, you
can configure DTR to use it. To avoid downtime you should do this configuration
outside business peak hours.
As an administrator, log into a node where DTR is deployed, and run:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} reconfigure \
--http-proxy http://<domain>:<port> \
--https-proxy https://<doman>:<port> \
--ucp-insecure-tls
```
To confirm how DTR is configured, check the **Settings** page on the web UI.
![DTR settings](../../images/use-a-web-proxy-1.png){: .with-border}
If by chance the web proxy requires authentication you can submit the username
and password, in the command, as shown below:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} reconfigure \
--http-proxy username:password@<domain>:<port> \
--https-proxy username:password@<doman>:<port> \
--ucp-insecure-tls
```
> **Note**: DTR will hide the password portion of the URL, when it is displayed in the DTR UI.
## Where to go next
- [Configure garbage collection](garbage-collection.md)

View File

@ -0,0 +1,44 @@
---
title: Use your own TLS certificates
description: Learn how to configure Docker Trusted Registry with your own TLS certificates.
keywords: dtr, tls
---
By default the DTR services are exposed using HTTPS, to ensure all
communications between clients and DTR is encrypted. Since DTR
replicas use self-signed certificates for this, when a client accesses
DTR, their browsers won't trust this certificate, so the browser displays a
warning message.
You can configure DTR to use your own certificates, so that it is automatically
trusted by your users' browser and client tools.
## Replace the server certificates
To configure DTR to use your own certificates and keys, go to the
**DTR web UI**, navigate to the **Settings** page, and scroll down to the
**Domain** section.
![](../../images/use-your-certificates-1.png){: .with-border}
Set the DTR domain name and upload the certificates and key:
* Load balancer/public address, is the domain name clients will use to access DTR.
* TLS certificate, is the server certificate and any intermediate CA public
certificates. This certificate needs to be valid for the DTR public address,
and have SANs for all addresses used to reach the DTR replicas, including load
balancers.
* TLS private key is the server private key.
* TLS CA is the root CA public certificate.
Finally, click **Save** for the changes to take effect.
If you're using certificates issued by a globally trusted certificate authority,
any web browser or client tool should now trust DTR. If you're using an internal
certificate authority, you'll need to configure your system to trust that
certificate authority.
## Where to go next
- [Set up external storage](external-storage/index.md)

View File

@ -0,0 +1,223 @@
---
title: Create a backup
description: Learn how to create a backup of Docker Trusted Registry, for disaster recovery.
keywords: dtr, disaster recovery
toc_max_header: 3
---
{% assign metadata_backup_file = "dtr-metadata-backup.tar" %}
{% assign image_backup_file = "dtr-image-backup.tar" %}
## Data managed by DTR
Docker Trusted Registry maintains data about:
| Data | Description |
|:-----------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|
| Configurations | The DTR cluster configurations |
| Repository metadata | The metadata about the repositories and images deployed |
| Access control to repos and images | Permissions for teams and repositories |
| Notary data | Notary tags and signatures |
| Scan results | Security scanning results for images |
| Certificates and keys | The certificates, public keys, and private keys that are used for mutual TLS communication |
| Images content | The images you push to DTR. This can be stored on the file system of the node running DTR, or other storage system, depending on the configuration |
This data is persisted on the host running DTR, using named volumes.
[Learn more about DTR named volumes](../../architecture.md).
To perform a backup of a DTR node, run the [docker/dtr backup](/reference/dtr/2.6/cli/backup/) command. This
command backs up the following data:
| Data | Backed up | Description |
|:-----------------------------------|:----------|:---------------------------------------------------------------|
| Configurations | yes | DTR settings |
| Repository metadata | yes | Metadata such as image architecture and size |
| Access control to repos and images | yes | Data about who has access to which images |
| Notary data | yes | Signatures and digests for images that are signed |
| Scan results | yes | Information about vulnerabilities in your images |
| Certificates and keys | yes | TLS certificates and keys used by DTR |
| Image content | no | Needs to be backed up separately, depends on DTR configuration |
| Users, orgs, teams | no | Create a UCP backup to back up this data |
| Vulnerability database | no | Can be redownloaded after a restore |
## Back up DTR data
To create a backup of DTR, you need to:
1. Back up image content
2. Back up DTR metadata
You should always create backups from the same DTR replica, to ensure a smoother
restore. If you have not previously performed a backup, the web interface displays a warning for you to do so:
![](/ee/dtr/images/backup-warning.png)
#### Find your replica ID
Since you need your DTR replica ID during a backup, the following covers a few ways for you to determine your replica ID:
##### UCP web interface
You can find the list of replicas by navigating to **Shared Resources > Stacks** or **Swarm > Volumes** (when using [swarm mode](/engine/swarm/)) on the UCP web interface.
##### UCP client bundle
From a terminal [using a UCP client bundle]((/ee/ucp/user-access/cli/)), run:
{% raw %}
```bash
docker ps --format "{{.Names}}" | grep dtr
# The list of DTR containers with <node>/<component>-<replicaID>, e.g.
# node-1/dtr-api-a1640e1c15b6
```
{% endraw %}
##### SSH access
Another way to determine the replica ID is to log into a DTR node using SSH and run the following:
{% raw %}
```bash
REPLICA_ID=$(docker ps --format '{{.Names}}' -f name=dtr-rethink | cut -f 3 -d '-')
&& echo $REPLICA_ID
```
{% endraw %}
### Back up image content
Since you can configure the storage backend that DTR uses to store images,
the way you back up images depends on the storage backend you're using.
If you've configured DTR to store images on the local file system or NFS mount,
you can back up the images by using SSH to log into a DTR node,
and creating a `tar` archive of the [dtr-registry volume](../../architecture.md):
#### Example backup command
##### Local images
{% raw %}
```none
sudo tar -cf dtr-image-backup-$(date +%Y%m%d-%H_%M_%S).tar \
/var/lib/docker/volumes/dtr-registry-$(docker ps --format '{{.Names}}' -f name=dtr-rethink | cut -f 3 -d '-')
```
{% endraw %}
###### Expected output
```bash
tar: Removing leading `/' from member names
```
If you're using a different storage backend, follow the best practices
recommended for that system.
### Back up DTR metadata
To create a DTR backup, load your UCP client bundle, and run the following
command.
#### Chained commands (Linux only)
{% raw %}
```none
DTR_VERSION=$(docker container inspect $(docker container ps -f name=dtr-registry -q) | \
grep -m1 -Po '(?<=DTR_VERSION=)\d.\d.\d'); \
REPLICA_ID=$(docker ps --format '{{.Names}}' -f name=dtr-rethink | cut -f 3 -d '-'); \
read -p 'ucp-url (The UCP URL including domain and port): ' UCP_URL; \
read -p 'ucp-username (The UCP administrator username): ' UCP_ADMIN; \
read -sp 'ucp password: ' UCP_PASSWORD; \
docker run --log-driver none -i --rm \
--env UCP_PASSWORD=$UCP_PASSWORD \
docker/dtr:$DTR_VERSION backup \
--ucp-username $UCP_ADMIN \
--ucp-url $UCP_URL \
--ucp-ca "$(curl https://${UCP_URL}/ca)" \
--existing-replica-id $REPLICA_ID > dtr-metadata-${DTR_VERSION}-backup-$(date +%Y%m%d-%H_%M_%S).tar
```
{% endraw %}
#### UCP field prompts
* `<ucp-url>` is the URL you use to access UCP.
* `<ucp-username>` is the username of a UCP administrator.
* `<replica-id>` is the DTR replica ID to back up.
The above chained commands run through the following tasks:
1. Sets your DTR version and replica ID. To back up
a specific replica, set the replica ID manually by modifying the
`--existing-replica-id` flag in the backup command.
2. Prompts you for your UCP URL (domain and port) and admin username.
3. Prompts you for your UCP password without saving it to your disk or printing it on the terminal.
4. Retrieves the CA certificate for your specified UCP URL. To skip TLS verification, replace the `--ucp-ca`
flag with `--ucp-insecure-tls`. Docker does not recommend this flag for production environments.
5. Includes DTR version and timestamp to your `tar` backup file.
You can learn more about the supported flags in
the [DTR backup reference documentation](/reference/dtr/2.6/cli/backup.md).
By default, the backup command does not pause the DTR replica being backed up to
prevent interruptions of user access to DTR. Since the replica
is not stopped, changes that happen during the backup may not be saved.
Use the `--offline-backup` flag to stop the DTR replica during the backup procedure. If you set this flag,
remove the replica from the load balancing pool to avoid user interruption.
Also, the backup contains sensitive information
like private keys, so you can encrypt the backup by running:
```none
gpg --symmetric {{ metadata_backup_file }}
```
This prompts you for a password to encrypt the backup, copies the backup file
and encrypts it.
### Test your backups
To validate that the backup was correctly performed, you can print the contents
of the tar file created. The backup of the images should look like:
```none
tar -tf {{ metadata_backup_file }}
dtr-backup-v{{ page.dtr_version }}/
dtr-backup-v{{ page.dtr_version }}/rethink/
dtr-backup-v{{ page.dtr_version }}/rethink/layers/
```
And the backup of the DTR metadata should look like:
```none
tar -tf {{ metadata_backup_file }}
# The archive should look like this
dtr-backup-v{{ page.dtr_version }}/
dtr-backup-v{{ page.dtr_version }}/rethink/
dtr-backup-v{{ page.dtr_version }}/rethink/properties/
dtr-backup-v{{ page.dtr_version }}/rethink/properties/0
```
If you've encrypted the metadata backup, you can use:
```none
gpg -d {{ metadata_backup_file }} | tar -t
```
You can also create a backup of a UCP cluster and restore it into a new
cluster. Then restore DTR on that new cluster to confirm that everything is
working as expected.
## Where to go next
- [Configure your storage backend](/ee/dtr/admin/configure/external-storage/index.md)
- [Switch your storage backend](/ee/dtr/admin/configure/external-storage/storage-backend-migration.md)
- [Use NFS](/ee/dtr/admin/configure/external-storage/nfs.md)
- [Use S3](/ee/dtr/admin/configure/external-storage/s3.md)
- CLI reference pages
- [docker/dtr install](/reference/dtr/2.6/cli/install/)
- [docker/dtr reconfigure](/reference/dtr/2.6/cli/reconfigure/)
- [docker/dtr restore](/reference/dtr/2.6/cli/restore/)

View File

@ -0,0 +1,60 @@
---
title: DTR disaster recovery overview
description: Learn the multiple disaster recovery strategies you can use with
Docker Trusted Registry.
keywords: dtr, disaster recovery
---
Docker Trusted Registry is a clustered application. You can join multiple
replicas for high availability.
For a DTR cluster to be healthy, a majority of its replicas (n/2 + 1) need to
be healthy and be able to communicate with the other replicas. This is also
known as maintaining quorum.
This means that there are three failure scenarios possible.
## Replica is unhealthy but cluster maintains quorum
One or more replicas are unhealthy, but the overall majority (n/2 + 1) is still
healthy and able to communicate with one another.
![Failure scenario 1](../../images/dr-overview-1.svg)
In this example the DTR cluster has five replicas but one of the nodes stopped
working, and the other has problems with the DTR overlay network.
Even though these two replicas are unhealthy the DTR cluster has a majority
of replicas still working, which means that the cluster is healthy.
In this case you should repair the unhealthy replicas, or remove them from
the cluster and join new ones.
[Learn how to repair a replica](repair-a-single-replica.md).
## The majority of replicas are unhealthy
A majority of replicas are unhealthy, making the cluster lose quorum, but at
least one replica is still healthy, or at least the data volumes for DTR are
accessible from that replica.
![Failure scenario 2](../../images/dr-overview-2.svg)
In this example the DTR cluster is unhealthy but since one replica is still
running it's possible to repair the cluster without having to restore from
a backup. This minimizes the amount of data loss.
[Learn how to do an emergency repair](repair-a-cluster.md).
## All replicas are unhealthy
This is a total disaster scenario where all DTR replicas were lost, causing
the data volumes for all DTR replicas to get corrupted or lost.
![Failure scenario 3](../../images/dr-overview-3.svg)
In a disaster scenario like this, you'll have to restore DTR from an existing
backup. Restoring from a backup should be only used as a last resort, since
doing an emergency repair might prevent some data loss.
[Learn how to restore from a backup](restore-from-backup.md).

View File

@ -0,0 +1,90 @@
---
title: Repair a cluster
description: Learn how to repair DTR when the majority of replicas are unhealthy.
keywords: dtr, disaster recovery
redirect_from:
- /datacenter/dtr/2.5/guides/admin/disaster-recovery/repair-a-cluster/
---
For a DTR cluster to be healthy, a majority of its replicas (n/2 + 1) need to
be healthy and be able to communicate with the other replicas. This is known
as maintaining quorum.
In a scenario where quorum is lost, but at least one replica is still
accessible, you can use that replica to repair the cluster. That replica doesn't
need to be completely healthy. The cluster can still be repaired as the DTR
data volumes are persisted and accessible.
![Unhealthy cluster](../../images/repair-cluster-1.svg)
Repairing the cluster from an existing replica minimizes the amount of data lost.
If this procedure doesn't work, you'll have to
[restore from an existing backup](restore-from-backup.md).
## Diagnose an unhealthy cluster
When a majority of replicas are unhealthy, causing the overall DTR cluster to
become unhealthy, operations like `docker login`, `docker pull`, and `docker push`
present `internal server error`.
Accessing the `/_ping` endpoint of any replica also returns the same error.
It's also possible that the DTR web UI is partially or fully unresponsive.
## Perform an emergency repair
Use the `docker/dtr emergency-repair` command to try to repair an unhealthy
DTR cluster, from an existing replica.
This command checks the data volumes for the DTR
This command checks the data volumes for the DTR replica are uncorrupted,
redeploys all internal DTR components and reconfigured them to use the existing
volumes.
It also reconfigures DTR removing all other nodes from the cluster, leaving DTR
as a single-replica cluster with the replica you chose.
Start by finding the ID of the DTR replica that you want to repair from.
You can find the list of replicas by navigating to **Shared Resources > Stacks** or **Swarm > Volumes** (when using [swarm mode](/engine/swarm/)) on the UCP web interface, or by using
a UCP client bundle to run:
{% raw %}
```bash
docker ps --format "{{.Names}}" | grep dtr
# The list of DTR containers with <node>/<component>-<replicaID>, e.g.
# node-1/dtr-api-a1640e1c15b6
```
{% endraw %}
Another way to determine the replica ID is to SSH into a DTR node and run the following:
{% raw %}
```bash
REPLICA_ID=$(docker inspect -f '{{.Name}}' $(docker ps -q -f name=dtr-rethink) | cut -f 3 -d '-')
&& echo $REPLICA_ID
```
{% endraw %}
Then, use your UCP client bundle to run the emergency repair command:
```bash
docker run -it --rm {{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} emergency-repair \
--ucp-insecure-tls \
--existing-replica-id <replica-id>
```
If the emergency repair procedure is successful, your DTR cluster now has a
single replica. You should now
[join more replicas for high availability](../configure/set-up-high-availability.md).
![Healthy cluster](../../images/repair-cluster-2.svg)
If the emergency repair command fails, try running it again using a different
replica ID. As a last resort, you can restore your cluster from an existing
backup.
## Where to go next
- [Create a backup](create-a-backup.md)
- [Restore from an existing backup](restore-from-backup.md)

View File

@ -0,0 +1,114 @@
---
title: Repair a single replica
description: Learn how to repair a single DTR replica when it is unhealthy.
keywords: dtr, disaster recovery
---
When one or more DTR replicas are unhealthy but the overall majority
(n/2 + 1) is healthy and able to communicate with one another, your DTR
cluster is still functional and healthy.
![Cluster with two nodes unhealthy](../../images/repair-replica-1.svg)
Given that the DTR cluster is healthy, there's no need to execute any disaster
recovery procedures like restoring from a backup.
Instead, you should:
1. Remove the unhealthy replicas from the DTR cluster.
2. Join new replicas to make DTR highly available.
Since a DTR cluster requires a majority of replicas to be healthy at all times,
the order of these operations is important. If you join more replicas before
removing the ones that are unhealthy, your DTR cluster might become unhealthy.
## Split-brain scenario
To understand why you should remove unhealthy replicas before joining new ones,
imagine you have a five-replica DTR deployment, and something goes wrong with
the overlay network connection the replicas, causing them to be separated in
two groups.
![Cluster with network problem](../../images/repair-replica-2.svg)
Because the cluster originally had five replicas, it can work as long as
three replicas are still healthy and able to communicate (5 / 2 + 1 = 3).
Even though the network separated the replicas in two groups, DTR is still
healthy.
If at this point you join a new replica instead of fixing the network problem
or removing the two replicas that got isolated from the rest, it's possible
that the new replica ends up in the side of the network partition that has
less replicas.
![cluster with split brain](../../images/repair-replica-3.svg)
When this happens, both groups now have the minimum amount of replicas needed
to establish a cluster. This is also known as a split-brain scenario, because
both groups can now accept writes and their histories start diverging, making
the two groups effectively two different clusters.
## Remove replicas
To remove unhealthy replicas, you'll first have to find the replica ID
of one of the replicas you want to keep, and the replica IDs of the unhealthy
replicas you want to remove.
You can find the list of replicas by navigating to **Shared Resources > Stacks** or **Swarm > Volumes** (when using [swarm mode](/engine/swarm/)) on the UCP web interface, or by using the UCP
client bundle to run:
{% raw %}
```bash
docker ps --format "{{.Names}}" | grep dtr
# The list of DTR containers with <node>/<component>-<replicaID>, e.g.
# node-1/dtr-api-a1640e1c15b6
```
{% endraw %}
Another way to determine the replica ID is to SSH into a DTR node and run the following:
{% raw %}
```bash
REPLICA_ID=$(docker inspect -f '{{.Name}}' $(docker ps -q -f name=dtr-rethink) | cut -f 3 -d '-')
&& echo $REPLICA_ID
```
{% endraw %}
Then use the UCP client bundle to remove the unhealthy replicas:
```bash
docker run -it --rm {{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} remove \
--existing-replica-id <healthy-replica-id> \
--replica-ids <unhealthy-replica-id> \
--ucp-insecure-tls \
--ucp-url <ucp-url> \
--ucp-username <user> \
--ucp-password <password>
```
You can remove more than one replica at the same time, by specifying multiple
IDs with a comma.
![Healthy cluster](../../images/repair-replica-4.svg)
## Join replicas
Once you've removed the unhealthy nodes from the cluster, you should join new
ones to make sure your cluster is highly available.
Use your UCP client bundle to run the following command which prompts you for
the necessary parameters:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} join \
--ucp-node <ucp-node-name> \
--ucp-insecure-tls
```
[Learn more about high availability](../configure/set-up-high-availability.md).
## Where to go next
- [Disaster recovery overview](index.md)

View File

@ -0,0 +1,110 @@
---
title: Restore from a backup
description: Learn how to restore a DTR cluster from an existing backup
keywords: dtr, disaster recovery
---
{% assign metadata_backup_file = "dtr-metadata-backup.tar" %}
{% assign image_backup_file = "dtr-image-backup.tar" %}
## Restore DTR data
If your DTR has a majority of unhealthy replicas, the one way to restore it to
a working state is by restoring from an existing backup.
To restore DTR, you need to:
1. Stop any DTR containers that might be running
2. Restore the images from a backup
3. Restore DTR metadata from a backup
4. Re-fetch the vulnerability database
You need to restore DTR on the same UCP cluster where you've created the
backup. If you restore on a different UCP cluster, all DTR resources will be
owned by users that don't exist, so you'll not be able to manage the resources,
even though they're stored in the DTR data store.
When restoring, you need to use the same version of the `docker/dtr` image
that you've used when creating the update. Other versions are not guaranteed
to work.
### Remove DTR containers
Start by removing any DTR container that is still running:
```none
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} destroy \
--ucp-insecure-tls
```
### Restore images
If you had DTR configured to store images on the local filesystem, you can
extract your backup:
```none
sudo tar -xf {{ image_backup_file }} -C /var/lib/docker/volumes
```
If you're using a different storage backend, follow the best practices
recommended for that system.
### Restore DTR metadata
You can restore the DTR metadata with the `docker/dtr restore` command. This
performs a fresh installation of DTR, and reconfigures it with
the configuration created during a backup.
Load your UCP client bundle, and run the following command, replacing the
placeholders for the real values:
```bash
read -sp 'ucp password: ' UCP_PASSWORD;
```
This prompts you for the UCP password. Next, run the following to restore DTR from your backup. You can learn more about the supported flags in [docker/dtr restore](/reference/dtr/2.6/cli/restore).
```bash
docker run -i --rm \
--env UCP_PASSWORD=$UCP_PASSWORD \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} restore \
--ucp-url <ucp-url> \
--ucp-insecure-tls \
--ucp-username <ucp-username> \
--ucp-node <hostname> \
--replica-id <replica-id> \
--dtr-external-url <dtr-external-url> < {{ metadata_backup_file }}
```
Where:
* `<ucp-url>` is the url you use to access UCP
* `<ucp-username>` is the username of a UCP administrator
* `<hostname>` is the hostname of the node where you've restored the images
* `<replica-id>` the id of the replica you backed up
* `<dtr-external-url>`the url that clients use to access DTR
#### DTR 2.5 and below
If you're using NFS as a storage backend, also include `--nfs-storage-url` as
part of your restore command, otherwise DTR is restored but starts using a
local volume to persist your Docker images.
#### DTR 2.5 (with experimental online garbage collection) and DTR 2.6.0-2.6.3
> When running DTR 2.5 (with experimental online garbage collection) and 2.6.0 to 2.6.3, there is an issue with [reconfiguring and restoring DTR with `--nfs-storage-url`](/ee/dtr/release-notes#version-26) which leads to erased tags. Make sure to [back up your DTR metadata](/ee/dtr/admin/disaster-recovery/create-a-backup/#back-up-dtr-metadata) before you proceed. To work around the `--nfs-storage-url`flag issue, manually create a storage volume on each DTR node. To [restore DTR](/reference/dtr/2.6/cli/restore/) from an existing backup, use `docker/dtr restore` with `--dtr-storage-volume` and the new volume.
>
> See [Restore to a Local NFS Volume]( https://success.docker.com/article/dtr-26-lost-tags-after-reconfiguring-storage#restoretoalocalnfsvolume) for Docker's recommended recovery strategy.
{: .warning}
### Re-fetch the vulnerability database
If you're scanning images, you now need to download the vulnerability database.
After you successfully restore DTR, you can join new replicas the same way you
would after a fresh installation. [Learn more](../configure/set-up-vulnerability-scans.md).
## Where to go next
- [docker/dtr restore](/reference/dtr/2.6/cli/restore/)

View File

@ -0,0 +1,146 @@
---
title: Install Docker Trusted Registry
description: Learn how to install Docker Trusted Registry for production.
keywords: dtr, registry, install
---
Docker Trusted Registry (DTR) is a containerized application that runs on a
swarm managed by the Universal Control Plane (UCP). It can be installed
on-premises or on a cloud infrastructure.
## Step 1. Validate the system requirements
Before installing DTR, make sure your
infrastructure meets the [system requirements](./system-requirements) that DTR needs to run.
## Step 2. Install UCP
Since DTR requires Docker Universal Control Plane (UCP)
to run, you need to [install UCP](/ee/ucp/admin/install/) on all the nodes where you plan to install DTR.
DTR needs to be installed on a worker node that is being managed by UCP.
You cannot install DTR on a standalone Docker Engine.
![](../../images/install-dtr-1.svg)
## Step 3. Install DTR
Once UCP is installed, navigate to the **UCP web UI**. In the **Admin Settings**,
choose **Docker Trusted Registry**.
![](../../images/install-dtr-2.png){: .with-border}
After you configure all the options, you'll have a snippet that you can use
to deploy DTR. It should look like this:
```bash
# Pull the latest version of DTR
$ docker pull {{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }}
# Install DTR
$ docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} install \
--ucp-node <ucp-node-name> \
--ucp-insecure-tls
```
You can run that snippet on any node where Docker is installed. As an example
you can SSH into a UCP node and run the DTR installer from there. By default
the installer runs in interactive mode and prompts you for any additional
information that is necessary.
[Learn more about the installer](/reference/dtr/2.6/cli/install/).
By default DTR is deployed with self-signed certificates, so your UCP deployment
might not be able to pull images from DTR.
Use the `--dtr-external-url <dtr-domain>:<port>` optional flag while deploying
DTR, so that UCP is automatically reconfigured to trust DTR. Since [HSTS (HTTP Strict-Transport-Security)
header](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) is included in all API responses,
make sure to specify the FQDN (Fully Qualified Domain Name) of your DTR, or your browser may refuse
to load the web interface.
## Step 4. Check that DTR is running
In your browser, navigate to the Docker **Universal Control Plane**
web interface, and navigate to **Shared Resources > Stacks**. DTR should be listed
as an application.
![](../../images/install-dtr-3.png){: .with-border}
You can also access the **DTR web interface**, to make sure it is working. In your
browser, navigate to the address where you installed DTR.
![](../../images/create-repository-1.png){: .with-border}
## Step 5. Configure DTR
After installing DTR, you should configure:
* The certificates used for TLS communication. [Learn more](../configure/use-your-own-tls-certificates.md).
* The storage backend to store the Docker images. [Lean more](../configure/external-storage/index.md).
To perform these configurations, navigate to the **Settings** page of DTR.
![](../../images/auto-delete-job-logs-1.png){: .with-border}
## Step 6. Test pushing and pulling
Now that you have a working installation of DTR, you should test that you can
push and pull images to it:
* [Configure your local Docker Engine](../../user/access-dtr/index.md)
* [Create a repository](../../user/manage-images/index.md)
* [Push and pull images](../../user/manage-images/pull-and-push-images.md)
## Step 7. Join replicas to the cluster
This step is optional.
To set up DTR for high availability,
you can add more replicas to your DTR cluster. Adding more replicas allows you
to load-balance requests across all replicas, and keep DTR working if a
replica fails.
For high-availability you should set 3, 5, or 7 DTR replicas. The nodes where
you're going to install these replicas also need to be managed by UCP.
To add replicas to a DTR cluster, use the `docker/dtr join` command:
1. Load your [UCP user bundle](/ee/ucp/user-access/cli/#use-client-certificates).
2. Run the join command.
When you join a replica to a DTR cluster, you need to specify the
ID of a replica that is already part of the cluster. You can find an
existing replica ID by going to the **Shared Resources > Stacks** page on UCP.
Then run:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} join \
--ucp-node <ucp-node-name> \
--ucp-insecure-tls
```
> --ucp-node
>
> The <ucp-node-name> following the --ucp-node flag is the target node to
> install the DTR replica. This is NOT the UCP Manager URL.
{: .important}
3. Check that all replicas are running.
In your browser, navigate to the Docker **Universal Control Plane**
web interface, and navigate to **Shared Resources > Stacks**. All replicas should
be displayed.
![](../../images/install-dtr-6.png){: .with-border}
## Where to go next
- [Install DTR offline](install-offline.md)
- [Upgrade DTR](../upgrade.md)

View File

@ -0,0 +1,70 @@
---
title: Install Docker Trusted Registry offline
description: Learn how to install Docker Trusted Registry on a machine with no internet
access.
keywords: registry, install, offline
---
The procedure to install Docker Trusted Registry on a host is the same,
whether that host has access to the internet or not.
The only difference when installing on an offline host,
is that instead of pulling the UCP images from Docker Hub, you use a
computer that is connected to the internet to download a single package with
all the images. Then you copy that package to the host where youll install DTR.
## Versions available
{% include components/ddc_url_list_2.html product="dtr" version="2.6" %}
## Download the offline package
Use a computer with internet access to download a package with all DTR images:
```bash
$ wget <package-url> -O dtr.tar.gz
```
Now that you have the package in your local machine, you can transfer it to
the machines where you want to install DTR.
For each machine where you want to install DTR:
1. Copy the DTR package to that machine.
```bash
$ scp dtr.tar.gz <user>@<host>
```
2. Use ssh to log into the hosts where you transferred the package.
3. Load the DTR images.
Once the package is transferred to the hosts, you can use the
`docker load` command to load the Docker images from the tar archive:
```bash
$ docker load -i dtr.tar.gz
```
## Install DTR
Now that the offline hosts have all the images needed to install DTR,
you can [install DTR on that host](index.md).
### Preventing outgoing connections
DTR makes outgoing connections to:
* report analytics,
* check for new versions,
* check online licenses,
* update the vulnerability scanning database
All of these uses of online connections are optional. You can choose to
disable or not use any or all of these features on the admin settings page.
## Where to go next
- [DTR architecture](../../architecture.md)
- [Install DTR](index.md)

View File

@ -0,0 +1,58 @@
---
title: Docker Trusted Registry system requirements
description: Learn about the system requirements for installing Docker Trusted Registry.
keywords: DTR, architecture, requirements
---
Docker Trusted Registry can be installed on-premises or on the cloud.
Before installing, be sure your infrastructure has these requirements.
## Hardware and Software requirements
You can install DTR on-premises or on a cloud provider. To install DTR,
all nodes must:
* Be a worker node managed by UCP (Universal Control Plane). See [Compatibility Matrix](https://success.docker.com/article/compatibility-matrix) for version compatibility.
* Have a fixed hostname.
### Minimum requirements
* 16GB of RAM for nodes running DTR
* 2 vCPUs for nodes running DTR
* 10GB of free disk space
### Recommended production requirements
* 16GB of RAM for nodes running DTR
* 4 vCPUs for nodes running DTR
* 25-100GB of free disk space
Note that Windows container images are typically larger than Linux ones and for
this reason, you should consider provisioning more local storage for Windows
nodes and for DTR setups that will store Windows container images.
## Ports used
When installing DTR on a node, make sure the following ports are open on that
node:
| Direction | Port | Purpose |
|:---------:|:--------|:--------------------------------------|
| in | 80/tcp | Web app and API client access to DTR. |
| in | 443/tcp | Web app and API client access to DTR. |
These ports are configurable when installing DTR.
## Compatibility and maintenance lifecycle
Docker Enterprise Edition is a software subscription that includes three products:
* Docker Enterprise Engine
* Docker Trusted Registry
* Docker Universal Control Plane
[Learn more about the maintenance lifecycle for these products](https://success.docker.com/article/Compatibility_Matrix).
## Where to go next
- [DTR architecture](../../architecture.md)
- [Install DTR](index.md)

View File

@ -0,0 +1,25 @@
---
title: Uninstall Docker Trusted Registry
description: Learn how to uninstall your Docker Trusted Registry installation.
keywords: dtr, install, uninstall
---
Uninstalling DTR can be done by simply removing all data associated with each
replica. To do that, you just run the destroy command once per replica:
```bash
docker run -it --rm \
docker/dtr:{{ page.dtr_version }} destroy \
--ucp-insecure-tls
```
You will be prompted for the UCP URL, UCP credentials, and which replica to
destroy.
To see what options are available in the destroy command, check the
[destroy command reference documentation](/reference/dtr/2.6/cli/destroy.md).
## Where to go next
- [Scale your deployment](../configure/set-up-high-availability.md)
- [Install DTR](index.md)

View File

@ -0,0 +1,177 @@
---
title: Audit Jobs via the API
description: Learn how Docker Trusted Registry runs batch jobs for job-related troubleshooting.
keywords: dtr, troubleshoot, audit, job logs, jobs, api
---
## Overview
This covers troubleshooting batch jobs via the API and was introduced in DTR 2.2. Starting in DTR 2.6, admins have the ability to [audit jobs](audit-jobs-via-ui.md) using the web interface.
## Prerequisite
* [Job Queue](job-queue.md)
### Job capacity
Each job runner has a limited capacity and will not claim jobs that require a
higher capacity. You can see the capacity of a job runner via the
`GET /api/v0/workers` endpoint:
```json
{
"workers": [
{
"id": "000000000000",
"status": "running",
"capacityMap": {
"scan": 1,
"scanCheck": 1
},
"heartbeatExpiration": "2017-02-18T00:51:02Z"
}
]
}
```
This means that the worker with replica ID `000000000000` has a capacity of 1
`scan` and 1 `scanCheck`. Next, review the list of available jobs:
```json
{
"jobs": [
{
"id": "0",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scan": 1
}
},
{
"id": "1",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scan": 1
}
},
{
"id": "2",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scanCheck": 1
}
}
]
}
```
If worker `000000000000` notices the jobs
in `waiting` state above, then it will be able to pick up jobs `0` and `2` since it has the capacity
for both. Job `1` will have to wait until the previous scan job, `0`, is completed. The job queue will then look like:
```json
{
"jobs": [
{
"id": "0",
"workerID": "000000000000",
"status": "running",
"capacityMap": {
"scan": 1
}
},
{
"id": "1",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scan": 1
}
},
{
"id": "2",
"workerID": "000000000000",
"status": "running",
"capacityMap": {
"scanCheck": 1
}
}
]
}
```
You can get a list of jobs via the `GET /api/v0/jobs/` endpoint. Each job
looks like:
```json
{
"id": "1fcf4c0f-ff3b-471a-8839-5dcb631b2f7b",
"retryFromID": "1fcf4c0f-ff3b-471a-8839-5dcb631b2f7b",
"workerID": "000000000000",
"status": "done",
"scheduledAt": "2017-02-17T01:09:47.771Z",
"lastUpdated": "2017-02-17T01:10:14.117Z",
"action": "scan_check_single",
"retriesLeft": 0,
"retriesTotal": 0,
"capacityMap": {
"scan": 1
},
"parameters": {
"SHA256SUM": "1bacd3c8ccb1f15609a10bd4a403831d0ec0b354438ddbf644c95c5d54f8eb13"
},
"deadline": "",
"stopTimeout": ""
}
```
The JSON fields of interest here are:
* `id`: The ID of the job
* `workerID`: The ID of the worker in a DTR replica that is running this job
* `status`: The current state of the job
* `action`: The type of job the worker will actually perform
* `capacityMap`: The available capacity a worker needs for this job to run
### Cron jobs
Several of the jobs performed by DTR are run in a recurrent schedule. You can
see those jobs using the `GET /api/v0/crons` endpoint:
```json
{
"crons": [
{
"id": "48875b1b-5006-48f5-9f3c-af9fbdd82255",
"action": "license_update",
"schedule": "57 54 3 * * *",
"retries": 2,
"capacityMap": null,
"parameters": null,
"deadline": "",
"stopTimeout": "",
"nextRun": "2017-02-22T03:54:57Z"
},
{
"id": "b1c1e61e-1e74-4677-8e4a-2a7dacefffdc",
"action": "update_db",
"schedule": "0 0 3 * * *",
"retries": 0,
"capacityMap": null,
"parameters": null,
"deadline": "",
"stopTimeout": "",
"nextRun": "2017-02-22T03:00:00Z"
}
]
}
```
The `schedule` field uses a cron expression following the `(seconds) (minutes) (hours) (day of month) (month) (day of week)` format. For example, `57 54 3 * * *` with cron ID `48875b1b-5006-48f5-9f3c-af9fbdd82255` will be run at `03:54:57` on any day of the week or the month, which is `2017-02-22T03:54:57Z` in the example JSON response above.
## Where to go next
- [Enable auto-deletion of job logs](./auto-delete-job-logs.md)

View File

@ -0,0 +1,66 @@
---
title: Audit Jobs via the Web Interface
description: View a list of jobs happening within DTR and review the detailed logs for each job.
keywords: dtr, troubleshoot, audit, job logs, jobs, ui
---
As of DTR 2.2, admins were able to [view and audit jobs within DTR](audit-jobs-via-api) using the API. DTR 2.6 enhances those capabilities by adding a **Job Logs** tab under **System** settings on the user interface. The tab displays a sortable and paginated list of jobs along with links to associated job logs.
## Prerequisite
* [Job Queue](job-queue.md)
## View Jobs List
To view the list of jobs within DTR, do the following:
1. Navigate to `https://<dtr-url>`and log in with your UCP credentials.
2. Select **System** from the left navigation pane, and then click **Job Logs**. You should see a paginated list of past, running, and queued jobs. By default, **Job Logs** shows the latest `10` jobs on the first page.
![](../../images/view-job-logs-1.png){: .img-fluid .with-border}
3. Specify a filtering option. **Job Logs** lets you filter by:
* Action: See [Audit Jobs via the API: Job Types](job-queue/#job-types) for an explanation on the different actions or job types.
* Worker ID: The ID of the worker in a DTR replica that is responsible for running the job.
![](../../images/view-job-logs-2.png){: .img-fluid .with-border}
4. Optional: Click **Edit Settings** on the right of the filtering options to update your **Job Logs** settings. See [Enable auto-deletion of job logs](auto-delete-job-logs) for more details.
### Job Details
The following is an explanation of the job-related fields displayed in **Job Logs** and uses the filtered `online_gc` action from above.
| Job Detail | Description | Example |
|:----------------|:-------------------------------------------------|:--------|
| Action | The type of action or job being performed. See [Job Types](./job-queue/#job-types) for a full list of job types. | `onlinegc`
| ID | The ID of the job. | `ccc05646-569a-4ac4-b8e1-113111f63fb9` |
| Worker | The ID of the worker node responsible for running the job. | `8f553c8b697c`|
| Status | Current status of the action or job. See [Job Status](./job-queue/#job-status) for more details. | `done` |
| Start Time | Time when the job started. | `9/23/2018 7:04 PM` |
| Last Updated | Time when the job was last updated. | `9/23/2018 7:04 PM` |
| View Logs | Links to the full logs for the job. | `[View Logs]` |
## View Job-specific Logs
To view the log details for a specific job, do the following:
1. Click **View Logs** next to the job's **Last Updated** value. You will be redirected to the log detail page of your selected job.
![](../../images/view-job-logs-3.png){: .img-fluid .with-border}
Notice how the job `ID` is reflected in the URL while the `Action` and the abbreviated form of the job `ID` are reflected in the heading. Also, the JSON lines displayed are job-specific [DTR container logs](https://success.docker.com/article/how-to-check-the-docker-trusted-registry-dtr-logs). See [DTR Internal Components](../../architecture/#dtr-internal-components) for more details.
2. Enter or select a different line count to truncate the number of lines displayed. Lines are cut off from the end of the logs.
![](../../images/view-job-logs-4.png){: .img-fluid .with-border}
## Where to go next
- [Enable auto-deletion of job logs](./auto-delete-job-logs.md)

View File

@ -0,0 +1,50 @@
---
title: Enable Auto-Deletion of Job Logs
description: Enable auto-deletion of old or unnecessary job logs for maintenance.
keywords: dtr, jobs, log, job logs, system
---
## Overview
Docker Trusted Registry has a global setting for auto-deletion of job logs which allows them to be removed as part of [garbage collection](../configure/garbage-collection.md). DTR admins can enable auto-deletion of repository events in DTR 2.6 based on specified conditions which are covered below.
## Steps
1. In your browser, navigate to `https://<dtr-url>` and log in with your UCP credentials.
2. Select **System** on the left navigation pane which will display the **Settings** page by default.
3. Scroll down to **Job Logs** and turn on **Auto-Deletion**.
![](../../images/auto-delete-job-logs-1.png){: .img-fluid .with-border}
4. Specify the conditions with which a job log auto-deletion will be triggered.
DTR allows you to set your auto-deletion conditions based on the following optional job log attributes:
| Name | Description | Example |
|:----------------|:---------------------------------------------------| :----------------|
| Age | Lets you remove job logs which are older than your specified number of hours, days, weeks or months| `2 months` |
| Max number of events | Lets you specify the maximum number of job logs allowed within DTR. | `100` |
![](../../images/auto-delete-job-logs-2.png){: .img-fluid .with-border}
If you check and specify both, job logs will be removed from DTR during garbage collection if either condition is met. You should see a confirmation message right away.
5. Click **Start Deletion** if you're ready. Read more about [garbage collection](../configure/garbage-collection/#under-the-hood) if you're unsure about this operation.
6. Navigate to **System > Job Logs** to confirm that [**onlinegc_joblogs**](job-queue/#job-types) has started. For a detailed breakdown of individual job logs, see [View Job-specific Logs](audit-jobs-via-ui/#view-job-specific-logs) in "Audit Jobs via the Web Interface."
![](../../images/auto-delete-job-logs-3.png){: .img-fluid .with-border}
> Job Log Deletion
>
> When you enable auto-deletion of job logs, the logs will be permanently deleted during garbage collection. See [Configure logging drivers](../../../../config/containers/logging/configure/) for a list of supported logging drivers and plugins.
## Where to go next
- [Monitor Docker Trusted Registry](/ee/dtr/admin/monitor-and-troubleshoot/)

View File

@ -0,0 +1,80 @@
---
title: Job Queue
description: Learn how Docker Trusted Registry runs batch jobs for troubleshooting job-related issues.
keywords: dtr, job queue, job management
---
Docker Trusted Registry (DTR) uses a job queue to schedule batch jobs. Jobs are added to a cluster-wide job queue, and then consumed and executed by a job runner within DTR.
![batch jobs diagram](../../images/troubleshoot-batch-jobs-1.svg)
All DTR replicas have access to the job queue, and have a job runner component
that can get and execute work.
## How it works
When a job is created, it is added to a cluster-wide job queue and enters the `waiting` state.
When one of the DTR replicas is ready to claim the job, it waits a random time of up
to `3` seconds to give every replica the opportunity to claim the task.
A replica claims a job by adding its replica ID to the job. That way, other
replicas will know the job has been claimed. Once a replica claims a job, it adds
that job to an internal queue, which in turn sorts the jobs by their `scheduledAt` time.
Once that happens, the replica updates the job status to `running`, and
starts executing it.
The job runner component of each DTR replica keeps a `heartbeatExpiration`
entry on the database that is shared by all replicas. If a replica becomes
unhealthy, other replicas notice the change and update the status of the failing worker to `dead`.
Also, all the jobs that were claimed by the unhealthy replica enter the `worker_dead` state,
so that other replicas can claim the job.
## Job Types
DTR runs periodic and long-running jobs. The following is a complete list of jobs you can filter for via [the user interface](../manage-jobs/audit-jobs-via-ui.md) or [the API](../manage-jobs/audit-jobs-via-api.md).
| Job | Description |
|:------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| gc | A garbage collection job that deletes layers associated with deleted images. |
| onlinegc | A garbage collection job that deletes layers associated with deleted images without putting the registry in read-only mode. |
| onlinegc_metadata | A garbage collection job that deletes metadata associated with deleted images. |
| onlinegc_joblogs | A garbage collection job that deletes job logs based on a configured job history setting. |
| metadatastoremigration | A necessary migration that enables the `onlinegc` feature. |
| sleep | Used for testing the correctness of the jobrunner. It sleeps for 60 seconds. |
| false | Used for testing the correctness of the jobrunner. It runs the `false` command and immediately fails. |
| tagmigration | Used for synchronizing tag and manifest information between the DTR database and the storage backend. |
| bloblinkmigration | A DTR 2.1 to 2.2 upgrade process that adds references for blobs to repositories in the database. |
| license_update | Checks for license expiration extensions if online license updates are enabled. |
| scan_check | An image security scanning job. This job does not perform the actual scanning, rather it spawns `scan_check_single` jobs (one for each layer in the image). Once all of the `scan_check_single` jobs are complete, this job will terminate. |
| scan_check_single | A security scanning job for a particular layer given by the `parameter: SHA256SUM`. This job breaks up the layer into components and checks each component for vulnerabilities. |
| scan_check_all | A security scanning job that updates all of the currently scanned images to display the latest vulnerabilities. |
| update_vuln_db | A job that is created to update DTR's vulnerability database. It uses an Internet connection to check for database updates through `https://dss-cve-updates.docker.com/` and updates the `dtr-scanningstore` container if there is a new update available. |
| scannedlayermigration | A DTR 2.4 to 2.5 upgrade process that restructures scanned image data. |
| push_mirror_tag | A job that pushes a tag to another registry after a push mirror policy has been evaluated. |
| poll_mirror | A global cron that evaluates poll mirroring policies. |
| webhook | A job that is used to dispatch a webhook payload to a single endpoint. |
| nautilus_update_db | The old name for the `update_vuln_db` job. This may be visible on old log files. |
| ro_registry | A user-initiated job for manually switching DTR into read-only mode. |
| tag_pruning | A job for cleaning up unnecessary or unwanted repository tags which can be configured by repository admins. For configuration options, see [Tag Pruning](../../user/tag-pruning). |
## Job Status
Jobs can have one of the following status values:
| Status | Description |
|:----------------|:------------------------------------------------------------------------------------------------------------------------------------------|
| waiting | Unclaimed job waiting to be picked up by a worker. |
| running | The job is currently being run by the specified `workerID`. |
| done | The job has successfully completed. |
| error | The job has completed with errors. |
| cancel_request | The status of a job is monitored by the worker in the database. If the job status changes to `cancel_request`, the job is canceled by the worker. |
| cancel | The job has been canceled and was not fully executed. |
| deleted | The job and its logs have been removed. |
| worker_dead | The worker for this job has been declared `dead` and the job will not continue. |
| worker_shutdown | The worker that was running this job has been gracefully stopped. |
| worker_resurrection | The worker for this job has reconnected to the database and will cancel this job. |
## Where to go next
- [Audit Jobs via Web Interface](audit-jobs-via-ui)
- [Audit Jobs via API](audit-jobs-via-api)

View File

@ -0,0 +1,47 @@
---
title: Create and manage organizations
description: Learn how to set up organizations to enforce security in Docker Trusted
Registry.
keywords: registry, security, permissions, organizations
---
When a user creates a repository, only that user has permissions to make changes
to the repository.
For team workflows, where multiple users have permissions to manage a set of
common repositories, create an organization. By default, DTR has one
organization called 'docker-datacenter', that is shared between DTR and UCP.
To create a new organization, navigate to the **DTR web UI**, and go to the
**Organizations** page.
![](../../images/create-and-manage-orgs-1.png){: .with-border}
Click the **New organization** button, and choose a meaningful name for the
organization.
![](../../images/create-and-manage-orgs-2.png){: .with-border}
Repositories owned by this organization will contain the organization name, so
to pull an image from that repository, you'll use:
```bash
docker pull <dtr-domain-name>/<organization>/<repository>:<tag>
```
Click **Save** to create the organization, and then **click the organization**
to define which users are allowed to manage this
organization. These users will be able to edit the organization settings, edit
all repositories owned by the organization, and define the user permissions for
this organization.
For this, click the **Add user** button, **select the users** that you want to
grant permissions to manage the organization, and click
**Save**. Then change their permissions from 'Member' to **Org Owner**.
![](../../images/create-and-manage-orgs-3.png){: .with-border}
## Where to go next
- [Create and manage users](create-and-manage-users.md)
- [Create and manage teams](create-and-manage-teams.md)

View File

@ -0,0 +1,62 @@
---
title: Create and manage teams in DTR
description: Learn how to manage teams to enforce fine-grain access control in Docker
Trusted Registry.
keywords: registry, security, permissions, teams
---
You can extend a user's default permissions by granting them individual
permissions in other image repositories, by adding the user to a team. A team
defines the permissions a set of users have for a set of repositories.
To create a new team, go to the **DTR web UI**, and navigate to the
**Organizations** page.
Then **click the organization** where you want to create the team. In this
example, we'll create the 'billing' team under the 'whale' organization.
![organization](../../images/create-and-manage-teams-1.png){: .with-border}
Click '**+**' to create a new team, and give it a name.
![create team](../../images/create-and-manage-teams-2.png){: .with-border}
## Add users to a team
Once you have created a team, **click the team** name, to manage its settings.
The first thing we need to do is add users to the team. Click the **Add user**
button and add users to the team.
![add users](../../images/create-and-manage-teams-3.png){: .with-border}
## Manage team permissions
The next step is to define the permissions this team has for a set of
repositories. Navigate to the **Repositories** tab, and click the
**Add repository** button.
![manage permissions](../../images/create-and-manage-teams-4.png){: .with-border}
Choose the repositories this team has access to, and what permission levels the
team members have.
![](../../images/create-and-manage-teams-5.png){: .with-border}
There are three permission levels available:
| Permission level | Description |
|:-----------------|:-----------------------------------------------------------------|
| Read only | View repository and pull images. |
| Read & Write | View repository, pull and push images. |
| Admin | Manage repository and change its settings, pull and push images. |
## Delete a team
If you're an organization owner, you can delete a team in that organization.
Navigate to the **Team**, choose the **Settings** tab, and click **Delete**.
![delete team](../../images/create-and-manage-teams-6.png){: .with-border}
## Where to go next
- [Create and manage users](create-and-manage-users.md)
- [Permission levels](permission-levels.md)

View File

@ -0,0 +1,29 @@
---
title: Create and manage users in DTR
description: Learn how to manage user permissions in Docker Trusted Registry.
keywords: registry, security, permissions, users
---
When using the built-in authentication, you can create users
to grant them fine-grained permissions.
Users are shared across UCP and DTR. When you create a new user in
Docker Universal Control Plane, that user becomes available in DTR and vice
versa.
To create a new user, go to the **DTR web UI**, and navigate to the **Users**
page.
![](../../images/create-manage-users-1.png){: .with-border}
Click the **New user** button, and fill-in the user information.
![](../../images/create-manage-users-2.png){: .with-border}
Check the **Trusted Registry admin** option, if you want to grant permissions
for the user to be a UCP and DTR administrator.
## Where to go next
- [Authentication and authorization](index.md)
- [Create and manage teams](create-and-manage-teams.md)

View File

@ -0,0 +1,56 @@
---
title: Authentication and authorization in DTR
description: Learn about the permission levels available on Docker Trusted Registry.
keywords: registry, security, permissions, users
---
With DTR you get to control which users have access to your image repositories.
By default, anonymous users can only pull images from public repositories.
They can't create new repositories or push to existing ones.
You can then grant permissions to enforce fine-grained access control to image
repositories. For that:
* Start by creating a user.
Users are shared across UCP and DTR. When you create a new user in
Docker Universal Control Plane, that user becomes available in DTR and vice
versa. Registered users can create and manage their own repositories.
You can also integrate with an LDAP service to manage users from a single
place.
* Extend the permissions by adding the user to a team.
To extend a user's permission and manage their permissions over repositories,
you add the user to a team.
A team defines the permissions users have for a set of repositories.
## Organizations and teams
When a user creates a repository, only that user can make changes to the
repository settings, and push new images to it.
Organizations take permission management one step further, since they allow
multiple users to own and manage a common set of repositories. This
is useful when implementing team workflows. With organizations you can
delegate the management of a set of repositories and user permissions to the
organization administrators.
An organization owns a set of repositories, and defines a set of teams. With
teams you can define fine-grain permissions that a team of
user has for a set of repositories.
![](../../images/authentication-authorization-1.svg)
In this example, the 'Whale' organization has three repositories and two teams:
* Members of the blog team can only see and pull images from the whale/java
repository,
* Members of the billing team can manage the whale/golang repository, and push
and pull images from the whale/java repository.
## Where to go next
- [Create and manage users](create-and-manage-users.md)

View File

@ -0,0 +1,52 @@
---
title: Permission levels in DTR
description: Learn about the permission levels available in Docker Trusted Registry.
keywords: registry, security, permissions
---
Docker Trusted Registry allows you to define fine-grain permissions over image
repositories.
## Administrators
Users are shared across UCP and DTR. When you create a new user in Docker
Universal Control Plane, that user becomes available in DTR and vice versa.
When you create a trusted admin in DTR, the admin has permissions to manage:
* Users across UCP and DTR
* DTR repositories and settings
* UCP resources and settings
## Team permission levels
Teams allow you to define the permissions a set of user has for a set of
repositories. Three permission levels are available:
| Repository operation | read | read-write | admin |
|:----------------------|:----:|:----------:|:-----:|
| View/ browse | x | x | x |
| Pull | x | x | x |
| Push | | x | x |
| Start a scan | | x | x |
| Delete tags | | x | x |
| Edit description | | | x |
| Set public or private | | | x |
| Manage user access | | | x |
| Delete repository | | | x |
Team permissions are additive. When a user is a member of multiple teams, they
have the highest permission level defined by those teams.
## Overall permissions
Here's an overview of the permission levels available in DTR:
* Anonymous or unauthenticated Users: Can search and pull public repositories.
* Authenticated Users: Can search and pull public repos, and create and manage their own repositories.
* Team Member: Everything a user can do, plus the permissions granted by the team the user is a member of.
* Organization Owner: Can manage repositories and teams for the organization.
* Admin: Can manage anything across UCP and DTR.
## Where to go next
- [Authentication and authorization](index.md)

View File

@ -0,0 +1,33 @@
---
title: Manage webhooks
description: Learn how to create, configure, and test webhooks in Docker Trusted Registry.
keywords: registry, webhooks
---
You can configure DTR to automatically post event notifications to a webhook URL of your choosing. This lets you build complex CI and CD pipelines with your Docker images. The following is a complete list of event types you can trigger webhook notifications for via the [web interface](use-the-web-ui) or the [API](use-the-API).
## Webhook types
| Event Type | Scope | Access Level | Availability |
| --------------------------------------- | ----------------------- | ---------------- | ------------ |
| Tag pushed to repository (`TAG_PUSH`) | Individual repositories | Repository admin | Web UI & API |
| Tag pulled from repository (`TAG_PULL`) | Individual repositories | Repository admin | Web UI & API |
| Tag deleted from repository (`TAG_DELETE`) | Individual repositories | Repository admin | Web UI & API |
| Manifest pushed to repository (`MANIFEST_PUSH`) | Individual repositories | Repository admin | Web UI & API |
| Manifest pulled from repository (`MANIFEST_PULL`) | Individual repositories | Repository admin | Web UI & API |
| Manifest deleted from repository (`MANIFEST_DELETE`) | Individual repositories | Repository admin | Web UI & API |
| Security scan completed (`SCAN_COMPLETED`) | Individual repositories | Repository admin | Web UI & API |
| Security scan failed (`SCAN_FAILED`) | Individual repositories | Repository admin | Web UI & API |
| Image promoted from repository (`PROMOTION`) | Individual repositories | Repository admin | Web UI & API |
| Image mirrored from repository (`PUSH_MIRRORING`) | Individual repositories | Repository admin | Web UI & API |
| Image mirrored from remote repository (`POLL_MIRRORING`) | Individual repositories | Repository admin | Web UI & API |
| Repository created, updated, or deleted (`REPO_CREATED`, `REPO_UPDATED`, and `REPO_DELETED`) | Namespaces / Organizations | Namespace / Org owners | API Only |
| Security scanner update completed (`SCANNER_UPDATE_COMPLETED`) | Global | DTR admin | API only |
You must have admin privileges to a repository or namespace in order to
subscribe to its webhook events. For example, a user must be an admin of repository "foo/bar" to subscribe to its tag push events. A DTR admin can subscribe to any event.
## Where to go next
- [Manage webhooks via the web interface](use-the-web-ui)
- [Manage webhooks via the the API](use-the-api)

View File

@ -0,0 +1,311 @@
---
title: Manage webhooks via the API
description: Learn how to create, configure, and test webhooks for DTR using the API.
keywords: dtr, webhooks, api, registry
---
## Prerequisite
See [Webhook types](/ee/dtr/admin/manage-webhooks/index.md/#webhook-types) for a list of events you can trigger notifications for via the API.
## API Base URL
Your DTR hostname serves as the base URL for your API requests.
## Swagger API explorer
From the DTR web interface, click **API** on the bottom left navigation pane to explore the API resources and endpoints. Click **Execute** to send your API request.
## API requests via curl
You can use [curl](https://curl.haxx.se/docs/manpage.html) to send HTTP or HTTPS API requests. Note that you will have to specify `skipTLSVerification: true` on your request in order to test the webhook endpoint over HTTP.
### Example curl request
```bash
curl -u test-user:$TOKEN -X POST "https://dtr-example.com/api/v0/webhooks" -H "accept: application/json" -H "content-type: application/json" -d "{ \"endpoint\": \"https://webhook.site/441b1584-949d-4608-a7f3-f240bdd31019\", \"key\": \"maria-testorg/lab-words\", \"skipTLSVerification\": true, \"type\": \"TAG_PULL\"}"
```
### Example JSON response
```json
{
"id": "b7bf702c31601efb4796da59900ddc1b7c72eb8ca80fdfb1b9fecdbad5418155",
"type": "TAG_PULL",
"key": "maria-testorg/lab-words",
"endpoint": "https://webhook.site/441b1584-949d-4608-a7f3-f240bdd31019",
"authorID": "194efd8e-9ee6-4d43-a34b-eefd9ce39087",
"createdAt": "2019-05-22T01:55:20.471286995Z",
"lastSuccessfulAt": "0001-01-01T00:00:00Z",
"inactive": false,
"tlsCert": "",
"skipTLSVerification": true
}
```
## Subscribe to events
To subscribe to events, send a `POST` request to
`/api/v0/webhooks` with the following JSON payload:
### Example usage
```
{
"type": "TAG_PUSH",
"key": "foo/bar",
"endpoint": "https://example.com"
}
```
The keys in the payload are:
- `type`: The event type to subcribe to.
- `key`: The namespace/organization or repo to subscribe to. For example, "foo/bar" to subscribe to
pushes to the "bar" repository within the namespace/organization "foo".
- `endpoint`: The URL to send the JSON payload to.
Normal users **must** supply a "key" to scope a particular webhook event to
a repository or a namespace/organization. DTR admins can choose to omit this,
meaning a POST event notification of your specified type will be sent for all DTR repositories and namespaces.
### Receive a payload
Whenever your specified event type occurs, DTR will send a POST request to the given
endpoint with a JSON-encoded payload. The payload will always have the
following wrapper:
```
{
"type": "...",
"createdAt": "2012-04-23T18:25:43.511Z",
"contents": {...}
}
```
- `type` refers to the event type received at the specified subscription endpoint.
- `contents` refers to the payload of the event itself. Each event is different, therefore the
structure of the JSON object in `contents` will change depending on the event
type. See [Content structure](#content-structure) for more details.
### Test payload subscriptions
Before subscribing to an event, you can view and test your endpoints using
fake data. To send a test payload, send `POST` request to
`/api/v0/webhooks/test` with the following payload:
```
{
"type": "...",
"endpoint": "https://www.example.com/"
}
```
Change `type` to the event type that you want to receive. DTR will then send
an example payload to your specified endpoint. The example
payload sent is always the same.
## Content structure
Comments after (`//`) are for informational purposes only, and the example payloads have been clipped for brevity.
### Repository event content structure
**Tag push**
```
{
"namespace": "", // (string) namespace/organization for the repository
"repository": "", // (string) repository name
"tag": "", // (string) the name of the tag just pushed
"digest": "", // (string) sha256 digest of the manifest the tag points to (eg. "sha256:0afb...")
"imageName": "", // (string) the fully-qualified image name including DTR host used to pull the image (eg. 10.10.10.1/foo/bar:tag)
"os": "", // (string) the OS for the tag's manifest
"architecture": "", // (string) the architecture for the tag's manifest
"author": "", // (string) the username of the person who pushed the tag
"pushedAt": "", // (string) JSON-encoded timestamp of when the push occurred
...
}
```
**Tag delete**
```
{
"namespace": "", // (string) namespace/organization for the repository
"repository": "", // (string) repository name
"tag": "", // (string) the name of the tag just deleted
"digest": "", // (string) sha256 digest of the manifest the tag points to (eg. "sha256:0afb...")
"imageName": "", // (string) the fully-qualified image name including DTR host used to pull the image (eg. 10.10.10.1/foo/bar:tag)
"os": "", // (string) the OS for the tag's manifest
"architecture": "", // (string) the architecture for the tag's manifest
"author": "", // (string) the username of the person who deleted the tag
"deletedAt": "", // (string) JSON-encoded timestamp of when the delete occurred
...
}
```
**Manifest push**
```
{
"namespace": "", // (string) namespace/organization for the repository
"repository": "", // (string) repository name
"digest": "", // (string) sha256 digest of the manifest (eg. "sha256:0afb...")
"imageName": "", // (string) the fully-qualified image name including DTR host used to pull the image (eg. 10.10.10.1/foo/bar@sha256:0afb...)
"os": "", // (string) the OS for the manifest
"architecture": "", // (string) the architecture for the manifest
"author": "", // (string) the username of the person who pushed the manifest
...
}
```
**Manifest delete**
```
{
"namespace": "", // (string) namespace/organization for the repository
"repository": "", // (string) repository name
"digest": "", // (string) sha256 digest of the manifest (eg. "sha256:0afb...")
"imageName": "", // (string) the fully-qualified image name including DTR host used to pull the image (eg. 10.10.10.1/foo/bar@sha256:0afb...)
"os": "", // (string) the OS for the manifest
"architecture": "", // (string) the architecture for the manifest
"author": "", // (string) the username of the person who deleted the manifest
"deletedAt": "", // (string) JSON-encoded timestamp of when the delete occurred
...
}
```
**Security scan completed**
```
{
"namespace": "", // (string) namespace/organization for the repository
"repository": "", // (string) repository name
"tag": "", // (string) the name of the tag scanned
"imageName": "", // (string) the fully-qualified image name including DTR host used to pull the image (eg. 10.10.10.1/foo/bar:tag)
"scanSummary": {
"namespace": "", // (string) repository's namespace/organization name
"repository": "", // (string) repository name
"tag": "", // (string) the name of the tag just pushed
"critical": 0, // (int) number of critical issues, where CVSS >= 7.0
"major": 0, // (int) number of major issues, where CVSS >= 4.0 && CVSS < 7
"minor": 0, // (int) number of minor issues, where CVSS > 0 && CVSS < 4.0
"last_scan_status": 0, // (int) enum; see scan status section
"check_completed_at": "", // (string) JSON-encoded timestamp of when the scan completed
...
}
}
```
**Security scan failed**
```
{
"namespace": "", // (string) namespace/organization for the repository
"repository": "", // (string) repository name
"tag": "", // (string) the name of the tag scanned
"imageName": "", // (string) the fully-qualified image name including DTR host used to pull the image (eg. 10.10.10.1/foo/bar@sha256:0afb...)
"error": "", // (string) the error that occurred while scanning
...
}
```
### Namespace-specific event structure
**Repository event (created/updated/deleted)**
```
{
"namespace": "", // (string) repository's namespace/organization name
"repository": "", // (string) repository name
"event": "", // (string) enum: "REPO_CREATED", "REPO_DELETED" or "REPO_UPDATED"
"author": "", // (string) the name of the user responsible for the event
"data": {} // (object) when updating or creating a repo this follows the same format as an API response from /api/v0/repositories/{namespace}/{repository}
}
```
### Global event structure
**Security scanner update complete**
```
{
"scanner_version": "",
"scanner_updated_at": "", // (string) JSON-encoded timestamp of when the scanner updated
"db_version": 0, // (int) newly updated database version
"db_updated_at": "", // (string) JSON-encoded timestamp of when the database updated
"success": <true|false> // (bool) whether the update was successful
"replicas": { // (object) a map keyed by replica ID containing update information for each replica
"replica_id": {
"db_updated_at": "", // (string) JSON-encoded time of when the replica updated
"version": "", // (string) version updated to
"replica_id": "" // (string) replica ID
},
...
}
}
```
### Security scan status codes
- 0: **Failed**. An error occurred checking an image's layer
- 1: **Unscanned**. The image has not yet been scanned
- 2: **Scanning**. Scanning in progress
- 3: **Pending**: The image will be scanned when a worker is available
- 4: **Scanned**: The image has been scanned but vulnerabilities have not yet been checked
- 5: **Checking**: The image is being checked for vulnerabilities
- 6: **Completed**: The image has been fully security scanned
## View and manage existing subscriptions
### View all subscriptions
To view existing subscriptions, send a `GET` request to `/api/v0/webhooks`. As
a normal user (i.e. not a DTR admin), this will show all of your
current subscriptions across every namespace/organization and repository. As a DTR
admin, this will show **every** webhook configured for your DTR.
The API response will be in the following format:
```
[
{
"id": "", // (string): UUID of the webhook subscription
"type": "", // (string): webhook event type
"key": "", // (string): the individual resource this subscription is scoped to
"endpoint": "", // (string): the endpoint to send POST event notifications to
"authorID": "", // (string): the user ID resposible for creating the subscription
"createdAt": "", // (string): JSON-encoded datetime when the subscription was created
},
...
]
```
For more information, [view the API documentation](/reference/dtr/{{site.dtr_version}}/api/).
### View subscriptions for a particular resource
You can also view subscriptions for a given resource that you are an
admin of. For example, if you have admin rights to the repository
"foo/bar", you can view all subscriptions (even other people's) from a
particular API endpoint. These endpoints are:
- `GET /api/v0/repositories/{namespace}/{repository}/webhooks`: View all
webhook subscriptions for a repository
- `GET /api/v0/repositories/{namespace}/webhooks`: View all webhook subscriptions for a
namespace/organization
### Delete a subscription
To delete a webhook subscription, send a `DELETE` request to
`/api/v0/webhooks/{id}`, replacing `{id}` with the webhook subscription ID
which you would like to delete.
Only a DTR admin or an admin for the resource with the event subscription can delete a subscription. As a normal user, you can only
delete subscriptions for repositories which you manage.
## Where to go next
- [Manage jobs](/ee/dtr/admin/manage-jobs/job-queue/)

View File

@ -0,0 +1,54 @@
---
title: Manage repository webhooks via the web interface
description: Learn how to create, configure, and test repository webhooks for DTR using the web interface.
keywords: dtr, webhooks, ui, web interface, registry
---
## Prerequisites
- You must have admin privileges to the repository in order to create a webhook.
- See [Webhook types](/ee/dtr/admin/manage-webhooks/index.md/#webhook-types) for a list of events you can trigger notifications for using the web interface.
## Create a webhook for your repository
1. In your browser, navigate to `https://<dtr-url>` and log in with your credentials.
2. Select **Repositories** from the left navigation pane, and then click on the name of the repository that you want to view. Note that you will have to click on the repository name following the `/` after the specific namespace for your repository.
3. Select the **Webhooks** tab, and click **New Webhook**.
![](/ee/dtr/images/manage-webhooks-1.png){: .with-border}
4. From the drop-down list, select the event that will trigger the webhook.
5. Set the URL which will receive the JSON payload. Click **Test** next to the **Webhook URL** field, so that you can validate that the integration is working. At your specified URL, you should receive a JSON payload for your chosen event type notification.
```json
{
"type": "TAG_PUSH",
"createdAt": "2019-05-15T19:39:40.607337713Z",
"contents": {
"namespace": "foo",
"repository": "bar",
"tag": "latest",
"digest": "sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c",
"imageName": "foo/bar:latest",
"os": "linux",
"architecture": "amd64",
"author": "",
"pushedAt": "2015-01-02T15:04:05Z"
},
"location": "/repositories/foo/bar/tags/latest"
}
```
6. Expand "Show advanced settings" to paste the TLS certificate associated with your webhook URL. For testing purposes, you can test over HTTP instead of HTTPS.
7. Click **Create** to save. Once saved, your webhook is active and starts sending POST notifications whenever your chosen event type is triggered.
![](/ee/dtr/images/manage-webhooks-2.png){: .with-border}
As a repository admin, you can add or delete a webhook at any point. Additionally, you can create, view, and delete webhooks for your organization or trusted registry [using the API](use-the-api).
## Where to go next
- [Manage webhooks via the API](use-the-api)

View File

@ -0,0 +1,75 @@
---
title: Monitor Docker Trusted Registry
description: Learn how to monitor your DTR installation.
keywords: registry, monitor, troubleshoot
---
Docker Trusted Registry is a Dockerized application. To monitor it, you can
use the same tools and techniques you're already using to monitor other
containerized applications running on your cluster. One way to monitor
DTR is using the monitoring capabilities of Docker Universal Control Plane.
In your browser, log in to **Docker Universal Control Plane** (UCP), and
navigate to the **Stacks** page.
If you have DTR set up for high-availability, then all the DTR replicas are
displayed.
![](../../images/monitor-1.png){: .with-border}
To check the containers for the DTR replica, **click the replica** you want
to inspect, click **Inspect Resource**, and choose **Containers**.
![](../../images/monitor-2.png){: .with-border}
Now you can drill into each DTR container to see its logs and find the root
cause of the problem.
![](../../images/monitor-3.png){: .with-border}
## Health check endpoints
DTR also exposes several endpoints you can use to assess if a DTR replica
is healthy or not:
* `/_ping`: Checks if the DTR replica is healthy, and
returns a simple json response. This is useful for load balancing or other
automated health check tasks.
* `/nginx_status`: Returns the number of connections being handled by the
NGINX front-end used by DTR.
* `/api/v0/meta/cluster_status`: Returns extensive information about all DTR
replicas.
## Cluster status
The `/api/v0/meta/cluster_status` [endpoint](/reference/dtr/{{ site.dtr_version
}}/api/) requires administrator credentials, and returns a JSON object for the
entire cluster as observed by the replica being queried. You can authenticate
your requests using HTTP basic auth.
```bash
curl -ksL -u <user>:<pass> https://<dtr-domain>/api/v0/meta/cluster_status
```
```json
{
"current_issues": [
{
"critical": false,
"description": "... some replicas are not ready. The following servers are
not reachable: dtr_rethinkdb_f2277ad178f7",
}],
"replica_health": {
"f2277ad178f7": "OK",
"f3712d9c419a": "OK",
"f58cf364e3df": "OK"
},
}
```
You can find health status on the `current_issues` and `replica_health` arrays.
If this endpoint doesn't provide meaningful information when trying to
troubleshoot, try [troubleshooting using logs](troubleshoot-with-logs.md).
## Where to go next
- [Troubleshoot with logs](troubleshoot-with-logs.md)

View File

@ -0,0 +1,267 @@
---
title: Check Notary audit logs
description: When you push signed images, Docker Trusted Registry keeps audit
logs for the changes made to the image metadata. Learn how to view these logs.
keywords: registry, monitor, troubleshoot
---
Docker Content Trust (DCT) keeps audit logs of changes made to trusted repositories.
Every time you push a signed image to a repository, or delete trust data for a
repository, DCT logs that information.
These logs are only available from the DTR API.
## Get an authentication token
To access the audit logs you need to authenticate your requests using an
authentication token. You can get an authentication token for all repositories,
or one that is specific to a single repository.
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" data-target="#tab1">Global</a></li>
<li><a data-toggle="tab" data-target="#tab2">Repository-specific</a></li>
</ul>
<div class="tab-content">
<div id="tab1" class="tab-pane fade in active" markdown="1">
```bash
curl --insecure --silent \
--user <user>:<password> \
"https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=registry:catalog:*"
```
<hr></div>
<div id="tab2" class="tab-pane fade" markdown="1">
```bash
curl --insecure --silent \
--user <user>:<password> \
"https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=repository:<dtr-url>/<repository>:pull"
```
<hr></div>
</div>
DTR returns a JSON file with a token, even when the user doesn't have access
to the repository to which they requested the authentication token. This token
doesn't grant access to DTR repositories.
The JSON file returned has the following structure:
```json
{
"token": "<token>",
"access_token": "<token>",
"expires_in": "<expiration in seconds>",
"issued_at": "<time>"
}
```
[Learn more about the authentication API](/registry/spec/auth/token/).
## Changefeed API
Once you have an authentication token you can use the following endpoints to
get audit logs:
| URL | Description | Authorization |
|:---------------------------------------------------|:------------------------------------------|:--------------------------|
| `GET /v2/_trust/changefeed` | Get audit logs for all repositories. | Global scope token |
| `GET /v2/<dtr-url>/<repository>/_trust/changefeed` | Get audit logs for a specific repository. | Repository-specific token |
Both endpoints have the following query string parameters:
<table>
<thead>
<tr>
<th>Field name</th>
<th>Required</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>change_id</code></td>
<td>Yes</td>
<td>String</td>
<td>
<p>A non-inclusive starting change ID from which to start returning results. This will
typically be the first or last change ID from the previous page of records
requested, depending on which direction your are paging in.</p>
<p>The value <code>0</code> indicates records should be returned starting from the beginning
of time.</p>
<p>The value <code>1</code> indicates records should be returned starting from the most
recent record. If <code>1</code> is provided, the implementation will also assume the
records value is meant to be negative, regardless of the given sign.</p>
</td>
</tr>
<tr>
<td><code>records</code></td>
<td>Yes</td>
<td>Signed integer</td>
<td>
<p>The number of records to return. A negative value indicates the number
of records preceding the <code>change_id</code> should be returned.
Records are always returned sorted from oldest to newest. </p>
</td>
</tr>
</tbody>
</table>
### Response
The response is a JSON like:
```json
{
"count": 1,
"records": [
{
"ID": "0a60ec31-d2aa-4565-9b74-4171a5083bef",
"CreatedAt": "2017-11-06T18:45:58.428Z",
"GUN": "dtr.example.org/library/wordpress",
"Version": 1,
"SHA256": "a4ffcae03710ae61f6d15d20ed5e3f3a6a91ebfd2a4ba7f31fc6308ec6cc3e3d",
"Category": "update"
}
]
}
```
Below is the description for each of the fields in the response:
<table>
<thead>
<tr>
<th>Field name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>count</code></td>
<td>The number of records returned.</td>
</tr>
<tr>
<td><code>ID</code></td>
<td>The ID of the change record. Should be used in the <code>change_id</code>
field of requests to provide a non-exclusive starting index. It should be treated
as an opaque value that is guaranteed to be unique within an instance of
notary.</td>
</tr>
<tr>
<td><code>CreatedAt</code></td>
<td>The time the change happened.</td>
</tr>
<tr>
<td><code>GUN</code></td>
<td>The DTR repository that was changed.</td>
</tr>
<tr>
<td><code>Version</code></td>
<td>
<p>The version that the repository was updated to. This increments
every time there's a change to the trust repository.</p>
<p>This is always <code>0</code> for events representing trusted data being
removed from the repository.</p>
</td>
</tr>
<tr>
<td><code>SHA256</code></td>
<td>
<p>The checksum of the timestamp being updated to. This can be used
with the existing notary APIs to request said timestamp.</p>
<p>This is always an empty string for events representing trusted data
being removed from the repository</p>
</td>
</tr>
<tr>
<td><code>Category</code></td>
<td>The kind of change that was made to the trusted repository. Can be
<code>update</code>, or <code>deletion</code>.</td>
</tr>
</tbody>
</table>
The results only include audit logs for events that happened more than 60
seconds ago, and are sorted from oldest to newest.
Even though the authentication API always returns a token, the changefeed
API validates if the user has access to see the audit logs or not:
* If the user is an admin they can see the audit logs for any repositories,
* All other users can only see audit logs for repositories they have read access.
## Example - Get audit logs for all repositories
Before going through this example, make sure that you:
* Are a DTR admin user.
* Configured your [machine to trust DTR](../../user/access-dtr/index.md).
* Created the `library/wordpress` repository.
* Installed `jq`, to make it easier to parse the JSON responses.
```bash
# Pull an image from Docker Hub
docker pull wordpress:latest
# Tag that image
docker tag wordpress:latest <dtr-url>/library/wordpress:1
# Log into DTR
docker login <dtr-url>
# Push the image to DTR and sign it
DOCKER_CONTENT_TRUST=1 docker push <dtr-url>/library/wordpress:1
# Get global-scope authorization token, and store it in TOKEN
export TOKEN=$(curl --insecure --silent \
--user '<user>:<password>' \
'https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=registry:catalog:*' | jq --raw-output .token)
# Get audit logs for all repositories and pretty-print it
# If you pushed the image less than 60 seconds ago, it's possible
# That DTR doesn't show any events. Retry the command after a while.
curl --insecure --silent \
--header "Authorization: Bearer $TOKEN" \
"https://<dtr-url>/v2/_trust/changefeed?records=10&change_id=0" | jq .
```
## Example - Get audit logs for a single repository
Before going through this example, make sure that you:
* Configured your [machine to trust DTR](../../user/access-dtr/index.md).
* Created the `library/nginx` repository.
* Installed `jq`, to make it easier to parse the JSON responses.
```bash
# Pull an image from Docker Hub
docker pull nginx:latest
# Tag that image
docker tag nginx:latest <dtr-url>/library/nginx:1
# Log into DTR
docker login <dtr-url>
# Push the image to DTR and sign it
DOCKER_CONTENT_TRUST=1 docker push <dtr-url>/library/nginx:1
# Get global-scope authorization token, and store it in TOKEN
export TOKEN=$(curl --insecure --silent \
--user '<user>:<password>' \
'https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=repository:<dtr-url>/<repository>:pull' | jq --raw-output .token)
# Get audit logs for all repositories and pretty-print it
# If you pushed the image less than 60 seconds ago, it's possible that
# Docker Content Trust won't show any events. Retry the command after a while.
curl --insecure --silent \
--header "Authorization: Bearer $TOKEN" \
"https://<dtr-url>/v2/<dtr-url>/<dtr-repo>/_trust/changefeed?records=10&change_id=0" | jq .
```

View File

@ -0,0 +1,239 @@
---
title: Troubleshoot batch jobs
description: Learn how Docker Trusted Registry run batch jobs, so that you can troubleshoot when something goes wrong
keywords: dtr, troubleshoot
---
DTR uses a job queue to schedule batch jobs. A job is placed on this work queue,
and a job runner component of DTR consumes work from this cluster-wide job
queue and executes it.
![batch jobs diagram](../../images/troubleshoot-batch-jobs-1.svg)
All DTR replicas have access to the job queue, and have a job runner component
that can get and execute work.
## How it works
When a job is created, it is added to a cluster-wide job queue with the
`waiting` status.
When one of the DTR replicas is ready to claim, it waits a random time of up
to 3 seconds, giving the opportunity to every replica to claim the task.
A replica gets a job by adding it's replica ID to the job. That way, other
replicas know the job has been claimed. Once a replica claims a job it adds
it to an internal queue of jobs, that is sorted by their `scheduledAt` time.
When that time happens, the replica updates the job status to `running`, and
starts executing it.
The job runner component of each DTR replica keeps an `heartbeatExpiration`
entry on the database shared by all replicas. If a replica becomes
unhealthy, other replicas notice this and update that worker status to `dead`.
Also, all the jobs that replica had claimed are updated to the status `worker_dead`,
so that other replicas can claim the job.
## Job types
DTR has several types of jobs.
| Job | Description |
|:------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| gc | Garbage collection job that deletes layers associated with deleted images |
| onlinegc | Garbage collection job that deletes layers associated with deleted images without putting the registry in read only mode |
| onlinegc_metadata | Garbage collection job that deletes metadata associated with deleted images|
| onlinegc_joblogs | Garbage collection job that deletes job logs based on a set job history setting |
| metadatastoremigration | metadatastoremigration is a necessary migration that enables the online gc feature |
| sleep | Sleep is used to test the correctness of the jobrunner. It sleeps for 60 seconds |
| false | False is used to test the correctness of the jobrunner. It runs the `false` command and immediately fails |
| tagmigration | Tag migration is used to synchronize tag and manifest information between the DTR database and the storage backend. |
| bloblinkmigration | bloblinkmigration is a 2.1 to 2.1 upgrade process that adds references for blobs to repositories in the database |
| license_update | License update checks for license expiration extensions if online license updates are enabled |
| scan_check | An image security scanning job. This job does not perform the actual scanning, rather it spawns `scan_check_single` jobs (one for each layer in the image). Once all of the `scan_check_single` jobs are complete, this job will terminate |
| scan_check_single | A security scanning job for a particular layer given by the `parameter: SHA256SUM`. This job breaks up the layer into components and checks each component for vulnerabilities |
| scan_check_all | A security scanning job that updates all of the currently scanned images to display the latest vulnerabilities |
| update_vuln_db | A job that is created to update DTR's vulnerability database. It uses an Internet connection to check for database updates through `https://dss-cve-updates.docker.com/` and updates the `dtr-scanningstore` container if there is a new update available |
| scannedlayermigration | scannedlayermigration is a 2.4 to 2.5 upgrade process that restructures scanned image data |
| push_mirror_tag | A job that pushes a tag to another registry after a push mirror policy has been evaluated |
| poll_mirror | A global cron that evaluates poll mirroring policies |
| webhook | A job that is used to dispatch a webhook payload to a single endpoint |
## Job status
Jobs can be in one of the following status:
| Status | Description |
|:----------------|:------------------------------------------------------------------------------------------------------------------------------------------|
| waiting | The job is unclaimed and waiting to be picked up by a worker |
| running | The worker defined by `workerID` is currently running the job |
| done | The job has successfully completed |
| error | The job has completed with errors |
| cancel_request | The worker monitors the job statuses in the database. If the status for a job changes to `cancel_request`, the worker will cancel the job |
| cancel | The job has been canceled and not fully executed |
| deleted | The job and logs have been removed |
| worker_dead | The worker for this job has been declared `dead` and the job will not continue |
| worker_shutdown | The worker that was running this job has been gracefully stopped |
| worker | resurrection| The worker for this job has reconnected to the database and will cancel these jobs |
## Job capacity
Each job runner has a limited capacity and won't claim jobs that require a
higher capacity. You can see the capacity of a job runner using the
`GET /api/v0/workers` endpoint:
```json
{
"workers": [
{
"id": "000000000000",
"status": "running",
"capacityMap": {
"scan": 1,
"scanCheck": 1
},
"heartbeatExpiration": "2017-02-18T00:51:02Z"
}
]
}
```
This means that the worker with replica ID `000000000000` has a capacity of 1
`scan` and 1 `scanCheck`. If this worker notices that the following jobs
are available:
```json
{
"jobs": [
{
"id": "0",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scan": 1
}
},
{
"id": "1",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scan": 1
}
},
{
"id": "2",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scanCheck": 1
}
}
]
}
```
Our worker will be able to pick up job id `0` and `2` since it has the capacity
for both, while id `1` will have to wait until the previous scan job is complete:
```json
{
"jobs": [
{
"id": "0",
"workerID": "000000000000",
"status": "running",
"capacityMap": {
"scan": 1
}
},
{
"id": "1",
"workerID": "",
"status": "waiting",
"capacityMap": {
"scan": 1
}
},
{
"id": "2",
"workerID": "000000000000",
"status": "running",
"capacityMap": {
"scanCheck": 1
}
}
]
}
```
## Troubleshoot jobs
You can get the list of jobs, using the `GET /api/v0/jobs/` endpoint. Each job
looks like this:
```json
{
"id": "1fcf4c0f-ff3b-471a-8839-5dcb631b2f7b",
"retryFromID": "1fcf4c0f-ff3b-471a-8839-5dcb631b2f7b",
"workerID": "000000000000",
"status": "done",
"scheduledAt": "2017-02-17T01:09:47.771Z",
"lastUpdated": "2017-02-17T01:10:14.117Z",
"action": "scan_check_single",
"retriesLeft": 0,
"retriesTotal": 0,
"capacityMap": {
"scan": 1
},
"parameters": {
"SHA256SUM": "1bacd3c8ccb1f15609a10bd4a403831d0ec0b354438ddbf644c95c5d54f8eb13"
},
"deadline": "",
"stopTimeout": ""
}
```
The fields of interest here are:
* `id`: the ID of the job
* `workerID`: the ID of the worker in a DTR replica that is running this job
* `status`: the current state of the job
* `action`: what job the worker will actually perform
* `capacityMap`: the available capacity a worker needs for this job to run
## Cron jobs
Several of the jobs performed by DTR are run in a recurrent schedule. You can
see those jobs using the `GET /api/v0/crons` endpoint:
```json
{
"crons": [
{
"id": "48875b1b-5006-48f5-9f3c-af9fbdd82255",
"action": "license_update",
"schedule": "57 54 3 * * *",
"retries": 2,
"capacityMap": null,
"parameters": null,
"deadline": "",
"stopTimeout": "",
"nextRun": "2017-02-22T03:54:57Z"
},
{
"id": "b1c1e61e-1e74-4677-8e4a-2a7dacefffdc",
"action": "update_db",
"schedule": "0 0 3 * * *",
"retries": 0,
"capacityMap": null,
"parameters": null,
"deadline": "",
"stopTimeout": "",
"nextRun": "2017-02-22T03:00:00Z"
}
]
}
```
The `schedule` uses a Unix crontab syntax.

View File

@ -0,0 +1,244 @@
---
title: Troubleshoot Docker Trusted Registry
description: Learn how to troubleshoot your DTR installation.
keywords: registry, monitor, troubleshoot
---
This guide contains tips and tricks for troubleshooting DTR problems.
## Troubleshoot overlay networks
High availability in DTR depends on swarm overlay networking. One way to test
if overlay networks are working correctly is to deploy containers to the same
overlay network on different nodes and see if they can ping one another.
Use SSH to log into a node and run:
```bash
docker run -it --rm \
--net dtr-ol --name overlay-test1 \
--entrypoint sh {{ page.dtr_org }}/{{ page.dtr_repo }}
```
Then use SSH to log into another node and run:
```bash
docker run -it --rm \
--net dtr-ol --name overlay-test2 \
--entrypoint ping {{ page.dtr_org }}/{{ page.dtr_repo }} -c 3 overlay-test1
```
If the second command succeeds, it indicates overlay networking is working
correctly between those nodes.
You can run this test with any attachable overlay network and any Docker image
that has `sh` and `ping`.
## Access RethinkDB directly
DTR uses RethinkDB for persisting data and replicating it across replicas.
It might be helpful to connect directly to the RethinkDB instance running on a
DTR replica to check the DTR internal state.
> **Warning**: Modifying RethinkDB directly is not supported and may cause
> problems.
{: .warning }
### via RethinkCLI
As of v2.5.5, the [RethinkCLI has been removed](/ee/dtr/release-notes/#255) from the RethinkDB image along with other unused components. You can now run RethinkCLI from a separate image in the `dockerhubenterprise` organization. Note that the commands below are using separate tags for non-interactive and interactive modes.
#### Non-interactive
Use SSH to log into a node that is running a DTR replica, and run the following:
{% raw %}
```bash
# List problems in the cluster detected by the current node.
REPLICA_ID=$(docker container ls --filter=name=dtr-rethink --format '{{.Names}}' | cut -d'/' -f2 | cut -d'-' -f3 | head -n 1) && echo 'r.db("rethinkdb").table("current_issues")' | docker run --rm -i --net dtr-ol -v "dtr-ca-${REPLICA_ID}:/ca" -e DTR_REPLICA_ID=$REPLICA_ID dockerhubenterprise/rethinkcli:v2.2.0-ni non-interactive
```
{% endraw %}
On a healthy cluster the output will be `[]`.
#### Interactive
Starting in DTR 2.5.5, you can run RethinkCLI from a separate image. First, set an environment variable for your DTR replica ID:
{% raw %}
```bash
REPLICA_ID=$(docker inspect -f '{{.Name}}' $(docker ps -q -f name=dtr-rethink) | cut -f 3 -d '-')
```
{% endraw %}
RethinkDB stores data in different databases that contain multiple tables. Run the following command to get into interactive mode
and query the contents of the DB:
```bash
docker run -it --rm --net dtr-ol -v dtr-ca-$REPLICA_ID:/ca dockerhubenterprise/rethinkcli:v2.3.0 $REPLICA_ID
```
```none
# List problems in the cluster detected by the current node.
> r.db("rethinkdb").table("current_issues")
[]
# List all the DBs in RethinkDB
> r.dbList()
[ 'dtr2',
'jobrunner',
'notaryserver',
'notarysigner',
'rethinkdb' ]
# List the tables in the dtr2 db
> r.db('dtr2').tableList()
[ 'blob_links',
'blobs',
'client_tokens',
'content_caches',
'events',
'layer_vuln_overrides',
'manifests',
'metrics',
'namespace_team_access',
'poll_mirroring_policies',
'promotion_policies',
'properties',
'pruning_policies',
'push_mirroring_policies',
'repositories',
'repository_team_access',
'scanned_images',
'scanned_layers',
'tags',
'user_settings',
'webhooks' ]
# List the entries in the repositories table
> r.db('dtr2').table('repositories')
[ { enableManifestLists: false,
id: 'ac9614a8-36f4-4933-91fa-3ffed2bd259b',
immutableTags: false,
name: 'test-repo-1',
namespaceAccountID: 'fc3b4aec-74a3-4ba2-8e62-daed0d1f7481',
namespaceName: 'admin',
pk: '3a4a79476d76698255ab505fb77c043655c599d1f5b985f859958ab72a4099d6',
pulls: 0,
pushes: 0,
scanOnPush: false,
tagLimit: 0,
visibility: 'public' },
{ enableManifestLists: false,
id: '9f43f029-9683-459f-97d9-665ab3ac1fda',
immutableTags: false,
longDescription: '',
name: 'testing',
namespaceAccountID: 'fc3b4aec-74a3-4ba2-8e62-daed0d1f7481',
namespaceName: 'admin',
pk: '6dd09ac485749619becaff1c17702ada23568ebe0a40bb74a330d058a757e0be',
pulls: 0,
pushes: 0,
scanOnPush: false,
shortDescription: '',
tagLimit: 1,
visibility: 'public' } ]
```
Individual DBs and tables are a private implementation detail and may change in DTR
from version to version, but you can always use `dbList()` and `tableList()` to explore
the contents and data structure.
[Learn more about RethinkDB queries](https://www.rethinkdb.com/docs/guide/javascript/).
### via API
To check on the overall status of your DTR cluster without interacting with RethinkCLI, run the following API request:
```bash
curl -u admin:$TOKEN -X GET "https://<dtr-url>/api/v0/meta/cluster_status" -H "accept: application/json"
```
#### Example API Response
```none
{
"rethink_system_tables": {
"cluster_config": [
{
"heartbeat_timeout_secs": 10,
"id": "heartbeat"
}
],
"current_issues": [],
"db_config": [
{
"id": "339de11f-b0c2-4112-83ac-520cab68d89c",
"name": "notaryserver"
},
{
"id": "aa2e893f-a69a-463d-88c1-8102aafebebc",
"name": "dtr2"
},
{
"id": "bdf14a41-9c31-4526-8436-ab0fed00c2fd",
"name": "jobrunner"
},
{
"id": "f94f0e35-b7b1-4a2f-82be-1bdacca75039",
"name": "notarysigner"
}
],
"server_status": [
{
"id": "9c41fbc6-bcf2-4fad-8960-d117f2fdb06a",
"name": "dtr_rethinkdb_5eb9459a7832",
"network": {
"canonical_addresses": [
{
"host": "dtr-rethinkdb-5eb9459a7832.dtr-ol",
"port": 29015
}
],
"cluster_port": 29015,
"connected_to": {
"dtr_rethinkdb_56b65e8c1404": true
},
"hostname": "9e83e4fee173",
"http_admin_port": "<no http admin>",
"reql_port": 28015,
"time_connected": "2019-02-15T00:19:22.035Z"
},
}
...
]
}
}
```
## Recover from an unhealthy replica
When a DTR replica is unhealthy or down, the DTR web UI displays a warning:
```none
Warning: The following replicas are unhealthy: 59e4e9b0a254; Reasons: Replica reported health too long ago: 2017-02-18T01:11:20Z; Replicas 000000000000, 563f02aba617 are still healthy.
```
To fix this, you should remove the unhealthy replica from the DTR cluster,
and join a new one. Start by running:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} remove \
--ucp-insecure-tls
```
And then:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} join \
--ucp-node <ucp-node-name> \
--ucp-insecure-tls
```

View File

@ -0,0 +1,126 @@
---
title: Upgrade DTR
description: Learn how to upgrade your Docker Trusted Registry
keywords: dtr, upgrade, install
---
{% assign previous_version="2.5" %}
DTR uses [semantic versioning](http://semver.org/) and Docker aims to achieve specific
guarantees while upgrading between versions. While downgrades are not supported, Docker supports upgrades according to the following rules:
* When upgrading from one patch version to another, you can skip patch versions
because no data migration is done for patch versions.
* When upgrading between minor versions, you ***cannot*** skip versions, but you can
upgrade from any patch version of the previous minor version to any patch
version of the current minor version.
* When upgrading between major versions, make sure to upgrade one major
version at a time &ndash; and also upgrade to the earliest available minor
version. We strongly recommend upgrading to the latest minor/patch
version for your major version first.
| Description | From | To | Supported |
|:-------------------------------------|:------|:----------|:----------|
| patch upgrade | x.y.0 | x.y.1 | yes |
| skip patch version | x.y.0 | x.y.2 | yes |
| patch downgrade | x.y.2 | x.y.1 | no |
| minor upgrade | x.y.* | x.y+1.* | yes |
| skip minor version | x.y.* | x.y+2.* | no |
| minor downgrade | x.y.* | x.y-1.* | no |
| skip major version | x.*.* | x+2.*.* | no |
| major downgrade | x.*.* | x-1.*.* | no |
| major upgrade | x.y.z | x+1.0.0 | yes |
| major upgrade skipping minor version | x.y.z | x+1.y+1.z | no |
There may be at most a few seconds of interruption during the upgrade of a
DTR cluster. Schedule the upgrade to take place outside of peak hours
to avoid any business impacts.
## 2.5 to 2.6 upgrade
> Upgrade Best Practices
>
> There are [important changes to the upgrade process](/ee/upgrade) that, if not correctly followed, can have impact on the availability of applications running on the Swarm during upgrades. These constraints impact any upgrades coming from any version before `18.09` to version `18.09` or greater. See [Cluster Upgrade Best Practices](/ee/upgrade.md#cluster-upgrade-best-practices) for more details. Additionally, to ensure high availability during the DTR upgrade, you can also drain the DTR replicas and move their workloads to updated workers. To do this, you can join new workers as DTR replicas to your existing cluster and then remove the old replicas. See [docker/dtr join](/reference/dtr/2.6/cli/join) and [docker/dtr remove](/reference/dtr/2.6/cli/remove) for command options and details.
## Minor upgrade
Before starting your upgrade, make sure that:
* The version of UCP you are using is supported by the version of DTR you
are trying to upgrade to. [Check the compatibility matrix](https://success.docker.com/article/compatibility-matrix).
* You have a recent [DTR backup](disaster-recovery/create-a-backup).
* You [disable Docker content trust in UCP](/ee/ucp/admin/configure/run-only-the-images-you-trust/).
* You [meet the system requirements](install/system-requirements).
### Step 1. Upgrade DTR to {{ previous_version }} if necessary
Make sure you are running DTR {{ previous_version }}. If that is not the case,
[upgrade your installation to the {{ previous_version }} version](../{{ previous_version }}/guides/admin/upgrade/).
### Step 2. Upgrade DTR
Then pull the latest version of DTR:
```bash
docker pull {{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }}
```
Make sure you have at least [16GB of available RAM](install/system-requirements) on the node you are running the upgrade on. If the DTR node does not have access to the internet, you can
follow the [offline installation documentation](install/install-offline)
to get the images.
Once you have the latest image on your machine (and the images on the target
nodes if upgrading offline), run the upgrade command:
```bash
docker run -it --rm \
{{ page.dtr_org }}/{{ page.dtr_repo }}:{{ page.dtr_version }} upgrade \
--ucp-insecure-tls
```
By default the upgrade command runs in interactive mode and prompts you for
any necessary information. You can also check the
[reference documentation](/reference/dtr/2.6/cli/index.md) for other existing flags.
The upgrade command will start replacing every container in your DTR cluster,
one replica at a time. It will also perform certain data migrations. If anything
fails or the upgrade is interrupted for any reason, you can rerun the upgrade
command and it will resume from where it left off.
#### Metadata Store Migration
When upgrading from `2.5` to `2.6`, the system will run a `metadatastoremigration` job after a successful upgrade. This involves migrating the blob links for your images which is necessary for online garbage collection. With `2.6`, you can log in to the DTR web interface and navigate to **System > Job Logs** to check the status of the `metadatastoremigration` job. See [Audit Jobs via the Web Interface](/ee/dtr/admin/manage-jobs/audit-jobs-via-ui/) for more details.
![](../images/migration-warning.png){: .with-border}
Garbage collection is disabled while the migration is running. In the case of a failed `metadatastoremigration`, the system will retry twice.
![](../images/migration-error.png){: .with-border}
If the three attempts fail, you will have to retrigger the `metadatastoremigration` job manually. To do so, send a `POST` request to the `/api/v0/jobs` endpoint:
```bash
curl https://<dtr-external-url>/api/v0/jobs -X POST \
-u username:accesstoken -H 'Content-Type':'application/json' -d \
'{"action": "metadatastoremigration"}'
```
Alternatively, select **API** from the bottom left navigation pane of the DTR web interface and use the Swagger UI to send your API request.
## Patch upgrade
A patch upgrade changes only the DTR containers and is always safer than a minor version
upgrade. The command is the same as for a minor upgrade.
## DTR cache upgrade
If you have previously [deployed a cache](/ee/dtr/admin/configure/deploy-caches/), make sure to [upgrade the node dedicated for your cache](/ee/upgrade) to keep it in sync with your upstream DTR replicas. This prevents authentication errors and other weird behaviors.
## Download the vulnerability database
After upgrading DTR, you need to redownload the vulnerability database.
[Learn how to update your vulnerability database](configure/set-up-vulnerability-scans.md#update-the-cve-scanning-database).
## Where to go next
- [Release notes](../release-notes)
- [Garbage collection in v2.5](/datacenter/dtr/2.5/guides/admin/configure/garbage-collection/)

View File

@ -0,0 +1,102 @@
---
title: DTR architecture
description: Learn about the architecture of Docker Trusted Registry.
keywords: registry, dtr, architecture
---
Docker Trusted Registry (DTR) is a containerized application that runs on a
Docker Universal Control Plane cluster.
![](images/architecture-1.svg)
Once you have DTR deployed, you use your Docker CLI client to login, push, and
pull images.
## Under the hood
For high-availability you can deploy multiple DTR replicas, one on each UCP
worker node.
![](images/architecture-2.svg)
All DTR replicas run the same set of services and changes to their configuration
are automatically propagated to other replicas.
## DTR internal components
When you install DTR on a node, the following containers are started:
| Name | Description |
|:-------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------|
| dtr-api-&lt;replica_id&gt; | Executes the DTR business logic. It serves the DTR web application, and API |
| dtr-garant-&lt;replica_id&gt; | Manages DTR authentication |
| dtr-jobrunner-&lt;replica_id&gt; | Runs cleanup jobs in the background |
| dtr-nginx-&lt;replica_id&gt; | Receives http and https requests and proxies them to other DTR components. By default it listens to ports 80 and 443 of the host |
| dtr-notary-server-&lt;replica_id&gt; | Receives, validates, and serves content trust metadata, and is consulted when pushing or pulling to DTR with content trust enabled |
| dtr-notary-signer-&lt;replica_id&gt; | Performs server-side timestamp and snapshot signing for content trust metadata |
| dtr-registry-&lt;replica_id&gt; | Implements the functionality for pulling and pushing Docker images. It also handles how images are stored |
| dtr-rethinkdb-&lt;replica_id&gt; | A database for persisting repository metadata |
| dtr-scanningstore-&lt;replica_id&gt; | Stores security scanning data |
All these components are for internal use of DTR. Don't use them in your applications.
## Networks used by DTR
To allow containers to communicate, when installing DTR the following networks
are created:
| Name | Type | Description |
|:-------|:--------|:---------------------------------------------------------------------------------------|
| dtr-ol | overlay | Allows DTR components running on different nodes to communicate, to replicate DTR data |
## Volumes used by DTR
DTR uses these named volumes for persisting data:
| Volume name | Description |
|:------------------------------------|:---------------------------------------------------------------------------------|
| dtr-ca-&lt;replica_id&gt; | Root key material for the DTR root CA that issues certificates |
| dtr-notary-&lt;replica_id&gt; | Certificate and keys for the Notary components |
| dtr-postgres-&lt;replica_id&gt; | Vulnerability scans data |
| dtr-registry-&lt;replica_id&gt; | Docker images data, if DTR is configured to store images on the local filesystem |
| dtr-rethink-&lt;replica_id&gt; | Repository metadata |
| dtr-nfs-registry-&lt;replica_id&gt; | Docker images data, if DTR is configured to store images on NFS |
You can customize the volume driver used for these volumes, by creating the
volumes before installing DTR. During the installation, DTR checks which volumes
don't exist in the node, and creates them using the default volume driver.
By default, the data for these volumes can be found at
`/var/lib/docker/volumes/<volume-name>/_data`.
## Image storage
By default, Docker Trusted Registry stores images on the filesystem of the node
where it is running, but you should configure it to use a centralized storage
backend.
![](images/architecture-3.svg)
DTR supports these storage backends:
* NFS
* Amazon S3
* Cleversafe
* Google Cloud Storage
* OpenStack Swift
* Microsoft Azure
## How to interact with DTR
DTR has a web UI where you can manage settings and user permissions.
![](images/architecture-4.svg)
You can push and pull images using the standard Docker CLI client or other tools
that can interact with a Docker registry.
## Where to go next
* [System requirements](admin/install/system-requirements.md)
* [Install DTR](admin/install/index.md)

View File

@ -0,0 +1,18 @@
---
description: Page for deprecation announcements.
keywords: dtr, manifest list, api, repository, digest
title: Deprecation Notice
---
This document outlines the functionalities or components within DTR that will be deprecated.
### Enable Manifest List via the API
#### 2.5 and 2.6
Since `v2.5`, it has been possible for repository admins to autogenerate manifest lists when [creating a repository via the API](/datacenter/dtr/2.5/reference/api/). You accomplish this by setting `enableManifestLists` to `true` when sending a POST request to the `/api/v0/repositories/{namespace}` endpoint. When enabled for a repository, any image that you push to an existing tag will be appended to the list of manifests for that tag. `enableManifestLists` is set to false by default, which means pushing a new image to an existing tag will overwrite the manifest entry for that tag.
#### 2.7
The above behavior and the `enableManifestLists` field will be removed in `v2.7`. Starting in `v2.7`, you can use the DTR CLI to create and push a manifest list to any repository.

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 250" style="enable-background:new 0 0 740 250;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;}
.st2{font-family:'OpenSans';}
.st3{font-size:14px;}
.st4{fill-rule:evenodd;clip-rule:evenodd;fill:#1488C6;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:#00B6B5;}
.st6{fill:none;stroke:#82949E;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st7{fill-rule:evenodd;clip-rule:evenodd;fill:#8F9EA8;}
.st8{fill:#637986;}
.st9{font-family:'Courier-Bold';}
</style>
<rect class="st0" width="740" height="250"/>
<title>architecture-1</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="architecture-1">
<g id="Group" transform="translate(33.000000, 51.000000)">
<g id="stack" transform="translate(150.000000, 0.000000)">
<g id="servers" transform="translate(0.000000, 114.000000)">
<g id="cloud">
<path id="Rectangle-138" class="st1" d="M2,0h168c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"
/>
<text transform="matrix(1 0 0 1 42.5098 23)" class="st0 st2 st3">cloud servers</text>
</g>
<g id="virtual" transform="translate(176.000000, 0.000000)">
<path class="st1" d="M2,0h168c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 39.8608 23)" class="st0 st2 st3">virtual servers</text>
</g>
<g id="physical" transform="translate(352.000000, 0.000000)">
<path class="st1" d="M2,0h168c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 34.2075 23)" class="st0 st2 st3">physical servers</text>
</g>
</g>
<g id="docker" transform="translate(0.000000, 76.000000)">
<path class="st4" d="M2,0h520c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 205.936 23)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g id="ucp" transform="translate(0.000000, 38.000000)">
<path class="st4" d="M2,0h520c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 185.5366 23)" class="st0 st2 st3">Universal Control Plane</text>
</g>
<g id="dtr">
<path class="st4" d="M2,0h168c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 8.1318 23)" class="st0 st2 st3">Docker Trusted Registry</text>
</g>
<g id="your-apps" transform="translate(176.000000, 0.000000)">
<path class="st5" d="M2,0h344c1.1,0,2,0.9,2,2v30c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 118.4282 23)" class="st0 st2 st3">your applications</text>
</g>
</g>
<g id="commands" transform="translate(0.000000, 7.000000)">
<g id="command-2" transform="translate(0.000000, 38.000000)">
<path id="Line" class="st6" d="M101,10h35"/>
<circle id="Oval" class="st7" cx="138" cy="10" r="5"/>
<text transform="matrix(1 0 0 1 0 12)" class="st8 st9 st3">docker run</text>
</g>
<g id="command-1">
<path class="st6" d="M101,9h35"/>
<circle class="st1" cx="138" cy="9" r="5"/>
<text transform="matrix(1 0 0 1 0 12)" class="st8 st9 st3">docker push</text>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 250" style="enable-background:new 0 0 740 250;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#82949E;}
.st2{font-family:'OpenSans';}
.st3{font-size:10px;}
.st4{fill-rule:evenodd;clip-rule:evenodd;fill:#445D6E;}
.st5{font-size:8px;}
.st6{fill-rule:evenodd;clip-rule:evenodd;fill:#1488C6;}
.st7{fill:none;stroke:#445D6E;stroke-width:2;}
.st8{fill-rule:evenodd;clip-rule:evenodd;fill:#FFB463;}
.st9{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
</style>
<rect class="st0" width="738" height="250"/>
<title>architecture-2</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="architecture-2">
<text transform="matrix(1 0 0 1 28.025 239.0095)" class="st1 st2 st3">UCP cluster</text>
<g id="nodes" transform="translate(36.000000, 15.000000)">
<g id="workers" transform="translate(233.000000, 116.000000)">
<g id="node-1-copy">
<g id="node">
<g id="node-label">
<path id="Rectangle-127" class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">worker node</text>
</g>
</g>
<g id="engine" transform="translate(1.000000, 79.000000)">
<path id="Rectangle-138" class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"
/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g id="ucp" transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<path id="node-border" class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy-2" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<g id="worker-dtr" transform="translate(347.000000, 0.000000)">
<g id="node-1">
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<g id="dtr" transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st2 st3">DTR</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-2" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st2 st3">DTR</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-3" transform="translate(214.000000, 0.000000)">
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st2 st3">DTR</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<g id="manager-ucp">
<g transform="translate(214.000000, 0.000000)">
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">manager node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 16.0298 15)" class="st0 st2 st3">UCP manager</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">manager node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 16.0298 15)" class="st0 st2 st3">UCP manager</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g>
<g>
<g>
<path class="st4" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st5">manager node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st6" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 16.0298 15)" class="st0 st2 st3">UCP manager</text>
</g>
<path class="st7" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
</g>
<path id="group" class="st9" d="M23,3h683c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H23c-1.1,0-2-0.9-2-2V5C21,3.9,21.9,3,23,3z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 350" style="enable-background:new 0 0 740 350;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#445D6E;}
.st2{fill:#F7F8F9;}
.st3{font-family:'OpenSans';}
.st4{font-size:10px;}
.st5{fill:#82949E;}
.st6{fill:none;stroke:#445D6E;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st7{fill:none;stroke:#F7F8F9;stroke-width:2;}
.st8{fill-rule:evenodd;clip-rule:evenodd;fill:#FFB463;}
.st9{fill:none;stroke:#FFB463;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st10{font-size:8px;}
.st11{fill-rule:evenodd;clip-rule:evenodd;fill:#1488C6;}
.st12{fill:none;stroke:#445D6E;stroke-width:2;}
.st13{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
</style>
<rect y="2" class="st0" width="740" height="345"/>
<title>architecture-3</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="architecture-3">
<g transform="translate(154.000000, 18.000000)">
<g id="object-storage" transform="translate(34.000000, 235.000000)">
<path id="node-border" class="st1" d="M2,0h361c1.1,0,2,0.9,2,2v76c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 131.9214 44)" class="st2 st3 st4">shared object storage</text>
</g>
<g>
<text transform="matrix(1 0 0 1 7.025 206.0095)" class="st5 st3 st4">DTR cluster</text>
<g id="arrows-copy" transform="translate(104.000000, 166.000000)">
<g id="arrow-copy-2" transform="translate(218.500000, 37.000000) rotate(-90.000000) translate(-218.500000, -37.000000) translate(182.000000, 33.000000)">
<path id="Line" class="st6" d="M2,4h71"/>
<g id="Oval">
<g>
<circle id="path-1" class="st1" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-3" transform="translate(111.500000, 37.000000) rotate(-90.000000) translate(-111.500000, -37.000000) translate(75.000000, 33.000000)">
<path class="st6" d="M2,4h71"/>
<g>
<g>
<circle id="path-2" class="st1" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-4" transform="translate(4.500000, 37.000000) rotate(-90.000000) translate(-4.500000, -37.000000) translate(-32.000000, 33.000000)">
<path class="st6" d="M2,4h71"/>
<g>
<g>
<circle id="path-3" class="st1" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
<g id="network" transform="translate(33.000000, 23.000000)">
<path id="Rectangle-138" class="st8" d="M2,0h362c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"
/>
<text transform="matrix(1 0 0 1 146.0513 15)" class="st0 st3 st4">overlay network</text>
</g>
<g id="arrows" transform="translate(104.000000, 42.000000)">
<g transform="translate(218.500000, 18.000000) rotate(-90.000000) translate(-218.500000, -18.000000) translate(201.000000, 14.000000)">
<path class="st9" d="M0,4h31"/>
<g>
<g>
<circle id="path-4" class="st8" cx="31" cy="4" r="4"/>
</g>
<circle class="st7" cx="31" cy="4" r="5"/>
</g>
</g>
<g transform="translate(111.500000, 18.000000) rotate(-90.000000) translate(-111.500000, -18.000000) translate(94.000000, 14.000000)">
<path class="st9" d="M0,4h31"/>
<g>
<g>
<circle id="path-5" class="st8" cx="31" cy="4" r="4"/>
</g>
<circle class="st7" cx="31" cy="4" r="5"/>
</g>
</g>
<g transform="translate(4.500000, 18.000000) rotate(-90.000000) translate(-4.500000, -18.000000) translate(-13.000000, 14.000000)">
<path class="st9" d="M0,4h31"/>
<g>
<g>
<circle id="path-6" class="st8" cx="31" cy="4" r="4"/>
</g>
<circle class="st7" cx="31" cy="4" r="5"/>
</g>
</g>
</g>
<g id="nodes" transform="translate(60.000000, 70.000000)">
<g id="node-3" transform="translate(214.000000, 0.000000)">
<g id="node">
<g id="node-label">
<path id="Rectangle-127" class="st1" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st10">worker node</text>
</g>
</g>
<g id="engine" transform="translate(1.000000, 79.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker Engine EE</text>
</g>
<g id="ucp" transform="translate(1.000000, 56.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st3 st4">UCP worker</text>
</g>
<g id="dtr" transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st3 st4">DTR</text>
</g>
<path class="st12" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-2" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st1" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st10">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st3 st4">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st3 st4">DTR</text>
</g>
<path class="st12" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1">
<g>
<g>
<path class="st1" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st10">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st3 st4">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st3 st4">DTR</text>
</g>
<path class="st12" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<path id="group" class="st13" d="M2,0h429c1.1,0,2,0.9,2,2v212c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -0,0 +1,302 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 350" style="enable-background:new 0 0 740 350;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#E0E4E7;}
.st2{font-family:'OpenSans';}
.st3{font-size:10px;}
.st4{fill:none;stroke:#E0E4E7;stroke-width:2;stroke-dasharray:5,5,5,5;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:#445D6E;}
.st6{fill:none;stroke:#445D6E;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st7{fill:none;stroke:#F7F8F9;stroke-width:2;}
.st8{fill-rule:evenodd;clip-rule:evenodd;fill:#E0E4E7;}
.st9{font-size:8px;}
.st10{fill-rule:evenodd;clip-rule:evenodd;fill:#A1CFE8;}
.st11{fill:none;stroke:#E0E4E7;stroke-width:2;}
.st12{fill-rule:evenodd;clip-rule:evenodd;fill:#1488C6;}
.st13{fill-rule:evenodd;clip-rule:evenodd;fill:#FFB463;}
.st14{fill:none;stroke:#445D6E;stroke-width:2;}
.st15{fill:#82949E;}
.st16{font-size:12px;}
.st17{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;}
</style>
<rect class="st0" width="740" height="350"/>
<title>architecture-4</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="architecture-4">
<g id="ddc" transform="translate(30.000000, 56.000000)">
<g id="swarm-group" transform="translate(0.000000, 42.000000)">
<text transform="matrix(1 0 0 1 15.8219 236.0095)" class="st1 st2 st3">Docker swarm</text>
<path id="group" class="st4" d="M2,0h699c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="load-balancers" transform="translate(23.000000, 0.000000)">
<g id="right" transform="translate(347.000000, 0.000000)">
<g id="main">
<path id="Rectangle-138" class="st5" d="M2,0h305c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"
/>
<text transform="matrix(1 0 0 1 111.438 15)" class="st0 st2 st3">your load balancer</text>
</g>
<g id="arrows" transform="translate(43.000000, 21.000000)">
<g id="arrow-copy-3" transform="translate(218.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-218.500000, -17.000000) translate(202.000000, 13.000000)">
<path id="Line" class="st6" d="M2,4h31"/>
<g id="Oval">
<g>
<circle id="path-1" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy" transform="translate(111.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-111.500000, -17.000000) translate(95.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-2" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-2" transform="translate(4.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-4.500000, -17.000000) translate(-12.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-3" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
</g>
<g id="left">
<g>
<path class="st5" d="M2,0h305c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 111.438 15)" class="st0 st2 st3">your load balancer</text>
</g>
<g transform="translate(43.000000, 21.000000)">
<g transform="translate(218.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-218.500000, -17.000000) translate(202.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-4" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(111.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-111.500000, -17.000000) translate(95.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-5" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(4.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-4.500000, -17.000000) translate(-12.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-6" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
</g>
</g>
<g id="swam" transform="translate(22.000000, 54.000000)">
<g id="nodes">
<g id="workers" transform="translate(216.000000, 118.000000)">
<g id="node-1">
<g id="node">
<g id="node-label">
<path id="Rectangle-127" class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">worker node</text>
</g>
</g>
<g id="engine" transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g id="ucp" transform="translate(1.000000, 56.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<path id="node-border" class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"
/>
</g>
<g id="node-1-copy-3" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<path class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<g id="workers-dtr" transform="translate(347.000000, 0.000000)">
<g id="node-1-copy-4">
<g>
<g>
<path class="st5" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<g id="ucp-copy" transform="translate(1.000000, 33.000000)">
<path class="st13" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st2 st3">DTR</text>
</g>
<path class="st14" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy-5" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st5" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st13" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st2 st3">DTR</text>
</g>
<path class="st14" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy-6" transform="translate(214.000000, 0.000000)">
<g>
<g>
<path class="st5" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st2 st3">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st13" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st2 st3">DTR</text>
</g>
<path class="st14" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<g id="managers-ucp">
<g>
<g>
<g>
<path class="st5" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">manager node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 16.0298 15)" class="st0 st2 st3">UCP manager</text>
</g>
<path class="st14" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st5" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">manager node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 16.0298 15)" class="st0 st2 st3">UCP manager</text>
</g>
<path class="st14" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy-2" transform="translate(214.000000, 0.000000)">
<g>
<g>
<path class="st5" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st2 st9">manager node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st2 st3">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st12" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 16.0298 15)" class="st0 st2 st3">UCP manager</text>
</g>
<path class="st14" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
</g>
</g>
</g>
<g id="users" transform="translate(174.000000, 5.000000)">
<g transform="translate(347.000000, 0.000000)">
<g id="user">
<text transform="matrix(1 0 0 1 7 41)" class="st15 st2 st16">UI</text>
<path id="Shape" class="st17" d="M13,13c3.6,0,6.5-2.9,6.5-6.5C19.5,2.9,16.6,0,13,0S6.5,2.9,6.5,6.5C6.5,10.1,9.4,13,13,13
L13,13z M13,16.2c-4.3,0-13,2.2-13,6.5V26h26v-3.2C26,18.4,17.3,16.2,13,16.2L13,16.2z"/>
</g>
<g id="user-copy" transform="translate(42.000000, 0.000000)">
<text transform="matrix(1 0 0 1 4 41)" class="st15 st2 st16">CLI</text>
<path class="st17" d="M13,13c3.6,0,6.5-2.9,6.5-6.5C19.5,2.9,16.6,0,13,0S6.5,2.9,6.5,6.5C6.5,10.1,9.4,13,13,13L13,13z
M13,16.2c-4.3,0-13,2.2-13,6.5V26h26v-3.2C26,18.4,17.3,16.2,13,16.2L13,16.2z"/>
</g>
</g>
<g>
<g>
<text transform="matrix(1 0 0 1 7 41)" class="st15 st2 st16">UI</text>
<path class="st17" d="M13,13c3.6,0,6.5-2.9,6.5-6.5C19.5,2.9,16.6,0,13,0S6.5,2.9,6.5,6.5C6.5,10.1,9.4,13,13,13L13,13z
M13,16.2c-4.3,0-13,2.2-13,6.5V26h26v-3.2C26,18.4,17.3,16.2,13,16.2L13,16.2z"/>
</g>
<g transform="translate(42.000000, 0.000000)">
<text transform="matrix(1 0 0 1 4 41)" class="st15 st2 st16">CLI</text>
<path class="st17" d="M13,13c3.6,0,6.5-2.9,6.5-6.5C19.5,2.9,16.6,0,13,0S6.5,2.9,6.5,6.5C6.5,10.1,9.4,13,13,13L13,13z
M13,16.2c-4.3,0-13,2.2-13,6.5V26h26v-3.2C26,18.4,17.3,16.2,13,16.2L13,16.2z"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,208 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 690 282" style="enable-background:new 0 0 690 282;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{filter:url(#Adobe_OpacityMaskFilter);}
.st2{mask:url(#mask-2_1_);}
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#9967FF;}
.st4{enable-background:new ;}
.st5{fill:#C0C9CE;}
.st6{font-family:'OpenSans';}
.st7{font-size:12px;}
.st8{fill-rule:evenodd;clip-rule:evenodd;fill:#00CBCA;}
.st9{fill-rule:evenodd;clip-rule:evenodd;fill:#C0C9CE;}
.st10{fill-rule:evenodd;clip-rule:evenodd;fill:#445D6E;}
.st11{font-size:16px;}
.st12{fill-rule:evenodd;clip-rule:evenodd;fill:#1AAAF8;}
.st13{fill:none;stroke:#C0C9CE;stroke-width:2;}
</style>
<rect class="st0" width="690" height="282"/>
<title>dtr-authorization-1</title>
<desc>Created with Sketch.</desc>
<g id="Apps">
<defs>
<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="-1" y="-1" width="692" height="284">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="-1" y="-1" width="692" height="284" id="mask-2_1_">
<g class="st1">
<rect id="path-1_1_" class="st0" width="690" height="282"/>
</g>
</mask>
<g id="dtr-authorization-1" class="st2">
<g id="all" transform="translate(175.000000, 62.000000)">
<g id="Group" transform="translate(168.000000, 0.000000)">
<g id="teams">
<g id="billing-team" transform="translate(100.000000, 0.000000)">
<path id="Shape-Copy" class="st3" d="M34.5,26.5c7.3,0,13.2-5.9,13.2-13.2C47.8,5.9,41.8,0,34.5,0S21.2,5.9,21.2,13.2
C21.2,20.6,27.2,26.5,34.5,26.5L34.5,26.5z M34.5,33.1C25.7,33.1,8,37.5,8,46.4V53h53v-6.6C61,37.5,43.3,33.1,34.5,33.1
L34.5,33.1z"/>
<g class="st4">
<text transform="matrix(1 0 0 1 0 68)" class="st5 st6 st7">billing team</text>
</g>
</g>
<g id="blog-team">
<g class="st4">
<text transform="matrix(1 0 0 1 0 68)" class="st5 st6 st7">blog team</text>
</g>
<path id="Shape-Copy-2" class="st8" d="M29.5,26.5c7.3,0,13.2-5.9,13.2-13.2C42.8,5.9,36.8,0,29.5,0S16.2,5.9,16.2,13.2
C16.2,20.6,22.2,26.5,29.5,26.5L29.5,26.5z M29.5,33.1C20.7,33.1,3,37.5,3,46.4V53h53v-6.6C56,37.5,38.3,33.1,29.5,33.1
L29.5,33.1z"/>
</g>
</g>
</g>
<g id="permissions" transform="translate(160.000000, 101.000000)">
<g transform="translate(105.000000, 84.000000)">
<path id="settings" class="st9" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2
c-1.3,0.6-2,1.1-3.1,0.7h0C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9
c0.6,1.3,1.1,2,0.7,3.1C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9
c1.3-0.6,2-1.1,3.1-0.7h0c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9
c-0.6-1.3-1.1-2-0.7-3.1C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3
c1.8,0,3.3,1.5,3.3,3.3S66.8,13.3,65,13.3L65,13.3z"/>
<path id="Shape" class="st9" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3
S15,8.3,15,10L15,10z"/>
<path class="st9" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<g transform="translate(0.000000, 84.000000)">
<path class="st9" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st9" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16c-3.3,0-6-2.7-6-6
c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3S15,8.3,15,10
L15,10z"/>
<path class="st9" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<g transform="translate(105.000000, 42.000000)">
<path class="st9" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st10" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3
S15,8.3,15,10L15,10z"/>
<path class="st10" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<g transform="translate(0.000000, 42.000000)">
<path class="st9" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st10" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3
S15,8.3,15,10L15,10z"/>
<path class="st9" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<g transform="translate(105.000000, 0.000000)">
<path class="st10" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st10" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3
S15,8.3,15,10L15,10z"/>
<path class="st10" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<g>
<path class="st9" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st9" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16c-3.3,0-6-2.7-6-6
c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3S15,8.3,15,10
L15,10z"/>
<path class="st9" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
</g>
<g id="repos" transform="translate(0.000000, 98.000000)">
<g id="node" transform="translate(0.000000, 84.000000)">
<g class="st4">
<text transform="matrix(1 0 0 1 33 19)" class="st5 st6 st11">whale/node</text>
</g>
<path class="st12" d="M27.6,5.9c0.4,0.6,0.5,1.4,0.3,2.2l-4.6,15.2C23,24,22.6,24.6,22,25.1c-0.6,0.5-1.3,0.7-2.1,0.7H4.4
c-0.9,0-1.7-0.3-2.5-0.9s-1.4-1.3-1.7-2.2c-0.3-0.8-0.3-1.5,0-2.1c0,0,0-0.2,0.1-0.5s0.1-0.5,0.1-0.6c0-0.1,0-0.2-0.1-0.4
c0-0.2-0.1-0.3-0.1-0.3c0-0.1,0.1-0.2,0.1-0.4c0.1-0.1,0.2-0.2,0.3-0.4s0.2-0.3,0.3-0.4c0.3-0.4,0.5-0.9,0.8-1.5
c0.2-0.6,0.4-1.1,0.5-1.5c0-0.1,0-0.3,0-0.5c0-0.2,0-0.4,0-0.5c0-0.1,0.1-0.3,0.3-0.5c0.2-0.2,0.3-0.3,0.3-0.4
c0.2-0.4,0.5-0.9,0.7-1.5c0.2-0.6,0.4-1.1,0.4-1.5c0-0.1,0-0.3,0-0.5c0-0.3,0-0.4,0-0.5c0-0.1,0.2-0.3,0.4-0.5
C4.4,8,4.5,7.9,4.5,7.8C4.8,7.5,5,7,5.3,6.4s0.4-1.2,0.5-1.6c0-0.1,0-0.2-0.1-0.4S5.6,4,5.6,3.9c0-0.1,0.1-0.2,0.2-0.3
C5.9,3.5,6,3.3,6.1,3.2C6.2,3,6.3,2.9,6.4,2.8c0.1-0.1,0.2-0.3,0.3-0.5c0.1-0.2,0.2-0.4,0.3-0.6s0.2-0.4,0.3-0.6
c0.1-0.2,0.2-0.4,0.3-0.5S7.8,0.3,8,0.2S8.3,0,8.6,0S9,0,9.4,0.1l0,0.1C9.8,0.1,10.1,0,10.2,0H23c0.8,0,1.5,0.3,1.9,0.9
c0.4,0.6,0.5,1.4,0.3,2.2l-4.6,15.2c-0.4,1.3-0.8,2.2-1.2,2.6c-0.4,0.4-1.1,0.6-2.2,0.6H2.6c-0.3,0-0.5,0.1-0.6,0.3
c-0.1,0.2-0.1,0.4,0,0.7c0.3,0.8,1.1,1.2,2.4,1.2h15.5c0.3,0,0.6-0.1,0.9-0.3c0.3-0.2,0.5-0.4,0.6-0.7l5-16.6
c0.1-0.2,0.1-0.6,0.1-1C27,5.3,27.3,5.6,27.6,5.9L27.6,5.9z M9.7,5.9c0,0.1,0,0.3,0,0.4C9.8,6.4,9.9,6.5,10,6.5h10.2
c0.1,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.4l0.4-1.1c0-0.1,0-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.3-0.2H10.7
c-0.1,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.2-0.3,0.4L9.7,5.9z M8.3,10.2c0,0.1,0,0.3,0,0.4c0.1,0.1,0.2,0.2,0.3,0.2h10.2
c0.1,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.4l0.4-1.1c0-0.1,0-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.3-0.2H9.3
c-0.1,0-0.3,0.1-0.4,0.2S8.7,9,8.6,9.1L8.3,10.2z"/>
</g>
<g id="java" transform="translate(0.000000, 42.000000)">
<g class="st4">
<text transform="matrix(1 0 0 1 33 19)" class="st5 st6 st11">whale/java</text>
</g>
<path class="st12" d="M27.6,5.9c0.4,0.6,0.5,1.4,0.3,2.2l-4.6,15.2C23,24,22.6,24.6,22,25.1c-0.6,0.5-1.3,0.7-2.1,0.7H4.4
c-0.9,0-1.7-0.3-2.5-0.9s-1.4-1.3-1.7-2.2c-0.3-0.8-0.3-1.5,0-2.1c0,0,0-0.2,0.1-0.5s0.1-0.5,0.1-0.6c0-0.1,0-0.2-0.1-0.4
c0-0.2-0.1-0.3-0.1-0.3c0-0.1,0.1-0.2,0.1-0.4c0.1-0.1,0.2-0.2,0.3-0.4s0.2-0.3,0.3-0.4c0.3-0.4,0.5-0.9,0.8-1.5
c0.2-0.6,0.4-1.1,0.5-1.5c0-0.1,0-0.3,0-0.5c0-0.2,0-0.4,0-0.5c0-0.1,0.1-0.3,0.3-0.5c0.2-0.2,0.3-0.3,0.3-0.4
c0.2-0.4,0.5-0.9,0.7-1.5c0.2-0.6,0.4-1.1,0.4-1.5c0-0.1,0-0.3,0-0.5c0-0.3,0-0.4,0-0.5c0-0.1,0.2-0.3,0.4-0.5
C4.4,8,4.5,7.9,4.5,7.8C4.8,7.5,5,7,5.3,6.4s0.4-1.2,0.5-1.6c0-0.1,0-0.2-0.1-0.4S5.6,4,5.6,3.9c0-0.1,0.1-0.2,0.2-0.3
C5.9,3.5,6,3.3,6.1,3.2C6.2,3,6.3,2.9,6.4,2.8c0.1-0.1,0.2-0.3,0.3-0.5c0.1-0.2,0.2-0.4,0.3-0.6s0.2-0.4,0.3-0.6
c0.1-0.2,0.2-0.4,0.3-0.5S7.8,0.3,8,0.2S8.3,0,8.6,0S9,0,9.4,0.1l0,0.1C9.8,0.1,10.1,0,10.2,0H23c0.8,0,1.5,0.3,1.9,0.9
c0.4,0.6,0.5,1.4,0.3,2.2l-4.6,15.2c-0.4,1.3-0.8,2.2-1.2,2.6c-0.4,0.4-1.1,0.6-2.2,0.6H2.6c-0.3,0-0.5,0.1-0.6,0.3
c-0.1,0.2-0.1,0.4,0,0.7c0.3,0.8,1.1,1.2,2.4,1.2h15.5c0.3,0,0.6-0.1,0.9-0.3c0.3-0.2,0.5-0.4,0.6-0.7l5-16.6
c0.1-0.2,0.1-0.6,0.1-1C27,5.3,27.3,5.6,27.6,5.9L27.6,5.9z M9.7,5.9c0,0.1,0,0.3,0,0.4C9.8,6.4,9.9,6.5,10,6.5h10.2
c0.1,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.4l0.4-1.1c0-0.1,0-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.3-0.2H10.7
c-0.1,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.2-0.3,0.4L9.7,5.9z M8.3,10.2c0,0.1,0,0.3,0,0.4c0.1,0.1,0.2,0.2,0.3,0.2h10.2
c0.1,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.4l0.4-1.1c0-0.1,0-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.3-0.2H9.3
c-0.1,0-0.3,0.1-0.4,0.2S8.7,9,8.6,9.1L8.3,10.2z"/>
</g>
<g id="golang">
<g class="st4">
<text transform="matrix(1 0 0 1 33 19)" class="st5 st6 st11">whale/golang</text>
</g>
<path class="st12" d="M27.6,5.9c0.4,0.6,0.5,1.4,0.3,2.2l-4.6,15.2C23,24,22.6,24.6,22,25.1c-0.6,0.5-1.3,0.7-2.1,0.7H4.4
c-0.9,0-1.7-0.3-2.5-0.9s-1.4-1.3-1.7-2.2c-0.3-0.8-0.3-1.5,0-2.1c0,0,0-0.2,0.1-0.5s0.1-0.5,0.1-0.6c0-0.1,0-0.2-0.1-0.4
c0-0.2-0.1-0.3-0.1-0.3c0-0.1,0.1-0.2,0.1-0.4c0.1-0.1,0.2-0.2,0.3-0.4s0.2-0.3,0.3-0.4c0.3-0.4,0.5-0.9,0.8-1.5
c0.2-0.6,0.4-1.1,0.5-1.5c0-0.1,0-0.3,0-0.5c0-0.2,0-0.4,0-0.5c0-0.1,0.1-0.3,0.3-0.5c0.2-0.2,0.3-0.3,0.3-0.4
c0.2-0.4,0.5-0.9,0.7-1.5c0.2-0.6,0.4-1.1,0.4-1.5c0-0.1,0-0.3,0-0.5c0-0.3,0-0.4,0-0.5c0-0.1,0.2-0.3,0.4-0.5
C4.4,8,4.5,7.9,4.5,7.8C4.8,7.5,5,7,5.3,6.4s0.4-1.2,0.5-1.6c0-0.1,0-0.2-0.1-0.4S5.6,4,5.6,3.9c0-0.1,0.1-0.2,0.2-0.3
C5.9,3.5,6,3.3,6.1,3.2C6.2,3,6.3,2.9,6.4,2.8c0.1-0.1,0.2-0.3,0.3-0.5c0.1-0.2,0.2-0.4,0.3-0.6s0.2-0.4,0.3-0.6
c0.1-0.2,0.2-0.4,0.3-0.5S7.8,0.3,8,0.2S8.3,0,8.6,0S9,0,9.4,0.1l0,0.1C9.8,0.1,10.1,0,10.2,0H23c0.8,0,1.5,0.3,1.9,0.9
c0.4,0.6,0.5,1.4,0.3,2.2l-4.6,15.2c-0.4,1.3-0.8,2.2-1.2,2.6c-0.4,0.4-1.1,0.6-2.2,0.6H2.6c-0.3,0-0.5,0.1-0.6,0.3
c-0.1,0.2-0.1,0.4,0,0.7c0.3,0.8,1.1,1.2,2.4,1.2h15.5c0.3,0,0.6-0.1,0.9-0.3c0.3-0.2,0.5-0.4,0.6-0.7l5-16.6
c0.1-0.2,0.1-0.6,0.1-1C27,5.3,27.3,5.6,27.6,5.9L27.6,5.9z M9.7,5.9c0,0.1,0,0.3,0,0.4C9.8,6.4,9.9,6.5,10,6.5h10.2
c0.1,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.4l0.4-1.1c0-0.1,0-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.3-0.2H10.7
c-0.1,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.2-0.3,0.4L9.7,5.9z M8.3,10.2c0,0.1,0,0.3,0,0.4c0.1,0.1,0.2,0.2,0.3,0.2h10.2
c0.1,0,0.3-0.1,0.4-0.2c0.1-0.1,0.2-0.2,0.3-0.4l0.4-1.1c0-0.1,0-0.3,0-0.4c-0.1-0.1-0.2-0.2-0.3-0.2H9.3
c-0.1,0-0.3,0.1-0.4,0.2S8.7,9,8.6,9.1L8.3,10.2z"/>
</g>
</g>
</g>
<g class="st4">
<text transform="matrix(1 0 0 1 270 19)" class="st5 st6 st11">Whale organization</text>
</g>
<g id="border">
<rect class="st13" width="690" height="282"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 350" style="enable-background:new 0 0 740 350;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#445D6E;}
.st2{fill:#F7F8F9;}
.st3{font-family:'OpenSans';}
.st4{font-size:10px;}
.st5{fill:#82949E;}
.st6{fill:none;stroke:#445D6E;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st7{fill:none;stroke:#F7F8F9;stroke-width:2;}
.st8{fill-rule:evenodd;clip-rule:evenodd;fill:#FFB463;}
.st9{fill:none;stroke:#FFB463;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st10{font-size:8px;}
.st11{fill-rule:evenodd;clip-rule:evenodd;fill:#1488C6;}
.st12{fill:none;stroke:#445D6E;stroke-width:2;}
.st13{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
</style>
<rect class="st0" width="740" height="350"/>
<title>configure-external-storage-1</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="configure-external-storage-1">
<g transform="translate(154.000000, 18.000000)">
<g id="object-storage" transform="translate(34.000000, 235.000000)">
<path id="node-border" class="st1" d="M2,0h361c1.1,0,2,0.9,2,2v76c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 131.9214 44)" class="st2 st3 st4">shared object storage</text>
</g>
<g>
<text transform="matrix(1 0 0 1 7.025 206.0095)" class="st5 st3 st4">DTR cluster</text>
<g id="arrows-copy" transform="translate(104.000000, 166.000000)">
<g id="arrow-copy-2" transform="translate(218.500000, 37.000000) rotate(-90.000000) translate(-218.500000, -37.000000) translate(182.000000, 33.000000)">
<path id="Line" class="st6" d="M2,4h71"/>
<g id="Oval">
<g>
<circle id="path-1" class="st1" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-3" transform="translate(111.500000, 37.000000) rotate(-90.000000) translate(-111.500000, -37.000000) translate(75.000000, 33.000000)">
<path class="st6" d="M2,4h71"/>
<g>
<g>
<circle id="path-2" class="st1" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-4" transform="translate(4.500000, 37.000000) rotate(-90.000000) translate(-4.500000, -37.000000) translate(-32.000000, 33.000000)">
<path class="st6" d="M2,4h71"/>
<g>
<g>
<circle id="path-3" class="st1" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
<g id="network" transform="translate(33.000000, 23.000000)">
<path id="Rectangle-138" class="st8" d="M2,0h362c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"
/>
<text transform="matrix(1 0 0 1 146.0513 15)" class="st0 st3 st4">overlay network</text>
</g>
<g id="arrows" transform="translate(104.000000, 42.000000)">
<g transform="translate(218.500000, 18.000000) rotate(-90.000000) translate(-218.500000, -18.000000) translate(201.000000, 14.000000)">
<path class="st9" d="M0,4h31"/>
<g>
<g>
<circle id="path-4" class="st8" cx="31" cy="4" r="4"/>
</g>
<circle class="st7" cx="31" cy="4" r="5"/>
</g>
</g>
<g transform="translate(111.500000, 18.000000) rotate(-90.000000) translate(-111.500000, -18.000000) translate(94.000000, 14.000000)">
<path class="st9" d="M0,4h31"/>
<g>
<g>
<circle id="path-5" class="st8" cx="31" cy="4" r="4"/>
</g>
<circle class="st7" cx="31" cy="4" r="5"/>
</g>
</g>
<g transform="translate(4.500000, 18.000000) rotate(-90.000000) translate(-4.500000, -18.000000) translate(-13.000000, 14.000000)">
<path class="st9" d="M0,4h31"/>
<g>
<g>
<circle id="path-6" class="st8" cx="31" cy="4" r="4"/>
</g>
<circle class="st7" cx="31" cy="4" r="5"/>
</g>
</g>
</g>
<g id="nodes" transform="translate(60.000000, 70.000000)">
<g id="node-3" transform="translate(214.000000, 0.000000)">
<g id="node">
<g id="node-label">
<path id="Rectangle-127" class="st1" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st10">worker node</text>
</g>
</g>
<g id="engine" transform="translate(1.000000, 79.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker Engine EE</text>
</g>
<g id="ucp" transform="translate(1.000000, 56.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st3 st4">UCP worker</text>
</g>
<g id="dtr" transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st3 st4">DTR</text>
</g>
<path class="st12" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-2" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st1" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st10">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st3 st4">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st3 st4">DTR</text>
</g>
<path class="st12" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1">
<g>
<g>
<path class="st1" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st10">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker Engine EE</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st11" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 20.4756 15)" class="st0 st3 st4">UCP worker</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st8" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 38.498 15)" class="st0 st3 st4">DTR</text>
</g>
<path class="st12" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<path id="group" class="st13" d="M2,0h429c1.1,0,2,0.9,2,2v212c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 250" style="enable-background:new 0 0 740 250;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#82949E;}
.st2{font-family:'OpenSans';}
.st3{font-size:12px;}
.st4{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;}
.st6{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;stroke:#FFFFFF;stroke-width:2;}
.st7{fill-rule:evenodd;clip-rule:evenodd;fill:#254356;}
.st8{fill:#E0E4E7;}
.st9{font-family:'Courier-Bold';}
.st10{font-size:13px;}
.st11{fill:#254356;}
.st12{fill-rule:evenodd;clip-rule:evenodd;fill:#E0E4E7;}
.st13{fill:none;stroke:#E0E4E7;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st14{font-family:'OpenSans-Bold';}
.st15{font-size:18px;}
.st16{font-size:14px;}
.st17{fill:none;stroke:#E0E4E7;stroke-linecap:square;}
.st18{fill:#8F9EA8;}
.st19{font-family:'MyriadPro-Regular';}
.st20{font-size:26px;}
</style>
<rect class="st0" width="740" height="250"/>
<title>cache-overview-1</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="cache-overview-1">
<g id="all" transform="translate(126.000000, 3.000000)">
<g id="right" transform="translate(288.000000, 0.000000)">
<text transform="matrix(1 0 0 1 11.025 234.0095)" class="st1 st2 st3">Asia office</text>
<path id="group" class="st4" d="M2,0h196c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g id="users" transform="translate(57.000000, 34.000000)">
<path id="user-copy-2" class="st5" d="M69,28c4.7,0,8.5-3.8,8.5-8.5c0-4.7-3.8-8.5-8.5-8.5s-8.5,3.8-8.5,8.5
C60.5,24.2,64.3,28,69,28L69,28z M69,32.2c-5.7,0-17,2.8-17,8.5V45h34v-4.2C86,35.1,74.7,32.2,69,32.2L69,32.2z"/>
<path id="user-copy" class="st5" d="M17,28c4.7,0,8.5-3.8,8.5-8.5c0-4.7-3.8-8.5-8.5-8.5s-8.5,3.8-8.5,8.5
C8.5,24.2,12.3,28,17,28L17,28z M17,32.2c-5.7,0-17,2.8-17,8.5V45h34v-4.2C34,35.1,22.7,32.2,17,32.2L17,32.2z"/>
<path id="user" class="st6" d="M43,26.5c7.3,0,13.2-5.9,13.2-13.2C56.2,5.9,50.3,0,43,0S29.8,5.9,29.8,13.2
C29.8,20.6,35.7,26.5,43,26.5L43,26.5z M43,33.1c-8.8,0-26.5,4.4-26.5,13.2V53h53v-6.6C69.5,37.5,51.8,33.1,43,33.1L43,33.1z"
/>
</g>
<g id="terminal" transform="translate(17.000000, 86.000000)">
<path id="Rectangle-2" class="st7" d="M2,0h166c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<path id="Rectangle-2-Copy" class="st5" d="M2,0h166c1.1,0,2,0.9,2,2v16c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0
z"/>
<text transform="matrix(1 0 0 1 11 38)" class="st8 st9 st10">&gt; docker pull</text>
<text transform="matrix(1 0 0 1 112.4165 38)" class="st8 st9 st10"> </text>
<text transform="matrix(1 0 0 1 11 74)" class="st8 st9 st10">dtr.example.org/</text>
<text transform="matrix(1 0 0 1 135.8203 74)" class="st8 st9 st10"> </text>
<text transform="matrix(1 0 0 1 11 92)" class="st8 st9 st10">website/ui:3-stable</text>
<text transform="matrix(1 0 0 1 51 13)" class="st11 st9 st3">localhost</text>
</g>
</g>
<g id="arrow" transform="translate(208.000000, 112.000000)">
<circle id="Oval" class="st12" cx="4" cy="10" r="4"/>
<path id="Path-3" class="st13" d="M4,10c0,0,10.6-9.5,32-9.5S68,10,68,10"/>
</g>
<g id="slow" transform="translate(229.000000, 83.000000)">
<circle id="Oval-Copy" class="st12" cx="16" cy="12" r="12"/>
<text transform="matrix(1 0 0 1 13 19)" class="st0 st14 st15">!</text>
<text transform="matrix(1 0 0 1 0 49)" class="st8 st2 st16">slow</text>
</g>
<g id="middle">
<text transform="matrix(1 0 0 1 11.025 234.0095)" class="st1 st2 st3">DTR cluster (US)</text>
<path class="st4" d="M2,0h196c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g id="website-dev" transform="translate(31.000000, 47.000000)">
<text transform="matrix(1 0 0 1 38 40)" class="st1 st2 st3">1</text>
<text transform="matrix(1 0 0 1 44.8613 40)" class="st1 st2 st3"> </text>
<text transform="matrix(1 0 0 1 38 57)" class="st1 st2 st3">2</text>
<text transform="matrix(1 0 0 1 44.8613 57)" class="st1 st2 st3"> </text>
<text transform="matrix(1 0 0 1 38 74)" class="st1 st2 st3">3-stable</text>
<path id="Line" class="st17" d="M31.5,31.5v42"/>
<text transform="matrix(1 0 0 1 31 19)" class="st1 st2 st16">website/ui</text>
<text transform="matrix(1 0 0 1 0 22)" class="st18 st19 st20"></text>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 250" style="enable-background:new 0 0 740 250;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#82949E;}
.st2{font-family:'OpenSans';}
.st3{font-size:12px;}
.st4{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:#E0E4E7;}
.st6{fill:none;stroke:#E0E4E7;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st7{fill:#E0E4E7;}
.st8{font-size:14px;}
.st9{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;}
.st10{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;stroke:#FFFFFF;stroke-width:2;}
.st11{fill:none;stroke:#82949E;stroke-width:2;}
.st12{fill:none;stroke:#E0E4E7;stroke-linecap:square;}
.st13{fill:#8F9EA8;}
.st14{font-family:'MyriadPro-Regular';}
.st15{font-size:26px;}
</style>
<rect class="st0" width="740" height="250"/>
<title>cache-overview-2</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="cache-overview-2">
<g id="all" transform="translate(16.000000, 3.000000)">
<g id="right" transform="translate(410.000000, 0.000000)">
<text transform="matrix(1 0 0 1 11.025 234.0095)" class="st1 st2 st3">Asia office</text>
<path id="group" class="st4" d="M2,0h296c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g id="Group" transform="translate(64.000000, 19.000000)">
<g id="arrow-3" transform="translate(97.000000, 52.000000)">
<circle id="Oval" class="st5" cx="4" cy="86" r="4"/>
<path id="Path-3" class="st6" d="M4,87c0,0,10.7-21.6,10.7-43S4,1,4,1"/>
<text transform="matrix(1 0 0 1 35.5 41)" class="st7 st2 st8">3. pull image</text>
<text transform="matrix(1 0 0 1 118.6318 41)" class="st7 st2 st8"> </text>
<text transform="matrix(1 0 0 1 35.5 60)" class="st7 st2 st8">layers</text>
</g>
<g id="users" transform="translate(0.000000, 128.000000)">
<path id="user-copy-2" class="st9" d="M69,28c4.7,0,8.5-3.8,8.5-8.5c0-4.7-3.8-8.5-8.5-8.5s-8.5,3.8-8.5,8.5
C60.5,24.2,64.3,28,69,28L69,28z M69,32.2c-5.7,0-17,2.8-17,8.5V45h34v-4.2C86,35.1,74.7,32.2,69,32.2L69,32.2z"/>
<path id="user-copy" class="st9" d="M17,28c4.7,0,8.5-3.8,8.5-8.5c0-4.7-3.8-8.5-8.5-8.5s-8.5,3.8-8.5,8.5
C8.5,24.2,12.3,28,17,28L17,28z M17,32.2c-5.7,0-17,2.8-17,8.5V45h34v-4.2C34,35.1,22.7,32.2,17,32.2L17,32.2z"/>
<path id="user" class="st10" d="M43,26.5c7.3,0,13.2-5.9,13.2-13.2C56.2,5.9,50.3,0,43,0S29.8,5.9,29.8,13.2
C29.8,20.6,35.7,26.5,43,26.5L43,26.5z M43,33.1c-8.8,0-26.5,4.4-26.5,13.2V53h53v-6.6C69.5,37.5,51.8,33.1,43,33.1L43,33.1z"
/>
</g>
<g id="server" transform="translate(9.000000, 0.000000)">
<text transform="matrix(1 0 0 1 3 70)" class="st1 st2 st3">cache-asia</text>
<g id="dials-3" transform="translate(3.000000, 43.000000)">
<circle id="Oval-4-Copy" class="st9" cx="11" cy="3" r="3"/>
<circle id="Oval-4" class="st9" cx="3" cy="3" r="3"/>
</g>
<path class="st11" d="M2,38h62c1.1,0,2,0.9,2,2v12c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V40C0,38.9,0.9,38,2,38z"/>
<g id="dials-2" transform="translate(3.000000, 24.000000)">
<circle class="st9" cx="11" cy="3" r="3"/>
<circle class="st9" cx="3" cy="3" r="3"/>
</g>
<path class="st11" d="M2,19h62c1.1,0,2,0.9,2,2v12c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V21C0,19.9,0.9,19,2,19z"/>
<g id="dials" transform="translate(3.000000, 5.000000)">
<circle class="st9" cx="11" cy="3" r="3"/>
<circle class="st9" cx="3" cy="3" r="3"/>
</g>
<path class="st11" d="M2,0h62c1.1,0,2,0.9,2,2v12c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
</g>
<g id="arrows" transform="translate(282.000000, 51.000000)">
<g id="arrow-1" transform="translate(16.000000, 0.000000)">
<circle class="st5" cx="67" cy="9" r="4"/>
<path class="st6" d="M4,9c0,0,10.6-8.9,32-8.9S68,9,68,9"/>
<text transform="matrix(1 0 0 1 0 34)" class="st7 st2 st8">2. redirect</text>
</g>
<g id="arrow-2" transform="translate(0.000000, 115.000000)">
<circle class="st5" cx="17" cy="4" r="4"/>
<path class="st6" d="M17,4c0,0,10.6,10.2,32,10.2S81,4,81,4"/>
<text transform="matrix(1 0 0 1 0 36)" class="st7 st2 st8">1. authenticate</text>
</g>
</g>
<g id="middle">
<text transform="matrix(1 0 0 1 10.025 234.0095)" class="st1 st2 st3">DTR cluster (US) - dtr.example.org</text>
<path class="st4" d="M2,0h256c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g id="website-dev" transform="translate(79.000000, 47.000000)">
<text transform="matrix(1 0 0 1 38 40)" class="st1 st2 st3">1</text>
<text transform="matrix(1 0 0 1 44.8613 40)" class="st1 st2 st3"> </text>
<text transform="matrix(1 0 0 1 38 57)" class="st1 st2 st3">2</text>
<text transform="matrix(1 0 0 1 44.8613 57)" class="st1 st2 st3"> </text>
<text transform="matrix(1 0 0 1 38 74)" class="st1 st2 st3">3-stable</text>
<path id="Line" class="st12" d="M31.5,31.5v42"/>
<text transform="matrix(1 0 0 1 31 19)" class="st0 st2 st8">website/ui</text>
<text transform="matrix(1 0 0 1 0 22)" class="st13 st14 st15"></text>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 250" style="enable-background:new 0 0 740 250;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{font-family:'OpenSans';}
.st2{font-size:12px;}
.st3{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
.st4{fill-rule:evenodd;clip-rule:evenodd;fill:#E0E4E7;}
.st5{fill:#82949E;}
.st6{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;stroke:#FFFFFF;stroke-width:2;}
.st7{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;}
.st8{fill:none;stroke:#E0E4E7;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st9{fill:#E0E4E7;}
.st10{font-size:14px;}
</style>
<rect class="st0" width="740" height="250"/>
<title>cache-overview-3</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="cache-overview-3">
<g id="all" transform="translate(10.000000, 3.000000)">
<g id="prod" transform="translate(540.000000, 0.000000)">
<text transform="matrix(1 0 0 1 9.025 234.0095)" class="st0 st1 st2">DTR at prod.example.org</text>
<path id="group" class="st3" d="M2,0h176c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g id="user-1" transform="translate(14.000000, 78.000000)">
<g id="widgets" transform="translate(77.000000, 15.000000)">
<path id="settings" class="st4" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2
c-1.3,0.6-2,1.1-3.1,0.7h0C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9
c0.6,1.3,1.1,2,0.7,3.1C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9
c1.3-0.6,2-1.1,3.1-0.7h0c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9
c-0.6-1.3-1.1-2-0.7-3.1C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3
c1.8,0,3.3,1.5,3.3,3.3S66.8,13.3,65,13.3L65,13.3z"/>
<path id="Shape" class="st4" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3
s1.3-3,3-3S15,8.3,15,10L15,10z"/>
<path class="st4" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<text transform="matrix(1 0 0 1 0 64)" class="st5 st1 st2">dev team</text>
<path id="user" class="st6" d="M27,25c6.9,0,12.5-5.6,12.5-12.5C39.5,5.6,33.9,0,27,0S14.5,5.6,14.5,12.5
C14.5,19.4,20.1,25,27,25L27,25z M27,31.2c-8.3,0-25,4.2-25,12.5V50h50v-6.2C52,35.4,35.3,31.2,27,31.2L27,31.2z"/>
</g>
</g>
<g id="qa" transform="translate(270.000000, 0.000000)">
<text transform="matrix(1 0 0 1 9.025 234.0095)" class="st5 st1 st2">DTR at qa.example.org</text>
<path class="st3" d="M2,0h176c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g transform="translate(14.000000, 78.000000)">
<g transform="translate(77.000000, 15.000000)">
<path class="st4" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st7" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3
s1.3-3,3-3S15,8.3,15,10L15,10z"/>
<path class="st4" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<text transform="matrix(1 0 0 1 0 64)" class="st5 st1 st2">dev team</text>
<path class="st6" d="M27,25c6.9,0,12.5-5.6,12.5-12.5C39.5,5.6,33.9,0,27,0S14.5,5.6,14.5,12.5C14.5,19.4,20.1,25,27,25L27,25z
M27,31.2c-8.3,0-25,4.2-25,12.5V50h50v-6.2C52,35.4,35.3,31.2,27,31.2L27,31.2z"/>
</g>
</g>
<g id="arrow-2" transform="translate(462.000000, 101.000000)">
<circle id="Oval" class="st4" cx="63" cy="38" r="4"/>
<path id="Path-3" class="st8" d="M0,38c0,0,10.6-8.9,32-8.9S64,38,64,38"/>
<text transform="matrix(1 0 0 1 4 15)" class="st9 st1 st10">promote</text>
</g>
<g id="dev">
<text transform="matrix(1 0 0 1 8.025 234.0095)" class="st5 st1 st2">DTR at dev.example.org</text>
<path class="st3" d="M2,0h176c1.1,0,2,0.9,2,2v241c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<g transform="translate(14.000000, 78.000000)">
<g transform="translate(77.000000, 15.000000)">
<path class="st4" d="M75,11.3V8.7C73.6,8.2,72.8,8,72.3,7v0c-0.4-1.1,0.1-1.8,0.7-3.1L71.1,2c-1.3,0.6-2,1.1-3.1,0.7h0
C67,2.2,66.8,1.4,66.3,0h-2.7C63.2,1.4,63,2.2,62,2.7h0c-1.1,0.4-1.8-0.1-3.1-0.7L57,3.9c0.6,1.3,1.1,2,0.7,3.1
C57.2,8,56.4,8.2,55,8.7v2.7c1.4,0.5,2.2,0.6,2.7,1.7c0.4,1.1-0.1,1.8-0.7,3.1l1.9,1.9c1.3-0.6,2-1.1,3.1-0.7h0
c1.1,0.4,1.2,1.3,1.7,2.7h2.7c0.5-1.4,0.6-2.2,1.7-2.7h0c1.1-0.4,1.8,0.1,3.1,0.7l1.9-1.9c-0.6-1.3-1.1-2-0.7-3.1
C72.8,12,73.6,11.8,75,11.3L75,11.3z M65,13.3c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3c1.8,0,3.3,1.5,3.3,3.3
S66.8,13.3,65,13.3L65,13.3z"/>
<path class="st7" d="M12.1,1C4.5,1,0,10,0,10s4.5,9,12.1,9c7.4,0,11.9-9,11.9-9S19.5,1,12.1,1L12.1,1z M12,16
c-3.3,0-6-2.7-6-6c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6C18,13.3,15.3,16,12,16L12,16z M15,10c0,1.7-1.3,3-3,3s-3-1.3-3-3
s1.3-3,3-3S15,8.3,15,10L15,10z"/>
<path class="st7" d="M31,15v4h4L45.6,8.4l-4-4L31,15L31,15z M35,17.7h-2.6V15h1.3v1.3H35V17.7L35,17.7z M48.6,5.4l-1.7,1.7
l-4-4l1.7-1.7C44.9,1.1,45.2,1,45.6,1c0.4,0,0.7,0.1,0.9,0.4l2.1,2.1C49.1,4,49.1,4.8,48.6,5.4L48.6,5.4z"/>
</g>
<text transform="matrix(1 0 0 1 0 64)" class="st5 st1 st2">dev team</text>
<path class="st6" d="M27,25c6.9,0,12.5-5.6,12.5-12.5C39.5,5.6,33.9,0,27,0S14.5,5.6,14.5,12.5C14.5,19.4,20.1,25,27,25L27,25z
M27,31.2c-8.3,0-25,4.2-25,12.5V50h50v-6.2C52,35.4,35.3,31.2,27,31.2L27,31.2z"/>
</g>
</g>
<g id="arrow-1" transform="translate(193.000000, 101.000000)">
<circle class="st4" cx="63" cy="38" r="4"/>
<path class="st8" d="M0,38c0,0,10.6-8.9,32-8.9S64,38,64,38"/>
<text transform="matrix(1 0 0 1 4 15)" class="st9 st1 st10">promote</text>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -0,0 +1,336 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 740 550" style="enable-background:new 0 0 740 550;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:none;stroke:#82949E;stroke-width:2;stroke-dasharray:5,5,5,5;}
.st2{fill:#82949E;}
.st3{font-family:'OpenSans';}
.st4{font-size:10px;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:#00B6B5;}
.st6{fill:none;stroke:#00B6B5;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st7{fill:none;stroke:#F7F8F9;stroke-width:2;}
.st8{fill-rule:evenodd;clip-rule:evenodd;fill:#445D6E;}
.st9{font-size:8px;}
.st10{fill-rule:evenodd;clip-rule:evenodd;fill:#1488C6;}
.st11{fill:none;stroke:#445D6E;stroke-width:2;}
.st12{fill:none;stroke:#445D6E;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st13{fill-rule:evenodd;clip-rule:evenodd;fill:#FFB463;}
.st14{fill:none;stroke:#FFB463;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st15{font-size:12px;}
.st16{fill-rule:evenodd;clip-rule:evenodd;fill:#82949E;}
.st17{fill-rule:evenodd;clip-rule:evenodd;fill:#E0E4E7;}
.st18{fill:none;stroke:#E0E4E7;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.st19{fill:#E0E4E7;}
.st20{font-size:14px;}
.st21{font-size:26px;}
.st22{font-size:100px;}
</style>
<rect class="st0" width="740" height="550"/>
<title>deploy-caches-ha-1</title>
<desc>Created with Sketch.</desc>
<g id="dtr-diagrams">
<g id="deploy-caches-ha-1">
<g id="asia" transform="translate(11.000000, 318.000000)">
<path id="group" class="st1" d="M2,42h332c1.1,0,2,0.9,2,2v180c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V44C0,42.9,0.9,42,2,42z"/>
<text transform="matrix(1 0 0 1 10.8219 218.0095)" class="st2 st3 st4">Asia datacenter</text>
<g id="storage" transform="translate(15.000000, 143.000000)">
<path id="Rectangle-138" class="st5" d="M2,31h305c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V33
C0,31.9,0.9,31,2,31z"/>
<text transform="matrix(1 0 0 1 118.5195 46)" class="st0 st3 st4">shared storage</text>
<g id="arrows" transform="translate(44.000000, 0.000000)">
<g id="arrow-copy-2" transform="translate(218.500000, 17.000000) rotate(-90.000000) translate(-218.500000, -17.000000) translate(202.000000, 13.000000)">
<path id="Line" class="st6" d="M2,4h31"/>
<g id="Oval">
<g>
<circle id="path-1" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-3" transform="translate(111.500000, 17.000000) rotate(-90.000000) translate(-111.500000, -17.000000) translate(95.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-2" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy-4" transform="translate(4.500000, 17.000000) rotate(-90.000000) translate(-4.500000, -17.000000) translate(-12.000000, 13.000000)">
<path class="st6" d="M2,4h31"/>
<g>
<g>
<circle id="path-3" class="st5" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
</g>
<g id="nodes" transform="translate(14.000000, 54.000000)">
<g id="node-1-copy-4">
<g id="node">
<g id="node-label">
<path id="Rectangle-127" class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st9">worker node</text>
</g>
</g>
<g id="engine" transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker EE Engine</text>
</g>
<g id="ucp-copy" transform="translate(1.000000, 56.000000)">
<path class="st5" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 23.7837 15)" class="st0 st3 st4">DTR cache</text>
</g>
<path id="node-border" class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy-5" transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker EE Engine</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st5" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 23.7837 15)" class="st0 st3 st4">DTR cache</text>
</g>
<path class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g id="node-1-copy-6" transform="translate(214.000000, 0.000000)">
<g>
<g>
<path class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker EE Engine</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st5" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 23.7837 15)" class="st0 st3 st4">DTR cache</text>
</g>
<path class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<g id="lb" transform="translate(15.000000, 0.000000)">
<g id="main">
<path class="st8" d="M2,0h305c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 111.438 15)" class="st0 st3 st4">your load balancer</text>
</g>
<g transform="translate(43.000000, 21.000000)">
<g transform="translate(218.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-218.500000, -17.000000) translate(202.000000, 13.000000)">
<path class="st12" d="M2,4h31"/>
<g>
<g>
<circle id="path-4" class="st8" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g id="arrow-copy" transform="translate(111.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-111.500000, -17.000000) translate(95.000000, 13.000000)">
<path class="st12" d="M2,4h31"/>
<g>
<g>
<circle id="path-5" class="st8" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(4.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-4.500000, -17.000000) translate(-12.000000, 13.000000)">
<path class="st12" d="M2,4h31"/>
<g>
<g>
<circle id="path-6" class="st8" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
</g>
</g>
<g id="us" transform="translate(202.000000, 6.000000)">
<text transform="matrix(1 0 0 1 10.8219 267.0095)" class="st2 st3 st4">US datacenter</text>
<path class="st1" d="M2,93h332c1.1,0,2,0.9,2,2v177c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V95C0,93.9,0.9,93,2,93z"/>
<g transform="translate(14.000000, 194.000000)">
<path class="st13" d="M2,31h305c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V33C0,31.9,0.9,31,2,31z"/>
<text transform="matrix(1 0 0 1 118.5195 46)" class="st0 st3 st4">shared storage</text>
<g transform="translate(44.000000, 0.000000)">
<g transform="translate(218.500000, 17.000000) rotate(-90.000000) translate(-218.500000, -17.000000) translate(202.000000, 13.000000)">
<path class="st14" d="M2,4h31"/>
<g>
<g>
<circle id="path-7" class="st13" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(111.500000, 17.000000) rotate(-90.000000) translate(-111.500000, -17.000000) translate(95.000000, 13.000000)">
<path class="st14" d="M2,4h31"/>
<g>
<g>
<circle id="path-8" class="st13" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(4.500000, 17.000000) rotate(-90.000000) translate(-4.500000, -17.000000) translate(-12.000000, 13.000000)">
<path class="st14" d="M2,4h31"/>
<g>
<g>
<circle id="path-9" class="st13" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
</g>
<g transform="translate(14.000000, 105.000000)">
<g>
<g>
<g>
<path class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker EE Engine</text>
</g>
<g id="ucp" transform="translate(1.000000, 56.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 23.7373 15)" class="st0 st3 st4">UCP agent</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st13" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 21.5986 15)" class="st0 st3 st4">DTR replica</text>
</g>
<path class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g transform="translate(107.000000, 0.000000)">
<g>
<g>
<path class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker EE Engine</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 23.7373 15)" class="st0 st3 st4">UCP agent</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st13" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 21.5986 15)" class="st0 st3 st4">DTR replica</text>
</g>
<path class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
<g transform="translate(214.000000, 0.000000)">
<g>
<g>
<path class="st8" d="M0,2c0-1.1,0.9-2,2-2h69v10.6c0,5.9-4.8,10.6-10.6,10.6H0V2z"/>
<text transform="matrix(1 0 0 1 6 14)" class="st0 st3 st9">worker node</text>
</g>
</g>
<g transform="translate(1.000000, 79.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 7.5972 15)" class="st0 st3 st4">Docker EE Engine</text>
</g>
<g transform="translate(1.000000, 56.000000)">
<path class="st10" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 23.7373 15)" class="st0 st3 st4">UCP agent</text>
</g>
<g transform="translate(1.000000, 33.000000)">
<path class="st13" d="M2,0h91c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 21.5986 15)" class="st0 st3 st4">DTR replica</text>
</g>
<path class="st11" d="M2,0h93c1.1,0,2,0.9,2,2v98c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
</g>
</g>
<g transform="translate(15.000000, 51.000000)">
<g>
<path class="st8" d="M2,0h305c1.1,0,2,0.9,2,2v18c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2C0,0.9,0.9,0,2,0z"/>
<text transform="matrix(1 0 0 1 111.438 15)" class="st0 st3 st4">your load balancer</text>
</g>
<g transform="translate(43.000000, 21.000000)">
<g transform="translate(218.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-218.500000, -17.000000) translate(202.000000, 13.000000)">
<path class="st12" d="M2,4h31"/>
<g>
<g>
<circle id="path-10" class="st8" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(111.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-111.500000, -17.000000) translate(95.000000, 13.000000)">
<path class="st12" d="M2,4h31"/>
<g>
<g>
<circle id="path-11" class="st8" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
<g transform="translate(4.500000, 17.000000) scale(1, -1) rotate(-90.000000) translate(-4.500000, -17.000000) translate(-12.000000, 13.000000)">
<path class="st12" d="M2,4h31"/>
<g>
<g>
<circle id="path-12" class="st8" cx="4" cy="4" r="4"/>
</g>
<circle class="st7" cx="4" cy="4" r="5"/>
</g>
</g>
</g>
</g>
<g id="users" transform="translate(136.000000, 0.000000)">
<g id="user">
<text transform="matrix(1 0 0 1 7 41)" class="st2 st3 st15">UI</text>
<path id="Shape" class="st16" d="M13,13c3.6,0,6.5-2.9,6.5-6.5C19.5,2.9,16.6,0,13,0S6.5,2.9,6.5,6.5C6.5,10.1,9.4,13,13,13
L13,13z M13,16.2c-4.3,0-13,2.2-13,6.5V26h26v-3.2C26,18.4,17.3,16.2,13,16.2L13,16.2z"/>
</g>
<g id="user-copy" transform="translate(42.000000, 0.000000)">
<text transform="matrix(1 0 0 1 4 41)" class="st2 st3 st15">CLI</text>
<path class="st16" d="M13,13c3.6,0,6.5-2.9,6.5-6.5C19.5,2.9,16.6,0,13,0S6.5,2.9,6.5,6.5C6.5,10.1,9.4,13,13,13L13,13z
M13,16.2c-4.3,0-13,2.2-13,6.5V26h26v-3.2C26,18.4,17.3,16.2,13,16.2L13,16.2z"/>
</g>
</g>
</g>
<g id="arrow-1" transform="translate(68.000000, 203.000000)">
<circle class="st17" cx="96" cy="4" r="4"/>
<path id="Path-3" class="st18" d="M96.1,88c0,0-6.1-21.6-6.1-43s6.1-43,6.1-43"/>
<text transform="matrix(1 0 0 1 0 41)" class="st19 st3 st20">pull from</text>
<text transform="matrix(1 0 0 1 59.8281 41)" class="st19 st3 st20"> </text>
<text transform="matrix(1 0 0 1 0 60)" class="st19 st3 st20">upstream</text>
</g>
<g id="europe" transform="translate(381.000000, 318.000000)">
<path class="st17" d="M4,0h328c2.2,0,4,1.8,4,4v218c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4C0,1.8,1.8,0,4,0z"/>
<text transform="matrix(1 0 0 1 55.3291 183)" class="st0 st3 st21">Europe datacenter</text>
<text transform="matrix(1 0 0 1 139.4111 133)" class="st0 st3 st22">+</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More