Docker-DCO-1.1-Signed-off-by: O.S. Tezer <ostezer@gmail.com> (github: ostezer)
| ... | ... |
@@ -101,7 +101,7 @@ pages: |
| 101 | 101 |
- ['reference/api/index.md', '**HIDDEN**'] |
| 102 | 102 |
- ['reference/api/docker-io_api.md', 'Reference', 'Docker Hub API'] |
| 103 | 103 |
- ['reference/api/registry_api.md', 'Reference', 'Docker Registry API'] |
| 104 |
-- ['reference/api/registry_index_spec.md', 'Reference', 'Registry & Index Spec'] |
|
| 104 |
+- ['reference/api/hub_registry_spec.md', 'Reference', 'Docker Hub and Registry Spec'] |
|
| 105 | 105 |
- ['reference/api/docker_remote_api.md', 'Reference', 'Docker Remote API'] |
| 106 | 106 |
- ['reference/api/docker_remote_api_v1.11.md', 'Reference', 'Docker Remote API v1.11'] |
| 107 | 107 |
- ['reference/api/docker_remote_api_v1.10.md', 'Reference', 'Docker Remote API v1.10'] |
| 108 | 108 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,697 @@ |
| 0 |
+page_title: Registry Documentation |
|
| 1 |
+page_description: Documentation for docker Registry and Registry API |
|
| 2 |
+page_keywords: docker, registry, api, hub |
|
| 3 |
+ |
|
| 4 |
+# The Docker Hub and the Registry spec |
|
| 5 |
+ |
|
| 6 |
+## The 3 roles |
|
| 7 |
+ |
|
| 8 |
+### Docker Hub |
|
| 9 |
+ |
|
| 10 |
+The Docker Hub is responsible for centralizing information about: |
|
| 11 |
+ |
|
| 12 |
+ - User accounts |
|
| 13 |
+ - Checksums of the images |
|
| 14 |
+ - Public namespaces |
|
| 15 |
+ |
|
| 16 |
+The Docker Hub has different components: |
|
| 17 |
+ |
|
| 18 |
+ - Web UI |
|
| 19 |
+ - Meta-data store (comments, stars, list public repositories) |
|
| 20 |
+ - Authentication service |
|
| 21 |
+ - Tokenization |
|
| 22 |
+ |
|
| 23 |
+The Docker Hub is authoritative for those information. |
|
| 24 |
+ |
|
| 25 |
+We expect that there will be only one instance of the Docker Hub, run and |
|
| 26 |
+managed by Docker Inc. |
|
| 27 |
+ |
|
| 28 |
+### Registry |
|
| 29 |
+ |
|
| 30 |
+ - It stores the images and the graph for a set of repositories |
|
| 31 |
+ - It does not have user accounts data |
|
| 32 |
+ - It has no notion of user accounts or authorization |
|
| 33 |
+ - It delegates authentication and authorization to the Docker Hub Auth |
|
| 34 |
+ service using tokens |
|
| 35 |
+ - It supports different storage backends (S3, cloud files, local FS) |
|
| 36 |
+ - It doesn't have a local database |
|
| 37 |
+ - [Source Code](https://github.com/dotcloud/docker-registry) |
|
| 38 |
+ |
|
| 39 |
+We expect that there will be multiple registries out there. To help to |
|
| 40 |
+grasp the context, here are some examples of registries: |
|
| 41 |
+ |
|
| 42 |
+ - **sponsor registry**: such a registry is provided by a third-party |
|
| 43 |
+ hosting infrastructure as a convenience for their customers and the |
|
| 44 |
+ docker community as a whole. Its costs are supported by the third |
|
| 45 |
+ party, but the management and operation of the registry are |
|
| 46 |
+ supported by dotCloud. It features read/write access, and delegates |
|
| 47 |
+ authentication and authorization to the Docker Hub. |
|
| 48 |
+ - **mirror registry**: such a registry is provided by a third-party |
|
| 49 |
+ hosting infrastructure but is targeted at their customers only. Some |
|
| 50 |
+ mechanism (unspecified to date) ensures that public images are |
|
| 51 |
+ pulled from a sponsor registry to the mirror registry, to make sure |
|
| 52 |
+ that the customers of the third-party provider can “docker pull” |
|
| 53 |
+ those images locally. |
|
| 54 |
+ - **vendor registry**: such a registry is provided by a software |
|
| 55 |
+ vendor, who wants to distribute docker images. It would be operated |
|
| 56 |
+ and managed by the vendor. Only users authorized by the vendor would |
|
| 57 |
+ be able to get write access. Some images would be public (accessible |
|
| 58 |
+ for anyone), others private (accessible only for authorized users). |
|
| 59 |
+ Authentication and authorization would be delegated to the Docker Hub. |
|
| 60 |
+ The goal of vendor registries is to let someone do “docker pull |
|
| 61 |
+ basho/riak1.3” and automatically push from the vendor registry |
|
| 62 |
+ (instead of a sponsor registry); i.e. get all the convenience of a |
|
| 63 |
+ sponsor registry, while retaining control on the asset distribution. |
|
| 64 |
+ - **private registry**: such a registry is located behind a firewall, |
|
| 65 |
+ or protected by an additional security layer (HTTP authorization, |
|
| 66 |
+ SSL client-side certificates, IP address authorization...). The |
|
| 67 |
+ registry is operated by a private entity, outside of dotCloud's |
|
| 68 |
+ control. It can optionally delegate additional authorization to the |
|
| 69 |
+ Docker Hub, but it is not mandatory. |
|
| 70 |
+ |
|
| 71 |
+> **Note:** The latter implies that while HTTP is the protocol |
|
| 72 |
+> of choice for a registry, multiple schemes are possible (and |
|
| 73 |
+> in some cases, trivial): |
|
| 74 |
+> |
|
| 75 |
+> - HTTP with GET (and PUT for read-write registries); |
|
| 76 |
+> - local mount point; |
|
| 77 |
+> - remote docker addressed through SSH. |
|
| 78 |
+ |
|
| 79 |
+The latter would only require two new commands in docker, e.g. |
|
| 80 |
+`registryget` and `registryput`, |
|
| 81 |
+wrapping access to the local filesystem (and optionally doing |
|
| 82 |
+consistency checks). Authentication and authorization are then delegated |
|
| 83 |
+to SSH (e.g. with public keys). |
|
| 84 |
+ |
|
| 85 |
+### Docker |
|
| 86 |
+ |
|
| 87 |
+On top of being a runtime for LXC, Docker is the Registry client. It |
|
| 88 |
+supports: |
|
| 89 |
+ |
|
| 90 |
+ - Push / Pull on the registry |
|
| 91 |
+ - Client authentication on the Docker Hub |
|
| 92 |
+ |
|
| 93 |
+## Workflow |
|
| 94 |
+ |
|
| 95 |
+### Pull |
|
| 96 |
+ |
|
| 97 |
+ |
|
| 98 |
+ |
|
| 99 |
+1. Contact the Docker Hub to know where I should download “samalba/busybox” |
|
| 100 |
+2. Docker Hub replies: a. `samalba/busybox` is on Registry A b. here are the |
|
| 101 |
+ checksums for `samalba/busybox` (for all layers) c. token |
|
| 102 |
+3. Contact Registry A to receive the layers for `samalba/busybox` (all of |
|
| 103 |
+ them to the base image). Registry A is authoritative for “samalba/busybox” |
|
| 104 |
+ but keeps a copy of all inherited layers and serve them all from the same |
|
| 105 |
+ location. |
|
| 106 |
+4. registry contacts Docker Hub to verify if token/user is allowed to download images |
|
| 107 |
+5. Docker Hub returns true/false lettings registry know if it should proceed or error |
|
| 108 |
+ out |
|
| 109 |
+6. Get the payload for all layers |
|
| 110 |
+ |
|
| 111 |
+It's possible to run: |
|
| 112 |
+ |
|
| 113 |
+ $ docker pull https://<registry>/repositories/samalba/busybox |
|
| 114 |
+ |
|
| 115 |
+In this case, Docker bypasses the Docker Hub. However the security is not |
|
| 116 |
+guaranteed (in case Registry A is corrupted) because there won't be any |
|
| 117 |
+checksum checks. |
|
| 118 |
+ |
|
| 119 |
+Currently registry redirects to s3 urls for downloads, going forward all |
|
| 120 |
+downloads need to be streamed through the registry. The Registry will |
|
| 121 |
+then abstract the calls to S3 by a top-level class which implements |
|
| 122 |
+sub-classes for S3 and local storage. |
|
| 123 |
+ |
|
| 124 |
+Token is only returned when the `X-Docker-Token` |
|
| 125 |
+header is sent with request. |
|
| 126 |
+ |
|
| 127 |
+Basic Auth is required to pull private repos. Basic auth isn't required |
|
| 128 |
+for pulling public repos, but if one is provided, it needs to be valid |
|
| 129 |
+and for an active account. |
|
| 130 |
+ |
|
| 131 |
+**API (pulling repository foo/bar):** |
|
| 132 |
+ |
|
| 133 |
+1. (Docker -> Docker Hub) GET /v1/repositories/foo/bar/images: |
|
| 134 |
+ |
|
| 135 |
+ **Headers**: |
|
| 136 |
+ Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
| 137 |
+ X-Docker-Token: true |
|
| 138 |
+ |
|
| 139 |
+ **Action**: |
|
| 140 |
+ (looking up the foo/bar in db and gets images and checksums |
|
| 141 |
+ for that repo (all if no tag is specified, if tag, only |
|
| 142 |
+ checksums for those tags) see part 4.4.1) |
|
| 143 |
+ |
|
| 144 |
+2. (Docker Hub -> Docker) HTTP 200 OK |
|
| 145 |
+ |
|
| 146 |
+ **Headers**: |
|
| 147 |
+ Authorization: Token |
|
| 148 |
+ signature=123abc,repository=”foo/bar”,access=write |
|
| 149 |
+ X-Docker-Endpoints: registry.docker.io [,registry2.docker.io] |
|
| 150 |
+ |
|
| 151 |
+ **Body**: |
|
| 152 |
+ Jsonified checksums (see part 4.4.1) |
|
| 153 |
+ |
|
| 154 |
+3. (Docker -> Registry) GET /v1/repositories/foo/bar/tags/latest |
|
| 155 |
+ |
|
| 156 |
+ **Headers**: |
|
| 157 |
+ Authorization: Token |
|
| 158 |
+ signature=123abc,repository=”foo/bar”,access=write |
|
| 159 |
+ |
|
| 160 |
+4. (Registry -> Docker Hub) GET /v1/repositories/foo/bar/images |
|
| 161 |
+ |
|
| 162 |
+ **Headers**: |
|
| 163 |
+ Authorization: Token |
|
| 164 |
+ signature=123abc,repository=”foo/bar”,access=read |
|
| 165 |
+ |
|
| 166 |
+ **Body**: |
|
| 167 |
+ <ids and checksums in payload> |
|
| 168 |
+ |
|
| 169 |
+ **Action**: |
|
| 170 |
+ (Lookup token see if they have access to pull.) |
|
| 171 |
+ |
|
| 172 |
+ If good: |
|
| 173 |
+ HTTP 200 OK Docker Hub will invalidate the token |
|
| 174 |
+ |
|
| 175 |
+ If bad: |
|
| 176 |
+ HTTP 401 Unauthorized |
|
| 177 |
+ |
|
| 178 |
+5. (Docker -> Registry) GET /v1/images/928374982374/ancestry |
|
| 179 |
+ |
|
| 180 |
+ **Action**: |
|
| 181 |
+ (for each image id returned in the registry, fetch /json + /layer) |
|
| 182 |
+ |
|
| 183 |
+> **Note**: |
|
| 184 |
+> If someone makes a second request, then we will always give a new token, |
|
| 185 |
+> never reuse tokens. |
|
| 186 |
+ |
|
| 187 |
+### Push |
|
| 188 |
+ |
|
| 189 |
+ |
|
| 190 |
+ |
|
| 191 |
+1. Contact the Docker Hub to allocate the repository name “samalba/busybox” |
|
| 192 |
+ (authentication required with user credentials) |
|
| 193 |
+2. If authentication works and namespace available, “samalba/busybox” |
|
| 194 |
+ is allocated and a temporary token is returned (namespace is marked |
|
| 195 |
+ as initialized in Docker Hub) |
|
| 196 |
+3. Push the image on the registry (along with the token) |
|
| 197 |
+4. Registry A contacts the Docker Hub to verify the token (token must |
|
| 198 |
+ corresponds to the repository name) |
|
| 199 |
+5. Docker Hub validates the token. Registry A starts reading the stream |
|
| 200 |
+ pushed by docker and store the repository (with its images) |
|
| 201 |
+6. docker contacts the Docker Hub to give checksums for upload images |
|
| 202 |
+ |
|
| 203 |
+> **Note:** |
|
| 204 |
+> **It's possible not to use the Docker Hub at all!** In this case, a deployed |
|
| 205 |
+> version of the Registry is deployed to store and serve images. Those |
|
| 206 |
+> images are not authenticated and the security is not guaranteed. |
|
| 207 |
+ |
|
| 208 |
+> **Note:** |
|
| 209 |
+> **Docker Hub can be replaced!** For a private Registry deployed, a custom |
|
| 210 |
+> Docker Hub can be used to serve and validate token according to different |
|
| 211 |
+> policies. |
|
| 212 |
+ |
|
| 213 |
+Docker computes the checksums and submit them to the Docker Hub at the end of |
|
| 214 |
+the push. When a repository name does not have checksums on the Docker Hub, |
|
| 215 |
+it means that the push is in progress (since checksums are submitted at |
|
| 216 |
+the end). |
|
| 217 |
+ |
|
| 218 |
+**API (pushing repos foo/bar):** |
|
| 219 |
+ |
|
| 220 |
+1. (Docker -> Docker Hub) PUT /v1/repositories/foo/bar/ |
|
| 221 |
+ |
|
| 222 |
+ **Headers**: |
|
| 223 |
+ Authorization: Basic sdkjfskdjfhsdkjfh== X-Docker-Token: |
|
| 224 |
+ true |
|
| 225 |
+ |
|
| 226 |
+ **Action**: |
|
| 227 |
+ - in Docker Hub, we allocated a new repository, and set to |
|
| 228 |
+ initialized |
|
| 229 |
+ |
|
| 230 |
+ **Body**: |
|
| 231 |
+ (The body contains the list of images that are going to be |
|
| 232 |
+ pushed, with empty checksums. The checksums will be set at |
|
| 233 |
+ the end of the push): |
|
| 234 |
+ |
|
| 235 |
+ [{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”}]
|
|
| 236 |
+ |
|
| 237 |
+2. (Docker Hub -> Docker) 200 Created |
|
| 238 |
+ |
|
| 239 |
+ **Headers**: |
|
| 240 |
+ - WWW-Authenticate: Token |
|
| 241 |
+ signature=123abc,repository=”foo/bar”,access=write |
|
| 242 |
+ - X-Docker-Endpoints: registry.docker.io [, |
|
| 243 |
+ registry2.docker.io] |
|
| 244 |
+ |
|
| 245 |
+3. (Docker -> Registry) PUT /v1/images/98765432_parent/json |
|
| 246 |
+ |
|
| 247 |
+ **Headers**: |
|
| 248 |
+ Authorization: Token |
|
| 249 |
+ signature=123abc,repository=”foo/bar”,access=write |
|
| 250 |
+ |
|
| 251 |
+4. (Registry->Docker Hub) GET /v1/repositories/foo/bar/images |
|
| 252 |
+ |
|
| 253 |
+ **Headers**: |
|
| 254 |
+ Authorization: Token |
|
| 255 |
+ signature=123abc,repository=”foo/bar”,access=write |
|
| 256 |
+ |
|
| 257 |
+ **Action**: |
|
| 258 |
+ - Docker Hub: |
|
| 259 |
+ will invalidate the token. |
|
| 260 |
+ - Registry: |
|
| 261 |
+ grants a session (if token is approved) and fetches |
|
| 262 |
+ the images id |
|
| 263 |
+ |
|
| 264 |
+5. (Docker -> Registry) PUT /v1/images/98765432_parent/json |
|
| 265 |
+ |
|
| 266 |
+ **Headers**:: |
|
| 267 |
+ - Authorization: Token |
|
| 268 |
+ signature=123abc,repository=”foo/bar”,access=write |
|
| 269 |
+ - Cookie: (Cookie provided by the Registry) |
|
| 270 |
+ |
|
| 271 |
+6. (Docker -> Registry) PUT /v1/images/98765432/json |
|
| 272 |
+ |
|
| 273 |
+ **Headers**: |
|
| 274 |
+ - Cookie: (Cookie provided by the Registry) |
|
| 275 |
+ |
|
| 276 |
+7. (Docker -> Registry) PUT /v1/images/98765432_parent/layer |
|
| 277 |
+ |
|
| 278 |
+ **Headers**: |
|
| 279 |
+ - Cookie: (Cookie provided by the Registry) |
|
| 280 |
+ |
|
| 281 |
+8. (Docker -> Registry) PUT /v1/images/98765432/layer |
|
| 282 |
+ |
|
| 283 |
+ **Headers**: |
|
| 284 |
+ X-Docker-Checksum: sha256:436745873465fdjkhdfjkgh |
|
| 285 |
+ |
|
| 286 |
+9. (Docker -> Registry) PUT /v1/repositories/foo/bar/tags/latest |
|
| 287 |
+ |
|
| 288 |
+ **Headers**: |
|
| 289 |
+ - Cookie: (Cookie provided by the Registry) |
|
| 290 |
+ |
|
| 291 |
+ **Body**: |
|
| 292 |
+ “98765432” |
|
| 293 |
+ |
|
| 294 |
+10. (Docker -> Docker Hub) PUT /v1/repositories/foo/bar/images |
|
| 295 |
+ |
|
| 296 |
+ **Headers**: |
|
| 297 |
+ Authorization: Basic 123oislifjsldfj== X-Docker-Endpoints: |
|
| 298 |
+ registry1.docker.io (no validation on this right now) |
|
| 299 |
+ |
|
| 300 |
+ **Body**: |
|
| 301 |
+ (The image, id`s, tags and checksums) |
|
| 302 |
+ [{“id”:
|
|
| 303 |
+ “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”, |
|
| 304 |
+ “checksum”: |
|
| 305 |
+ “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”}] |
|
| 306 |
+ |
|
| 307 |
+ **Return**: HTTP 204 |
|
| 308 |
+ |
|
| 309 |
+> **Note:** If push fails and they need to start again, what happens in the Docker Hub, |
|
| 310 |
+> there will already be a record for the namespace/name, but it will be |
|
| 311 |
+> initialized. Should we allow it, or mark as name already used? One edge |
|
| 312 |
+> case could be if someone pushes the same thing at the same time with two |
|
| 313 |
+> different shells. |
|
| 314 |
+ |
|
| 315 |
+If it's a retry on the Registry, Docker has a cookie (provided by the |
|
| 316 |
+registry after token validation). So the Docker Hub won't have to provide a |
|
| 317 |
+new token. |
|
| 318 |
+ |
|
| 319 |
+### Delete |
|
| 320 |
+ |
|
| 321 |
+If you need to delete something from the Docker Hub or registry, we need a |
|
| 322 |
+nice clean way to do that. Here is the workflow. |
|
| 323 |
+ |
|
| 324 |
+1. Docker contacts the Docker Hub to request a delete of a repository |
|
| 325 |
+ `samalba/busybox` (authentication required with user credentials) |
|
| 326 |
+2. If authentication works and repository is valid, `samalba/busybox` |
|
| 327 |
+ is marked as deleted and a temporary token is returned |
|
| 328 |
+3. Send a delete request to the registry for the repository (along with |
|
| 329 |
+ the token) |
|
| 330 |
+4. Registry A contacts the Docker Hub to verify the token (token must |
|
| 331 |
+ corresponds to the repository name) |
|
| 332 |
+5. Docker Hub validates the token. Registry A deletes the repository and |
|
| 333 |
+ everything associated to it. |
|
| 334 |
+6. docker contacts the Docker Hub to let it know it was removed from the |
|
| 335 |
+ registry, the Docker Hub removes all records from the database. |
|
| 336 |
+ |
|
| 337 |
+> **Note**: |
|
| 338 |
+> The Docker client should present an "Are you sure?" prompt to confirm |
|
| 339 |
+> the deletion before starting the process. Once it starts it can't be |
|
| 340 |
+> undone. |
|
| 341 |
+ |
|
| 342 |
+**API (deleting repository foo/bar):** |
|
| 343 |
+ |
|
| 344 |
+1. (Docker -> Docker Hub) DELETE /v1/repositories/foo/bar/ |
|
| 345 |
+ |
|
| 346 |
+ **Headers**: |
|
| 347 |
+ Authorization: Basic sdkjfskdjfhsdkjfh== X-Docker-Token: |
|
| 348 |
+ true |
|
| 349 |
+ |
|
| 350 |
+ **Action**: |
|
| 351 |
+ - in Docker Hub, we make sure it is a valid repository, and set |
|
| 352 |
+ to deleted (logically) |
|
| 353 |
+ |
|
| 354 |
+ **Body**: |
|
| 355 |
+ Empty |
|
| 356 |
+ |
|
| 357 |
+2. (Docker Hub -> Docker) 202 Accepted |
|
| 358 |
+ |
|
| 359 |
+ **Headers**: |
|
| 360 |
+ - WWW-Authenticate: Token |
|
| 361 |
+ signature=123abc,repository=”foo/bar”,access=delete |
|
| 362 |
+ - X-Docker-Endpoints: registry.docker.io [, |
|
| 363 |
+ registry2.docker.io] |
|
| 364 |
+ # list of endpoints where this repo lives. |
|
| 365 |
+ |
|
| 366 |
+3. (Docker -> Registry) DELETE /v1/repositories/foo/bar/ |
|
| 367 |
+ |
|
| 368 |
+ **Headers**: |
|
| 369 |
+ Authorization: Token |
|
| 370 |
+ signature=123abc,repository=”foo/bar”,access=delete |
|
| 371 |
+ |
|
| 372 |
+4. (Registry->Docker Hub) PUT /v1/repositories/foo/bar/auth |
|
| 373 |
+ |
|
| 374 |
+ **Headers**: |
|
| 375 |
+ Authorization: Token |
|
| 376 |
+ signature=123abc,repository=”foo/bar”,access=delete |
|
| 377 |
+ |
|
| 378 |
+ **Action**: |
|
| 379 |
+ - Docker Hub: |
|
| 380 |
+ will invalidate the token. |
|
| 381 |
+ - Registry: |
|
| 382 |
+ deletes the repository (if token is approved) |
|
| 383 |
+ |
|
| 384 |
+5. (Registry -> Docker) 200 OK |
|
| 385 |
+ |
|
| 386 |
+ 200 If success 403 if forbidden 400 if bad request 404 |
|
| 387 |
+ if repository isn't found |
|
| 388 |
+ |
|
| 389 |
+6. (Docker -> Docker Hub) DELETE /v1/repositories/foo/bar/ |
|
| 390 |
+ |
|
| 391 |
+ **Headers**: |
|
| 392 |
+ Authorization: Basic 123oislifjsldfj== X-Docker-Endpoints: |
|
| 393 |
+ registry-1.docker.io (no validation on this right now) |
|
| 394 |
+ |
|
| 395 |
+ **Body**: |
|
| 396 |
+ Empty |
|
| 397 |
+ |
|
| 398 |
+ **Return**: HTTP 200 |
|
| 399 |
+ |
|
| 400 |
+## How to use the Registry in standalone mode |
|
| 401 |
+ |
|
| 402 |
+The Docker Hub has two main purposes (along with its fancy social features): |
|
| 403 |
+ |
|
| 404 |
+ - Resolve short names (to avoid passing absolute URLs all the time): |
|
| 405 |
+ |
|
| 406 |
+ username/projectname -> |
|
| 407 |
+ https://registry.docker.io/users/<username>/repositories/<projectname>/ |
|
| 408 |
+ team/projectname -> |
|
| 409 |
+ https://registry.docker.io/team/<team>/repositories/<projectname>/ |
|
| 410 |
+ |
|
| 411 |
+ - Authenticate a user as a repos owner (for a central referenced |
|
| 412 |
+ repository) |
|
| 413 |
+ |
|
| 414 |
+### Without an Docker Hub |
|
| 415 |
+ |
|
| 416 |
+Using the Registry without the Docker Hub can be useful to store the images |
|
| 417 |
+on a private network without having to rely on an external entity |
|
| 418 |
+controlled by Docker Inc. |
|
| 419 |
+ |
|
| 420 |
+In this case, the registry will be launched in a special mode |
|
| 421 |
+(–standalone? ne? –no-index?). In this mode, the only thing which changes is |
|
| 422 |
+that Registry will never contact the Docker Hub to verify a token. It will be |
|
| 423 |
+the Registry owner responsibility to authenticate the user who pushes |
|
| 424 |
+(or even pulls) an image using any mechanism (HTTP auth, IP based, |
|
| 425 |
+etc...). |
|
| 426 |
+ |
|
| 427 |
+In this scenario, the Registry is responsible for the security in case |
|
| 428 |
+of data corruption since the checksums are not delivered by a trusted |
|
| 429 |
+entity. |
|
| 430 |
+ |
|
| 431 |
+As hinted previously, a standalone registry can also be implemented by |
|
| 432 |
+any HTTP server handling GET/PUT requests (or even only GET requests if |
|
| 433 |
+no write access is necessary). |
|
| 434 |
+ |
|
| 435 |
+### With an Docker Hub |
|
| 436 |
+ |
|
| 437 |
+The Docker Hub data needed by the Registry are simple: |
|
| 438 |
+ |
|
| 439 |
+ - Serve the checksums |
|
| 440 |
+ - Provide and authorize a Token |
|
| 441 |
+ |
|
| 442 |
+In the scenario of a Registry running on a private network with the need |
|
| 443 |
+of centralizing and authorizing, it's easy to use a custom Docker Hub. |
|
| 444 |
+ |
|
| 445 |
+The only challenge will be to tell Docker to contact (and trust) this |
|
| 446 |
+custom Docker Hub. Docker will be configurable at some point to use a |
|
| 447 |
+specific Docker Hub, it'll be the private entity responsibility (basically |
|
| 448 |
+the organization who uses Docker in a private environment) to maintain |
|
| 449 |
+the Docker Hub and the Docker's configuration among its consumers. |
|
| 450 |
+ |
|
| 451 |
+## The API |
|
| 452 |
+ |
|
| 453 |
+The first version of the api is available here: |
|
| 454 |
+[https://github.com/jpetazzo/docker/blob/acd51ecea8f5d3c02b00a08176171c59442df8b3/docs/images-repositories-push-pull.md](https://github.com/jpetazzo/docker/blob/acd51ecea8f5d3c02b00a08176171c59442df8b3/docs/images-repositories-push-pull.md) |
|
| 455 |
+ |
|
| 456 |
+### Images |
|
| 457 |
+ |
|
| 458 |
+The format returned in the images is not defined here (for layer and |
|
| 459 |
+JSON), basically because Registry stores exactly the same kind of |
|
| 460 |
+information as Docker uses to manage them. |
|
| 461 |
+ |
|
| 462 |
+The format of ancestry is a line-separated list of image ids, in age |
|
| 463 |
+order, i.e. the image's parent is on the last line, the parent of the |
|
| 464 |
+parent on the next-to-last line, etc.; if the image has no parent, the |
|
| 465 |
+file is empty. |
|
| 466 |
+ |
|
| 467 |
+ GET /v1/images/<image_id>/layer |
|
| 468 |
+ PUT /v1/images/<image_id>/layer |
|
| 469 |
+ GET /v1/images/<image_id>/json |
|
| 470 |
+ PUT /v1/images/<image_id>/json |
|
| 471 |
+ GET /v1/images/<image_id>/ancestry |
|
| 472 |
+ PUT /v1/images/<image_id>/ancestry |
|
| 473 |
+ |
|
| 474 |
+### Users |
|
| 475 |
+ |
|
| 476 |
+### Create a user (Docker Hub) |
|
| 477 |
+ |
|
| 478 |
+ POST /v1/users: |
|
| 479 |
+ |
|
| 480 |
+ **Body**: |
|
| 481 |
+ {"email": "[sam@dotcloud.com](mailto:sam%40dotcloud.com)",
|
|
| 482 |
+ "password": "toto42", "username": "foobar"`} |
|
| 483 |
+ |
|
| 484 |
+ **Validation**: |
|
| 485 |
+ - **username**: min 4 character, max 30 characters, must match the |
|
| 486 |
+ regular expression [a-z0-9_]. |
|
| 487 |
+ - **password**: min 5 characters |
|
| 488 |
+ |
|
| 489 |
+ **Valid**: return HTTP 200 |
|
| 490 |
+ |
|
| 491 |
+Errors: HTTP 400 (we should create error codes for possible errors) - |
|
| 492 |
+invalid json - missing field - wrong format (username, password, email, |
|
| 493 |
+etc) - forbidden name - name already exists |
|
| 494 |
+ |
|
| 495 |
+> **Note**: |
|
| 496 |
+> A user account will be valid only if the email has been validated (a |
|
| 497 |
+> validation link is sent to the email address). |
|
| 498 |
+ |
|
| 499 |
+### Update a user (Docker Hub) |
|
| 500 |
+ |
|
| 501 |
+ PUT /v1/users/<username> |
|
| 502 |
+ |
|
| 503 |
+ **Body**: |
|
| 504 |
+ {"password": "toto"}
|
|
| 505 |
+ |
|
| 506 |
+> **Note**: |
|
| 507 |
+> We can also update email address, if they do, they will need to reverify |
|
| 508 |
+> their new email address. |
|
| 509 |
+ |
|
| 510 |
+### Login (Docker Hub) |
|
| 511 |
+ |
|
| 512 |
+Does nothing else but asking for a user authentication. Can be used to |
|
| 513 |
+validate credentials. HTTP Basic Auth for now, maybe change in future. |
|
| 514 |
+ |
|
| 515 |
+GET /v1/users |
|
| 516 |
+ |
|
| 517 |
+ **Return**: |
|
| 518 |
+ - Valid: HTTP 200 |
|
| 519 |
+ - Invalid login: HTTP 401 |
|
| 520 |
+ - Account inactive: HTTP 403 Account is not Active |
|
| 521 |
+ |
|
| 522 |
+### Tags (Registry) |
|
| 523 |
+ |
|
| 524 |
+The Registry does not know anything about users. Even though |
|
| 525 |
+repositories are under usernames, it's just a namespace for the |
|
| 526 |
+registry. Allowing us to implement organizations or different namespaces |
|
| 527 |
+per user later, without modifying the Registry'sAPI. |
|
| 528 |
+ |
|
| 529 |
+The following naming restrictions apply: |
|
| 530 |
+ |
|
| 531 |
+ - Namespaces must match the same regular expression as usernames (See |
|
| 532 |
+ 4.2.1.) |
|
| 533 |
+ - Repository names must match the regular expression [a-zA-Z0-9-_.] |
|
| 534 |
+ |
|
| 535 |
+### Get all tags: |
|
| 536 |
+ |
|
| 537 |
+GET /v1/repositories/<namespace>/<repository_name>/tags |
|
| 538 |
+ |
|
| 539 |
+ **Return**: HTTP 200 |
|
| 540 |
+ { "latest":
|
|
| 541 |
+ "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f", |
|
| 542 |
+ “0.1.1”: |
|
| 543 |
+ “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087” } |
|
| 544 |
+ |
|
| 545 |
+ **4.3.2 Read the content of a tag (resolve the image id):** |
|
| 546 |
+ |
|
| 547 |
+ GET /v1/repositories/<namespace>/<repo_name>/tags/<tag> |
|
| 548 |
+ |
|
| 549 |
+ **Return**: |
|
| 550 |
+ "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f" |
|
| 551 |
+ |
|
| 552 |
+ **4.3.3 Delete a tag (registry):** |
|
| 553 |
+ |
|
| 554 |
+ DELETE /v1/repositories/<namespace>/<repo_name>/tags/<tag> |
|
| 555 |
+ |
|
| 556 |
+### 4.4 Images (Docker Hub) |
|
| 557 |
+ |
|
| 558 |
+For the Docker Hub to “resolve” the repository name to a Registry location, |
|
| 559 |
+it uses the X-Docker-Endpoints header. In other terms, this requests |
|
| 560 |
+always add a `X-Docker-Endpoints` to indicate the |
|
| 561 |
+location of the registry which hosts this repository. |
|
| 562 |
+ |
|
| 563 |
+**4.4.1 Get the images:** |
|
| 564 |
+ |
|
| 565 |
+ GET /v1/repositories/<namespace>/<repo_name>/images |
|
| 566 |
+ |
|
| 567 |
+ **Return**: HTTP 200 |
|
| 568 |
+ [{“id”:
|
|
| 569 |
+ “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”, |
|
| 570 |
+ “checksum”: |
|
| 571 |
+ “[md5:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087](md5:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087)”}] |
|
| 572 |
+ |
|
| 573 |
+### Add/update the images: |
|
| 574 |
+ |
|
| 575 |
+You always add images, you never remove them. |
|
| 576 |
+ |
|
| 577 |
+ PUT /v1/repositories/<namespace>/<repo_name>/images |
|
| 578 |
+ |
|
| 579 |
+ **Body**: |
|
| 580 |
+ [ {“id”:
|
|
| 581 |
+ “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”, |
|
| 582 |
+ “checksum”: |
|
| 583 |
+ “sha256:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”} |
|
| 584 |
+ ] |
|
| 585 |
+ |
|
| 586 |
+ **Return**: 204 |
|
| 587 |
+ |
|
| 588 |
+### Repositories |
|
| 589 |
+ |
|
| 590 |
+### Remove a Repository (Registry) |
|
| 591 |
+ |
|
| 592 |
+DELETE /v1/repositories/<namespace>/<repo_name> |
|
| 593 |
+ |
|
| 594 |
+Return 200 OK |
|
| 595 |
+ |
|
| 596 |
+### Remove a Repository (Docker Hub) |
|
| 597 |
+ |
|
| 598 |
+This starts the delete process. see 2.3 for more details. |
|
| 599 |
+ |
|
| 600 |
+DELETE /v1/repositories/<namespace>/<repo_name> |
|
| 601 |
+ |
|
| 602 |
+Return 202 OK |
|
| 603 |
+ |
|
| 604 |
+## Chaining Registries |
|
| 605 |
+ |
|
| 606 |
+It's possible to chain Registries server for several reasons: |
|
| 607 |
+ |
|
| 608 |
+ - Load balancing |
|
| 609 |
+ - Delegate the next request to another server |
|
| 610 |
+ |
|
| 611 |
+When a Registry is a reference for a repository, it should host the |
|
| 612 |
+entire images chain in order to avoid breaking the chain during the |
|
| 613 |
+download. |
|
| 614 |
+ |
|
| 615 |
+The Docker Hub and Registry use this mechanism to redirect on one or the |
|
| 616 |
+other. |
|
| 617 |
+ |
|
| 618 |
+Example with an image download: |
|
| 619 |
+ |
|
| 620 |
+On every request, a special header can be returned: |
|
| 621 |
+ |
|
| 622 |
+ X-Docker-Endpoints: server1,server2 |
|
| 623 |
+ |
|
| 624 |
+On the next request, the client will always pick a server from this |
|
| 625 |
+list. |
|
| 626 |
+ |
|
| 627 |
+## Authentication & Authorization |
|
| 628 |
+ |
|
| 629 |
+### On the Docker Hub |
|
| 630 |
+ |
|
| 631 |
+The Docker Hub supports both “Basic” and “Token” challenges. Usually when |
|
| 632 |
+there is a `401 Unauthorized`, the Docker Hub replies |
|
| 633 |
+this: |
|
| 634 |
+ |
|
| 635 |
+ 401 Unauthorized |
|
| 636 |
+ WWW-Authenticate: Basic realm="auth required",Token |
|
| 637 |
+ |
|
| 638 |
+You have 3 options: |
|
| 639 |
+ |
|
| 640 |
+1. Provide user credentials and ask for a token |
|
| 641 |
+ |
|
| 642 |
+ **Header**: |
|
| 643 |
+ - Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
| 644 |
+ - X-Docker-Token: true |
|
| 645 |
+ |
|
| 646 |
+ In this case, along with the 200 response, you'll get a new token |
|
| 647 |
+ (if user auth is ok): If authorization isn't correct you get a 401 |
|
| 648 |
+ response. If account isn't active you will get a 403 response. |
|
| 649 |
+ |
|
| 650 |
+ **Response**: |
|
| 651 |
+ - 200 OK |
|
| 652 |
+ - X-Docker-Token: Token |
|
| 653 |
+ signature=123abc,repository=”foo/bar”,access=read |
|
| 654 |
+ |
|
| 655 |
+ |
|
| 656 |
+2. Provide user credentials only |
|
| 657 |
+ |
|
| 658 |
+ **Header**: |
|
| 659 |
+ Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
| 660 |
+ |
|
| 661 |
+3. Provide Token |
|
| 662 |
+ |
|
| 663 |
+ **Header**: |
|
| 664 |
+ Authorization: Token |
|
| 665 |
+ signature=123abc,repository=”foo/bar”,access=read |
|
| 666 |
+ |
|
| 667 |
+### 6.2 On the Registry |
|
| 668 |
+ |
|
| 669 |
+The Registry only supports the Token challenge: |
|
| 670 |
+ |
|
| 671 |
+ 401 Unauthorized |
|
| 672 |
+ WWW-Authenticate: Token |
|
| 673 |
+ |
|
| 674 |
+The only way is to provide a token on `401 Unauthorized` |
|
| 675 |
+responses: |
|
| 676 |
+ |
|
| 677 |
+ Authorization: Token signature=123abc,repository="foo/bar",access=read |
|
| 678 |
+ |
|
| 679 |
+Usually, the Registry provides a Cookie when a Token verification |
|
| 680 |
+succeeded. Every time the Registry passes a Cookie, you have to pass it |
|
| 681 |
+back the same cookie.: |
|
| 682 |
+ |
|
| 683 |
+ 200 OK |
|
| 684 |
+ Set-Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4="; Path=/; HttpOnly |
|
| 685 |
+ |
|
| 686 |
+Next request: |
|
| 687 |
+ |
|
| 688 |
+ GET /(...) |
|
| 689 |
+ Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4=" |
|
| 690 |
+ |
|
| 691 |
+## Document Version |
|
| 692 |
+ |
|
| 693 |
+ - 1.0 : May 6th 2013 : initial release |
|
| 694 |
+ - 1.1 : June 1st 2013 : Added Delete Repository and way to handle new |
|
| 695 |
+ source namespace. |
|
| 696 |
+ |
| 0 | 697 |
deleted file mode 100644 |
| ... | ... |
@@ -1,697 +0,0 @@ |
| 1 |
-page_title: Registry Documentation |
|
| 2 |
-page_description: Documentation for docker Registry and Registry API |
|
| 3 |
-page_keywords: docker, registry, api, index |
|
| 4 |
- |
|
| 5 |
-# Registry & Index Spec |
|
| 6 |
- |
|
| 7 |
-## The 3 roles |
|
| 8 |
- |
|
| 9 |
-### Index |
|
| 10 |
- |
|
| 11 |
-The Index is responsible for centralizing information about: |
|
| 12 |
- |
|
| 13 |
- - User accounts |
|
| 14 |
- - Checksums of the images |
|
| 15 |
- - Public namespaces |
|
| 16 |
- |
|
| 17 |
-The Index has different components: |
|
| 18 |
- |
|
| 19 |
- - Web UI |
|
| 20 |
- - Meta-data store (comments, stars, list public repositories) |
|
| 21 |
- - Authentication service |
|
| 22 |
- - Tokenization |
|
| 23 |
- |
|
| 24 |
-The index is authoritative for those information. |
|
| 25 |
- |
|
| 26 |
-We expect that there will be only one instance of the index, run and |
|
| 27 |
-managed by Docker Inc. |
|
| 28 |
- |
|
| 29 |
-### Registry |
|
| 30 |
- |
|
| 31 |
- - It stores the images and the graph for a set of repositories |
|
| 32 |
- - It does not have user accounts data |
|
| 33 |
- - It has no notion of user accounts or authorization |
|
| 34 |
- - It delegates authentication and authorization to the Index Auth |
|
| 35 |
- service using tokens |
|
| 36 |
- - It supports different storage backends (S3, cloud files, local FS) |
|
| 37 |
- - It doesn't have a local database |
|
| 38 |
- - [Source Code](https://github.com/dotcloud/docker-registry) |
|
| 39 |
- |
|
| 40 |
-We expect that there will be multiple registries out there. To help to |
|
| 41 |
-grasp the context, here are some examples of registries: |
|
| 42 |
- |
|
| 43 |
- - **sponsor registry**: such a registry is provided by a third-party |
|
| 44 |
- hosting infrastructure as a convenience for their customers and the |
|
| 45 |
- docker community as a whole. Its costs are supported by the third |
|
| 46 |
- party, but the management and operation of the registry are |
|
| 47 |
- supported by dotCloud. It features read/write access, and delegates |
|
| 48 |
- authentication and authorization to the Index. |
|
| 49 |
- - **mirror registry**: such a registry is provided by a third-party |
|
| 50 |
- hosting infrastructure but is targeted at their customers only. Some |
|
| 51 |
- mechanism (unspecified to date) ensures that public images are |
|
| 52 |
- pulled from a sponsor registry to the mirror registry, to make sure |
|
| 53 |
- that the customers of the third-party provider can “docker pull” |
|
| 54 |
- those images locally. |
|
| 55 |
- - **vendor registry**: such a registry is provided by a software |
|
| 56 |
- vendor, who wants to distribute docker images. It would be operated |
|
| 57 |
- and managed by the vendor. Only users authorized by the vendor would |
|
| 58 |
- be able to get write access. Some images would be public (accessible |
|
| 59 |
- for anyone), others private (accessible only for authorized users). |
|
| 60 |
- Authentication and authorization would be delegated to the Index. |
|
| 61 |
- The goal of vendor registries is to let someone do “docker pull |
|
| 62 |
- basho/riak1.3” and automatically push from the vendor registry |
|
| 63 |
- (instead of a sponsor registry); i.e. get all the convenience of a |
|
| 64 |
- sponsor registry, while retaining control on the asset distribution. |
|
| 65 |
- - **private registry**: such a registry is located behind a firewall, |
|
| 66 |
- or protected by an additional security layer (HTTP authorization, |
|
| 67 |
- SSL client-side certificates, IP address authorization...). The |
|
| 68 |
- registry is operated by a private entity, outside of dotCloud's |
|
| 69 |
- control. It can optionally delegate additional authorization to the |
|
| 70 |
- Index, but it is not mandatory. |
|
| 71 |
- |
|
| 72 |
-> **Note:** The latter implies that while HTTP is the protocol |
|
| 73 |
-> of choice for a registry, multiple schemes are possible (and |
|
| 74 |
-> in some cases, trivial): |
|
| 75 |
-> |
|
| 76 |
-> - HTTP with GET (and PUT for read-write registries); |
|
| 77 |
-> - local mount point; |
|
| 78 |
-> - remote docker addressed through SSH. |
|
| 79 |
- |
|
| 80 |
-The latter would only require two new commands in docker, e.g. |
|
| 81 |
-`registryget` and `registryput`, |
|
| 82 |
-wrapping access to the local filesystem (and optionally doing |
|
| 83 |
-consistency checks). Authentication and authorization are then delegated |
|
| 84 |
-to SSH (e.g. with public keys). |
|
| 85 |
- |
|
| 86 |
-### Docker |
|
| 87 |
- |
|
| 88 |
-On top of being a runtime for LXC, Docker is the Registry client. It |
|
| 89 |
-supports: |
|
| 90 |
- |
|
| 91 |
- - Push / Pull on the registry |
|
| 92 |
- - Client authentication on the Index |
|
| 93 |
- |
|
| 94 |
-## Workflow |
|
| 95 |
- |
|
| 96 |
-### Pull |
|
| 97 |
- |
|
| 98 |
- |
|
| 99 |
- |
|
| 100 |
-1. Contact the Index to know where I should download “samalba/busybox” |
|
| 101 |
-2. Index replies: a. `samalba/busybox` is on Registry A b. here are the |
|
| 102 |
- checksums for `samalba/busybox` (for all layers) c. token |
|
| 103 |
-3. Contact Registry A to receive the layers for `samalba/busybox` (all of |
|
| 104 |
- them to the base image). Registry A is authoritative for “samalba/busybox” |
|
| 105 |
- but keeps a copy of all inherited layers and serve them all from the same |
|
| 106 |
- location. |
|
| 107 |
-4. registry contacts index to verify if token/user is allowed to download images |
|
| 108 |
-5. Index returns true/false lettings registry know if it should proceed or error |
|
| 109 |
- out |
|
| 110 |
-6. Get the payload for all layers |
|
| 111 |
- |
|
| 112 |
-It's possible to run: |
|
| 113 |
- |
|
| 114 |
- $ docker pull https://<registry>/repositories/samalba/busybox |
|
| 115 |
- |
|
| 116 |
-In this case, Docker bypasses the Index. However the security is not |
|
| 117 |
-guaranteed (in case Registry A is corrupted) because there won't be any |
|
| 118 |
-checksum checks. |
|
| 119 |
- |
|
| 120 |
-Currently registry redirects to s3 urls for downloads, going forward all |
|
| 121 |
-downloads need to be streamed through the registry. The Registry will |
|
| 122 |
-then abstract the calls to S3 by a top-level class which implements |
|
| 123 |
-sub-classes for S3 and local storage. |
|
| 124 |
- |
|
| 125 |
-Token is only returned when the `X-Docker-Token` |
|
| 126 |
-header is sent with request. |
|
| 127 |
- |
|
| 128 |
-Basic Auth is required to pull private repos. Basic auth isn't required |
|
| 129 |
-for pulling public repos, but if one is provided, it needs to be valid |
|
| 130 |
-and for an active account. |
|
| 131 |
- |
|
| 132 |
-**API (pulling repository foo/bar):** |
|
| 133 |
- |
|
| 134 |
-1. (Docker -> Index) GET /v1/repositories/foo/bar/images: |
|
| 135 |
- |
|
| 136 |
- **Headers**: |
|
| 137 |
- Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
| 138 |
- X-Docker-Token: true |
|
| 139 |
- |
|
| 140 |
- **Action**: |
|
| 141 |
- (looking up the foo/bar in db and gets images and checksums |
|
| 142 |
- for that repo (all if no tag is specified, if tag, only |
|
| 143 |
- checksums for those tags) see part 4.4.1) |
|
| 144 |
- |
|
| 145 |
-2. (Index -> Docker) HTTP 200 OK |
|
| 146 |
- |
|
| 147 |
- **Headers**: |
|
| 148 |
- Authorization: Token |
|
| 149 |
- signature=123abc,repository=”foo/bar”,access=write |
|
| 150 |
- X-Docker-Endpoints: registry.docker.io [,registry2.docker.io] |
|
| 151 |
- |
|
| 152 |
- **Body**: |
|
| 153 |
- Jsonified checksums (see part 4.4.1) |
|
| 154 |
- |
|
| 155 |
-3. (Docker -> Registry) GET /v1/repositories/foo/bar/tags/latest |
|
| 156 |
- |
|
| 157 |
- **Headers**: |
|
| 158 |
- Authorization: Token |
|
| 159 |
- signature=123abc,repository=”foo/bar”,access=write |
|
| 160 |
- |
|
| 161 |
-4. (Registry -> Index) GET /v1/repositories/foo/bar/images |
|
| 162 |
- |
|
| 163 |
- **Headers**: |
|
| 164 |
- Authorization: Token |
|
| 165 |
- signature=123abc,repository=”foo/bar”,access=read |
|
| 166 |
- |
|
| 167 |
- **Body**: |
|
| 168 |
- <ids and checksums in payload> |
|
| 169 |
- |
|
| 170 |
- **Action**: |
|
| 171 |
- (Lookup token see if they have access to pull.) |
|
| 172 |
- |
|
| 173 |
- If good: |
|
| 174 |
- HTTP 200 OK Index will invalidate the token |
|
| 175 |
- |
|
| 176 |
- If bad: |
|
| 177 |
- HTTP 401 Unauthorized |
|
| 178 |
- |
|
| 179 |
-5. (Docker -> Registry) GET /v1/images/928374982374/ancestry |
|
| 180 |
- |
|
| 181 |
- **Action**: |
|
| 182 |
- (for each image id returned in the registry, fetch /json + /layer) |
|
| 183 |
- |
|
| 184 |
-> **Note**: |
|
| 185 |
-> If someone makes a second request, then we will always give a new token, |
|
| 186 |
-> never reuse tokens. |
|
| 187 |
- |
|
| 188 |
-### Push |
|
| 189 |
- |
|
| 190 |
- |
|
| 191 |
- |
|
| 192 |
-1. Contact the index to allocate the repository name “samalba/busybox” |
|
| 193 |
- (authentication required with user credentials) |
|
| 194 |
-2. If authentication works and namespace available, “samalba/busybox” |
|
| 195 |
- is allocated and a temporary token is returned (namespace is marked |
|
| 196 |
- as initialized in index) |
|
| 197 |
-3. Push the image on the registry (along with the token) |
|
| 198 |
-4. Registry A contacts the Index to verify the token (token must |
|
| 199 |
- corresponds to the repository name) |
|
| 200 |
-5. Index validates the token. Registry A starts reading the stream |
|
| 201 |
- pushed by docker and store the repository (with its images) |
|
| 202 |
-6. docker contacts the index to give checksums for upload images |
|
| 203 |
- |
|
| 204 |
-> **Note:** |
|
| 205 |
-> **It's possible not to use the Index at all!** In this case, a deployed |
|
| 206 |
-> version of the Registry is deployed to store and serve images. Those |
|
| 207 |
-> images are not authenticated and the security is not guaranteed. |
|
| 208 |
- |
|
| 209 |
-> **Note:** |
|
| 210 |
-> **Index can be replaced!** For a private Registry deployed, a custom |
|
| 211 |
-> Index can be used to serve and validate token according to different |
|
| 212 |
-> policies. |
|
| 213 |
- |
|
| 214 |
-Docker computes the checksums and submit them to the Index at the end of |
|
| 215 |
-the push. When a repository name does not have checksums on the Index, |
|
| 216 |
-it means that the push is in progress (since checksums are submitted at |
|
| 217 |
-the end). |
|
| 218 |
- |
|
| 219 |
-**API (pushing repos foo/bar):** |
|
| 220 |
- |
|
| 221 |
-1. (Docker -> Index) PUT /v1/repositories/foo/bar/ |
|
| 222 |
- |
|
| 223 |
- **Headers**: |
|
| 224 |
- Authorization: Basic sdkjfskdjfhsdkjfh== X-Docker-Token: |
|
| 225 |
- true |
|
| 226 |
- |
|
| 227 |
- **Action**: |
|
| 228 |
- - in index, we allocated a new repository, and set to |
|
| 229 |
- initialized |
|
| 230 |
- |
|
| 231 |
- **Body**: |
|
| 232 |
- (The body contains the list of images that are going to be |
|
| 233 |
- pushed, with empty checksums. The checksums will be set at |
|
| 234 |
- the end of the push): |
|
| 235 |
- |
|
| 236 |
- [{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”}]
|
|
| 237 |
- |
|
| 238 |
-2. (Index -> Docker) 200 Created |
|
| 239 |
- |
|
| 240 |
- **Headers**: |
|
| 241 |
- - WWW-Authenticate: Token |
|
| 242 |
- signature=123abc,repository=”foo/bar”,access=write |
|
| 243 |
- - X-Docker-Endpoints: registry.docker.io [, |
|
| 244 |
- registry2.docker.io] |
|
| 245 |
- |
|
| 246 |
-3. (Docker -> Registry) PUT /v1/images/98765432_parent/json |
|
| 247 |
- |
|
| 248 |
- **Headers**: |
|
| 249 |
- Authorization: Token |
|
| 250 |
- signature=123abc,repository=”foo/bar”,access=write |
|
| 251 |
- |
|
| 252 |
-4. (Registry->Index) GET /v1/repositories/foo/bar/images |
|
| 253 |
- |
|
| 254 |
- **Headers**: |
|
| 255 |
- Authorization: Token |
|
| 256 |
- signature=123abc,repository=”foo/bar”,access=write |
|
| 257 |
- |
|
| 258 |
- **Action**: |
|
| 259 |
- - Index: |
|
| 260 |
- will invalidate the token. |
|
| 261 |
- - Registry: |
|
| 262 |
- grants a session (if token is approved) and fetches |
|
| 263 |
- the images id |
|
| 264 |
- |
|
| 265 |
-5. (Docker -> Registry) PUT /v1/images/98765432_parent/json |
|
| 266 |
- |
|
| 267 |
- **Headers**:: |
|
| 268 |
- - Authorization: Token |
|
| 269 |
- signature=123abc,repository=”foo/bar”,access=write |
|
| 270 |
- - Cookie: (Cookie provided by the Registry) |
|
| 271 |
- |
|
| 272 |
-6. (Docker -> Registry) PUT /v1/images/98765432/json |
|
| 273 |
- |
|
| 274 |
- **Headers**: |
|
| 275 |
- - Cookie: (Cookie provided by the Registry) |
|
| 276 |
- |
|
| 277 |
-7. (Docker -> Registry) PUT /v1/images/98765432_parent/layer |
|
| 278 |
- |
|
| 279 |
- **Headers**: |
|
| 280 |
- - Cookie: (Cookie provided by the Registry) |
|
| 281 |
- |
|
| 282 |
-8. (Docker -> Registry) PUT /v1/images/98765432/layer |
|
| 283 |
- |
|
| 284 |
- **Headers**: |
|
| 285 |
- X-Docker-Checksum: sha256:436745873465fdjkhdfjkgh |
|
| 286 |
- |
|
| 287 |
-9. (Docker -> Registry) PUT /v1/repositories/foo/bar/tags/latest |
|
| 288 |
- |
|
| 289 |
- **Headers**: |
|
| 290 |
- - Cookie: (Cookie provided by the Registry) |
|
| 291 |
- |
|
| 292 |
- **Body**: |
|
| 293 |
- “98765432” |
|
| 294 |
- |
|
| 295 |
-10. (Docker -> Index) PUT /v1/repositories/foo/bar/images |
|
| 296 |
- |
|
| 297 |
- **Headers**: |
|
| 298 |
- Authorization: Basic 123oislifjsldfj== X-Docker-Endpoints: |
|
| 299 |
- registry1.docker.io (no validation on this right now) |
|
| 300 |
- |
|
| 301 |
- **Body**: |
|
| 302 |
- (The image, id`s, tags and checksums) |
|
| 303 |
- [{“id”:
|
|
| 304 |
- “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”, |
|
| 305 |
- “checksum”: |
|
| 306 |
- “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”}] |
|
| 307 |
- |
|
| 308 |
- **Return**: HTTP 204 |
|
| 309 |
- |
|
| 310 |
-> **Note:** If push fails and they need to start again, what happens in the index, |
|
| 311 |
-> there will already be a record for the namespace/name, but it will be |
|
| 312 |
-> initialized. Should we allow it, or mark as name already used? One edge |
|
| 313 |
-> case could be if someone pushes the same thing at the same time with two |
|
| 314 |
-> different shells. |
|
| 315 |
- |
|
| 316 |
-If it's a retry on the Registry, Docker has a cookie (provided by the |
|
| 317 |
-registry after token validation). So the Index won't have to provide a |
|
| 318 |
-new token. |
|
| 319 |
- |
|
| 320 |
-### Delete |
|
| 321 |
- |
|
| 322 |
-If you need to delete something from the index or registry, we need a |
|
| 323 |
-nice clean way to do that. Here is the workflow. |
|
| 324 |
- |
|
| 325 |
-1. Docker contacts the index to request a delete of a repository |
|
| 326 |
- `samalba/busybox` (authentication required with user credentials) |
|
| 327 |
-2. If authentication works and repository is valid, `samalba/busybox` |
|
| 328 |
- is marked as deleted and a temporary token is returned |
|
| 329 |
-3. Send a delete request to the registry for the repository (along with |
|
| 330 |
- the token) |
|
| 331 |
-4. Registry A contacts the Index to verify the token (token must |
|
| 332 |
- corresponds to the repository name) |
|
| 333 |
-5. Index validates the token. Registry A deletes the repository and |
|
| 334 |
- everything associated to it. |
|
| 335 |
-6. docker contacts the index to let it know it was removed from the |
|
| 336 |
- registry, the index removes all records from the database. |
|
| 337 |
- |
|
| 338 |
-> **Note**: |
|
| 339 |
-> The Docker client should present an "Are you sure?" prompt to confirm |
|
| 340 |
-> the deletion before starting the process. Once it starts it can't be |
|
| 341 |
-> undone. |
|
| 342 |
- |
|
| 343 |
-**API (deleting repository foo/bar):** |
|
| 344 |
- |
|
| 345 |
-1. (Docker -> Index) DELETE /v1/repositories/foo/bar/ |
|
| 346 |
- |
|
| 347 |
- **Headers**: |
|
| 348 |
- Authorization: Basic sdkjfskdjfhsdkjfh== X-Docker-Token: |
|
| 349 |
- true |
|
| 350 |
- |
|
| 351 |
- **Action**: |
|
| 352 |
- - in index, we make sure it is a valid repository, and set |
|
| 353 |
- to deleted (logically) |
|
| 354 |
- |
|
| 355 |
- **Body**: |
|
| 356 |
- Empty |
|
| 357 |
- |
|
| 358 |
-2. (Index -> Docker) 202 Accepted |
|
| 359 |
- |
|
| 360 |
- **Headers**: |
|
| 361 |
- - WWW-Authenticate: Token |
|
| 362 |
- signature=123abc,repository=”foo/bar”,access=delete |
|
| 363 |
- - X-Docker-Endpoints: registry.docker.io [, |
|
| 364 |
- registry2.docker.io] |
|
| 365 |
- # list of endpoints where this repo lives. |
|
| 366 |
- |
|
| 367 |
-3. (Docker -> Registry) DELETE /v1/repositories/foo/bar/ |
|
| 368 |
- |
|
| 369 |
- **Headers**: |
|
| 370 |
- Authorization: Token |
|
| 371 |
- signature=123abc,repository=”foo/bar”,access=delete |
|
| 372 |
- |
|
| 373 |
-4. (Registry->Index) PUT /v1/repositories/foo/bar/auth |
|
| 374 |
- |
|
| 375 |
- **Headers**: |
|
| 376 |
- Authorization: Token |
|
| 377 |
- signature=123abc,repository=”foo/bar”,access=delete |
|
| 378 |
- |
|
| 379 |
- **Action**: |
|
| 380 |
- - Index: |
|
| 381 |
- will invalidate the token. |
|
| 382 |
- - Registry: |
|
| 383 |
- deletes the repository (if token is approved) |
|
| 384 |
- |
|
| 385 |
-5. (Registry -> Docker) 200 OK |
|
| 386 |
- |
|
| 387 |
- 200 If success 403 if forbidden 400 if bad request 404 |
|
| 388 |
- if repository isn't found |
|
| 389 |
- |
|
| 390 |
-6. (Docker -> Index) DELETE /v1/repositories/foo/bar/ |
|
| 391 |
- |
|
| 392 |
- **Headers**: |
|
| 393 |
- Authorization: Basic 123oislifjsldfj== X-Docker-Endpoints: |
|
| 394 |
- registry-1.docker.io (no validation on this right now) |
|
| 395 |
- |
|
| 396 |
- **Body**: |
|
| 397 |
- Empty |
|
| 398 |
- |
|
| 399 |
- **Return**: HTTP 200 |
|
| 400 |
- |
|
| 401 |
-## How to use the Registry in standalone mode |
|
| 402 |
- |
|
| 403 |
-The Index has two main purposes (along with its fancy social features): |
|
| 404 |
- |
|
| 405 |
- - Resolve short names (to avoid passing absolute URLs all the time): |
|
| 406 |
- |
|
| 407 |
- username/projectname -> |
|
| 408 |
- https://registry.docker.io/users/<username>/repositories/<projectname>/ |
|
| 409 |
- team/projectname -> |
|
| 410 |
- https://registry.docker.io/team/<team>/repositories/<projectname>/ |
|
| 411 |
- |
|
| 412 |
- - Authenticate a user as a repos owner (for a central referenced |
|
| 413 |
- repository) |
|
| 414 |
- |
|
| 415 |
-### Without an Index |
|
| 416 |
- |
|
| 417 |
-Using the Registry without the Index can be useful to store the images |
|
| 418 |
-on a private network without having to rely on an external entity |
|
| 419 |
-controlled by Docker Inc. |
|
| 420 |
- |
|
| 421 |
-In this case, the registry will be launched in a special mode |
|
| 422 |
-(–standalone? –no-index?). In this mode, the only thing which changes is |
|
| 423 |
-that Registry will never contact the Index to verify a token. It will be |
|
| 424 |
-the Registry owner responsibility to authenticate the user who pushes |
|
| 425 |
-(or even pulls) an image using any mechanism (HTTP auth, IP based, |
|
| 426 |
-etc...). |
|
| 427 |
- |
|
| 428 |
-In this scenario, the Registry is responsible for the security in case |
|
| 429 |
-of data corruption since the checksums are not delivered by a trusted |
|
| 430 |
-entity. |
|
| 431 |
- |
|
| 432 |
-As hinted previously, a standalone registry can also be implemented by |
|
| 433 |
-any HTTP server handling GET/PUT requests (or even only GET requests if |
|
| 434 |
-no write access is necessary). |
|
| 435 |
- |
|
| 436 |
-### With an Index |
|
| 437 |
- |
|
| 438 |
-The Index data needed by the Registry are simple: |
|
| 439 |
- |
|
| 440 |
- - Serve the checksums |
|
| 441 |
- - Provide and authorize a Token |
|
| 442 |
- |
|
| 443 |
-In the scenario of a Registry running on a private network with the need |
|
| 444 |
-of centralizing and authorizing, it's easy to use a custom Index. |
|
| 445 |
- |
|
| 446 |
-The only challenge will be to tell Docker to contact (and trust) this |
|
| 447 |
-custom Index. Docker will be configurable at some point to use a |
|
| 448 |
-specific Index, it'll be the private entity responsibility (basically |
|
| 449 |
-the organization who uses Docker in a private environment) to maintain |
|
| 450 |
-the Index and the Docker's configuration among its consumers. |
|
| 451 |
- |
|
| 452 |
-## The API |
|
| 453 |
- |
|
| 454 |
-The first version of the api is available here: |
|
| 455 |
-[https://github.com/jpetazzo/docker/blob/acd51ecea8f5d3c02b00a08176171c59442df8b3/docs/images-repositories-push-pull.md](https://github.com/jpetazzo/docker/blob/acd51ecea8f5d3c02b00a08176171c59442df8b3/docs/images-repositories-push-pull.md) |
|
| 456 |
- |
|
| 457 |
-### Images |
|
| 458 |
- |
|
| 459 |
-The format returned in the images is not defined here (for layer and |
|
| 460 |
-JSON), basically because Registry stores exactly the same kind of |
|
| 461 |
-information as Docker uses to manage them. |
|
| 462 |
- |
|
| 463 |
-The format of ancestry is a line-separated list of image ids, in age |
|
| 464 |
-order, i.e. the image's parent is on the last line, the parent of the |
|
| 465 |
-parent on the next-to-last line, etc.; if the image has no parent, the |
|
| 466 |
-file is empty. |
|
| 467 |
- |
|
| 468 |
- GET /v1/images/<image_id>/layer |
|
| 469 |
- PUT /v1/images/<image_id>/layer |
|
| 470 |
- GET /v1/images/<image_id>/json |
|
| 471 |
- PUT /v1/images/<image_id>/json |
|
| 472 |
- GET /v1/images/<image_id>/ancestry |
|
| 473 |
- PUT /v1/images/<image_id>/ancestry |
|
| 474 |
- |
|
| 475 |
-### Users |
|
| 476 |
- |
|
| 477 |
-### Create a user (Index) |
|
| 478 |
- |
|
| 479 |
- POST /v1/users: |
|
| 480 |
- |
|
| 481 |
- **Body**: |
|
| 482 |
- {"email": "[sam@dotcloud.com](mailto:sam%40dotcloud.com)",
|
|
| 483 |
- "password": "toto42", "username": "foobar"`} |
|
| 484 |
- |
|
| 485 |
- **Validation**: |
|
| 486 |
- - **username**: min 4 character, max 30 characters, must match the |
|
| 487 |
- regular expression [a-z0-9_]. |
|
| 488 |
- - **password**: min 5 characters |
|
| 489 |
- |
|
| 490 |
- **Valid**: return HTTP 200 |
|
| 491 |
- |
|
| 492 |
-Errors: HTTP 400 (we should create error codes for possible errors) - |
|
| 493 |
-invalid json - missing field - wrong format (username, password, email, |
|
| 494 |
-etc) - forbidden name - name already exists |
|
| 495 |
- |
|
| 496 |
-> **Note**: |
|
| 497 |
-> A user account will be valid only if the email has been validated (a |
|
| 498 |
-> validation link is sent to the email address). |
|
| 499 |
- |
|
| 500 |
-### Update a user (Index) |
|
| 501 |
- |
|
| 502 |
- PUT /v1/users/<username> |
|
| 503 |
- |
|
| 504 |
- **Body**: |
|
| 505 |
- {"password": "toto"}
|
|
| 506 |
- |
|
| 507 |
-> **Note**: |
|
| 508 |
-> We can also update email address, if they do, they will need to reverify |
|
| 509 |
-> their new email address. |
|
| 510 |
- |
|
| 511 |
-### Login (Index) |
|
| 512 |
- |
|
| 513 |
-Does nothing else but asking for a user authentication. Can be used to |
|
| 514 |
-validate credentials. HTTP Basic Auth for now, maybe change in future. |
|
| 515 |
- |
|
| 516 |
-GET /v1/users |
|
| 517 |
- |
|
| 518 |
- **Return**: |
|
| 519 |
- - Valid: HTTP 200 |
|
| 520 |
- - Invalid login: HTTP 401 |
|
| 521 |
- - Account inactive: HTTP 403 Account is not Active |
|
| 522 |
- |
|
| 523 |
-### Tags (Registry) |
|
| 524 |
- |
|
| 525 |
-The Registry does not know anything about users. Even though |
|
| 526 |
-repositories are under usernames, it's just a namespace for the |
|
| 527 |
-registry. Allowing us to implement organizations or different namespaces |
|
| 528 |
-per user later, without modifying the Registry'sAPI. |
|
| 529 |
- |
|
| 530 |
-The following naming restrictions apply: |
|
| 531 |
- |
|
| 532 |
- - Namespaces must match the same regular expression as usernames (See |
|
| 533 |
- 4.2.1.) |
|
| 534 |
- - Repository names must match the regular expression [a-zA-Z0-9-_.] |
|
| 535 |
- |
|
| 536 |
-### Get all tags: |
|
| 537 |
- |
|
| 538 |
-GET /v1/repositories/<namespace>/<repository_name>/tags |
|
| 539 |
- |
|
| 540 |
- **Return**: HTTP 200 |
|
| 541 |
- { "latest":
|
|
| 542 |
- "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f", |
|
| 543 |
- “0.1.1”: |
|
| 544 |
- “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087” } |
|
| 545 |
- |
|
| 546 |
- **4.3.2 Read the content of a tag (resolve the image id):** |
|
| 547 |
- |
|
| 548 |
- GET /v1/repositories/<namespace>/<repo_name>/tags/<tag> |
|
| 549 |
- |
|
| 550 |
- **Return**: |
|
| 551 |
- "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f" |
|
| 552 |
- |
|
| 553 |
- **4.3.3 Delete a tag (registry):** |
|
| 554 |
- |
|
| 555 |
- DELETE /v1/repositories/<namespace>/<repo_name>/tags/<tag> |
|
| 556 |
- |
|
| 557 |
-### 4.4 Images (Index) |
|
| 558 |
- |
|
| 559 |
-For the Index to “resolve” the repository name to a Registry location, |
|
| 560 |
-it uses the X-Docker-Endpoints header. In other terms, this requests |
|
| 561 |
-always add a `X-Docker-Endpoints` to indicate the |
|
| 562 |
-location of the registry which hosts this repository. |
|
| 563 |
- |
|
| 564 |
-**4.4.1 Get the images:** |
|
| 565 |
- |
|
| 566 |
- GET /v1/repositories/<namespace>/<repo_name>/images |
|
| 567 |
- |
|
| 568 |
- **Return**: HTTP 200 |
|
| 569 |
- [{“id”:
|
|
| 570 |
- “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”, |
|
| 571 |
- “checksum”: |
|
| 572 |
- “[md5:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087](md5:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087)”}] |
|
| 573 |
- |
|
| 574 |
-### Add/update the images: |
|
| 575 |
- |
|
| 576 |
-You always add images, you never remove them. |
|
| 577 |
- |
|
| 578 |
- PUT /v1/repositories/<namespace>/<repo_name>/images |
|
| 579 |
- |
|
| 580 |
- **Body**: |
|
| 581 |
- [ {“id”:
|
|
| 582 |
- “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”, |
|
| 583 |
- “checksum”: |
|
| 584 |
- “sha256:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”} |
|
| 585 |
- ] |
|
| 586 |
- |
|
| 587 |
- **Return**: 204 |
|
| 588 |
- |
|
| 589 |
-### Repositories |
|
| 590 |
- |
|
| 591 |
-### Remove a Repository (Registry) |
|
| 592 |
- |
|
| 593 |
-DELETE /v1/repositories/<namespace>/<repo_name> |
|
| 594 |
- |
|
| 595 |
-Return 200 OK |
|
| 596 |
- |
|
| 597 |
-### Remove a Repository (Index) |
|
| 598 |
- |
|
| 599 |
-This starts the delete process. see 2.3 for more details. |
|
| 600 |
- |
|
| 601 |
-DELETE /v1/repositories/<namespace>/<repo_name> |
|
| 602 |
- |
|
| 603 |
-Return 202 OK |
|
| 604 |
- |
|
| 605 |
-## Chaining Registries |
|
| 606 |
- |
|
| 607 |
-It's possible to chain Registries server for several reasons: |
|
| 608 |
- |
|
| 609 |
- - Load balancing |
|
| 610 |
- - Delegate the next request to another server |
|
| 611 |
- |
|
| 612 |
-When a Registry is a reference for a repository, it should host the |
|
| 613 |
-entire images chain in order to avoid breaking the chain during the |
|
| 614 |
-download. |
|
| 615 |
- |
|
| 616 |
-The Index and Registry use this mechanism to redirect on one or the |
|
| 617 |
-other. |
|
| 618 |
- |
|
| 619 |
-Example with an image download: |
|
| 620 |
- |
|
| 621 |
-On every request, a special header can be returned: |
|
| 622 |
- |
|
| 623 |
- X-Docker-Endpoints: server1,server2 |
|
| 624 |
- |
|
| 625 |
-On the next request, the client will always pick a server from this |
|
| 626 |
-list. |
|
| 627 |
- |
|
| 628 |
-## Authentication & Authorization |
|
| 629 |
- |
|
| 630 |
-### On the Index |
|
| 631 |
- |
|
| 632 |
-The Index supports both “Basic” and “Token” challenges. Usually when |
|
| 633 |
-there is a `401 Unauthorized`, the Index replies |
|
| 634 |
-this: |
|
| 635 |
- |
|
| 636 |
- 401 Unauthorized |
|
| 637 |
- WWW-Authenticate: Basic realm="auth required",Token |
|
| 638 |
- |
|
| 639 |
-You have 3 options: |
|
| 640 |
- |
|
| 641 |
-1. Provide user credentials and ask for a token |
|
| 642 |
- |
|
| 643 |
- **Header**: |
|
| 644 |
- - Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
| 645 |
- - X-Docker-Token: true |
|
| 646 |
- |
|
| 647 |
- In this case, along with the 200 response, you'll get a new token |
|
| 648 |
- (if user auth is ok): If authorization isn't correct you get a 401 |
|
| 649 |
- response. If account isn't active you will get a 403 response. |
|
| 650 |
- |
|
| 651 |
- **Response**: |
|
| 652 |
- - 200 OK |
|
| 653 |
- - X-Docker-Token: Token |
|
| 654 |
- signature=123abc,repository=”foo/bar”,access=read |
|
| 655 |
- |
|
| 656 |
- |
|
| 657 |
-2. Provide user credentials only |
|
| 658 |
- |
|
| 659 |
- **Header**: |
|
| 660 |
- Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
|
| 661 |
- |
|
| 662 |
-3. Provide Token |
|
| 663 |
- |
|
| 664 |
- **Header**: |
|
| 665 |
- Authorization: Token |
|
| 666 |
- signature=123abc,repository=”foo/bar”,access=read |
|
| 667 |
- |
|
| 668 |
-### 6.2 On the Registry |
|
| 669 |
- |
|
| 670 |
-The Registry only supports the Token challenge: |
|
| 671 |
- |
|
| 672 |
- 401 Unauthorized |
|
| 673 |
- WWW-Authenticate: Token |
|
| 674 |
- |
|
| 675 |
-The only way is to provide a token on `401 Unauthorized` |
|
| 676 |
-responses: |
|
| 677 |
- |
|
| 678 |
- Authorization: Token signature=123abc,repository="foo/bar",access=read |
|
| 679 |
- |
|
| 680 |
-Usually, the Registry provides a Cookie when a Token verification |
|
| 681 |
-succeeded. Every time the Registry passes a Cookie, you have to pass it |
|
| 682 |
-back the same cookie.: |
|
| 683 |
- |
|
| 684 |
- 200 OK |
|
| 685 |
- Set-Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4="; Path=/; HttpOnly |
|
| 686 |
- |
|
| 687 |
-Next request: |
|
| 688 |
- |
|
| 689 |
- GET /(...) |
|
| 690 |
- Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4=" |
|
| 691 |
- |
|
| 692 |
-## Document Version |
|
| 693 |
- |
|
| 694 |
- - 1.0 : May 6th 2013 : initial release |
|
| 695 |
- - 1.1 : June 1st 2013 : Added Delete Repository and way to handle new |
|
| 696 |
- source namespace. |
|
| 697 |
- |