Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement deletes per the Docker Registry HTTP API V2 #422

Closed
bwb opened this issue Apr 23, 2015 · 25 comments
Closed

Implement deletes per the Docker Registry HTTP API V2 #422

bwb opened this issue Apr 23, 2015 · 25 comments
Assignees

Comments

@bwb
Copy link

bwb commented Apr 23, 2015

I'm using registry:2.0 to run a private Docker registry.

Image delete requests fail with an unsupported operation error.

I searched for answers, only to learn that this feature is not implemented:

Please change the Docker Registry 2.0 documentation. It links directly to the Docker Registry HTTP API V2, yet implements only a subset of API V2.

@kjozsa
Copy link

kjozsa commented Apr 23, 2015

+1

I updated to Registry 2.0 to have the delete operation working, only to find out later that it's not yet implemented. At least the docs should get updated on this to save people some time.

@stevvooe stevvooe changed the title Registry 2.0 does not implement Docker Registry HTTP API V2 Implement deletes per the Docker Registry HTTP API V2 Apr 23, 2015
@stevvooe
Copy link
Collaborator

@bwb @kjozsa Sorry about the confusion in the documentation. cc @moxiegirl

While deletes are part of the API, they cannot be safely implemented on top of an eventually consistent backend (read: s3). Please see #210 and #106 (comment) for some detail. As long as the registry supports varied backends, using an eventually consistent VFS model, safe deletions are not really possible without more infrastructure.

We are adding the ability to delete blobs, without cleaning up interrelated content. This can be done easily but issuing such deletes may corrupt individual repositories so they must be done with care. @ncdc

I understand this is annoying but ensuring data integrity is priority number one.

@huslage
Copy link

huslage commented Apr 28, 2015

Can you go into this a little more? S3 operations are atomic and the consistency model is variable. The fact that you can't delete at all is more disturbing than any sort of temporary effects a deletion on eventual consistency.

At the very least an interim solution of deletion on write-guaranteed filesystems (local FS) would be tolerable. Some state would likely need to be kept (at least in memory) to count references, but the cost of that is vastly outweighed by the utility of the function being implemented.

@stevvooe
Copy link
Collaborator

@huslage

Can you go into this a little more? S3 operations are atomic and the consistency model is variable. The fact that you can't delete at all is more disturbing than any sort of temporary effects a deletion on eventual consistency.

While the individual operations are atomic, visibility of those operations or a series of those operations are not. If you cannot be sure that no references are held to a given data object, you cannot safely delete it since a new reference, not visible to the deleting process, can be created in the interim. For example, let's say a delete is issued to manifest with digest A references a layer with digest B. When you delete A, the reference for B would decremented (or you would delete a file). During that point, the deletion algorithm would check the number of references (perhaps, by listing a directory). If there are no references, the item would be deleted. That decision must hold a mutex starting at the point of decrement to the point of deletion. Without the mutex, other processes may add references in the interim that would end up being invalid if the deletion was issued.

The main danger here is that data is deleted that wasn't meant to be deleted. This is always worse than storing extra data.

Deletes could still be safely issued through a management tool that "locks the world" (either by turning off the registry or locking out writes to the backend in some way). Deletes could also be directly issued on blobs that a user is certain must be removed. The registry will still handle this correctly albeit invalid manifests may be made available.

There is also a scheme that could separate the registry backend into "generations", where one generation is read-only and one allows writes. The read-only generation is swept and garbage collected, while writes are issued to the other generation. Reads are broadcast to both. An optimization to this approach would be to write references at write time and then issue deletes at read time, when it can be certain they are consistent, avoiding the sweep phase.

At the very least an interim solution of deletion on write-guaranteed filesystems (local FS) would be tolerable.

We have a bit of a lowest common denominator problem. The main mistake here was that the v1 registry's virtual file system model was carried over to the v2 registry. This prevents one from making certain obvious optimizations in data storage that may be different from driver to driver (for example, leverage atomic moves on a unix filesystem). Instead of files, the registry driver should know how to store a blob or how to index a manifest. One should be able to compose these drivers in the manner they see fit. Imagine managing consistency in a postgres instance while storing blobs in s3.

There are still issues that can arise in these scenarios, but I hope that clarifies. Please checkout the eventual consistency section on architecture. It enumerates various cases and the approaches to dealing with it.

@shykes
Copy link

shykes commented Apr 28, 2015

@stevvooe perhaps we can find an appropriate stopgap, to give users 90% of what they want, and continue working on the (harder) remaining 10%.

For example, we could expose 2 distinct endpoints:

  • remove would simply remove the reference and decrement reference, but not attempt garbage collection. This means no risk of deleting too much. It also means that simply calling remove does not save disk space, but the current situation is strictly worse.
  • vacuum would be a privileged administrator operation, which "locks the world" and removes dangling blobs to reclaim disk space.

This is not a perfect arrangement, but for most users I think it would be a significant improvement. Users want 2 things right now 1) the ability to make an image unavailable for pull on their registry, and 2) the ability to reclaim disk space.

WDYT?

@stevvooe
Copy link
Collaborator

@shykes This sounds reasonable. We can divide this into two features:

  1. Soft deletes of manifests and blobs through the Registry HTTP API.
  2. Asynchronous cleanup of unreferenced blob data.

If these sound good to you, we can makes issues covering each.

@shykes
Copy link

shykes commented Apr 28, 2015

Yes those sound good to me! I think they would make a lot of people very happy

@stevvooe
Copy link
Collaborator

I've filed #461 to cover item 1 and #462 to cover item 2. #461 has been added to the 2.1 milestone and #462 is unspecified.

@shykes
Copy link

shykes commented Apr 28, 2015

Awesome thanks!

@CptJason
Copy link

+1

I updated to Registry 2.0,and I found that I was not able to delete the image that I pushed.

root@ubuntu24:~# curl -v --cacert ~/certs/docker-registry-ca.pem -X DELETE -u ops:wowotuan https://registry.wowotuan.me/v2/busybox/manifests/latest

  • Hostname was NOT found in DNS cache
  • Trying 10.9.120.21...
  • Connected to registry.wowotuan.me (10.9.120.21) port 443 (#0)
  • successfully set certificate verify locations:
  • CAfile: /home/wowotuan/certs/docker-registry-ca.pem
    CApath: /etc/ssl/certs
  • SSLv3, TLS handshake, Client hello (1):
  • SSLv3, TLS handshake, Server hello (2):
  • SSLv3, TLS handshake, CERT (11):
  • SSLv3, TLS handshake, Server key exchange (12):
  • SSLv3, TLS handshake, Server finished (14):
  • SSLv3, TLS handshake, Client key exchange (16):
  • SSLv3, TLS change cipher, Client hello (1):
  • SSLv3, TLS handshake, Finished (20):
  • SSLv3, TLS change cipher, Client hello (1):
  • SSLv3, TLS handshake, Finished (20):
  • SSL connection using ECDHE-RSA-AES256-GCM-SHA384
  • Server certificate:
  • subject: C=CN; ST=BeiJing; L=BeiJing; O=Wowo; OU=Sod; CN=registry.wowotuan.me; emailAddress=zhangfan@55tuan.com
  • start date: 2015-05-14 08:32:35 GMT
  • expire date: 2016-05-13 08:32:35 GMT
  • common name: registry.wowotuan.me (matched)
  • issuer: C=CN; ST=BeiJing; L=BeiJing; O=Wowo; OU=Sod; CN=registry.wowotuan.me; emailAddress=zhangfan@55tuan.com
  • SSL certificate verify ok.
  • Server auth using Basic with user 'ops'

    DELETE /v2/busybox/manifests/latest HTTP/1.1
    Authorization: Basic b3BzOndvd290dWFu
    User-Agent: curl/7.35.0
    Host: registry.wowotuan.me
    Accept: /

    < HTTP/1.1 400 Bad Request
  • Server nginx/1.7.12 is not blacklisted
    < Server: nginx/1.7.12
    < Date: Fri, 22 May 2015 09:27:32 GMT
    < Content-Type: text/plain; charset=utf-8
    < Content-Length: 78
    < Connection: keep-alive
    < Docker-Distribution-Api-Version: registry/2.0
    < Docker-Distribution-Api-Version:: registry/2.0
    <
    {"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}
  • Connection #0 to host registry.wowotuan.me left intact

@thaJeztah
Copy link
Member

@CptJason looking at #422 (comment) this looks to be planned for the 2.1 release / milestone

@mattes
Copy link

mattes commented Jun 18, 2015

+1

2 similar comments
@luongnv89
Copy link

+1

@eebjr
Copy link

eebjr commented Jun 24, 2015

+1

@rantoniuk
Copy link

No milestone specified in the issue though 😎

@stevvooe
Copy link
Collaborator

@warden Please see #460 and #461 for information on progress and roadmap. This issue will get closed out when we close those out.

@mattes @luongnv89 @eebjr For those adding "+1", please specify which deletes use case you are interested in.

@mattes
Copy link

mattes commented Jun 24, 2015

We use TeamCity to build a Docker image for every git feature branch with the following naming pattern docker-image:{feature-branch}-{git-short-hash}

Use case 1:
Delete docker-image:{feature-branch}-* once related git branch is deleted.

Use case 2:
Only keep the last 25 images per feature branch to save some space.

Using local FS.

Did this help?

@stevvooe
Copy link
Collaborator

@mattes This does. It sounds like you'll be served by delete API + garbage collection (#462). Unfortunately, this is quite a way out unless we can get some help from the community.

We are unlikely to bring such deletion policies into the core registry code base. There are several different ways to do this that might be best served by an external notification endpoint. You should be able to create simple callback server that can implement these policies and delete the data directly from the filesystem.

@gesellix
Copy link

... you'll be served by delete API + garbage collection (#460).

@stevvooe did you mean #462?

@stevvooe
Copy link
Collaborator

@gesellix I did. I've edited my comment. Thank you.

@mkobrosli
Copy link

+1

1 similar comment
@mariolameiras
Copy link

+1

@raphaelrodrigues
Copy link

+1

@azpekt
Copy link

azpekt commented Aug 5, 2015

+1

@mbentley
Copy link
Contributor

mbentley commented Aug 5, 2015

Instead of adding just a +1, it would be better to use the 'Subscribe' button on the issue since a +1 without any additional feedback as to which deletes use case you are interested in sends out unnecessary notifications. Deletes will be implemented but doing things like this in the best way take time, effort, and good feedback.

@distribution distribution locked and limited conversation to collaborators Aug 6, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests