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

Move --rm to daemon side #20848

Merged
merged 4 commits into from
Aug 8, 2016
Merged

Conversation

WeiZhang555
Copy link
Contributor

@WeiZhang555 WeiZhang555 commented Mar 2, 2016

Fixes #20334
Fixes #16575
Fixes #6003
Fixes #20744
Fixes #12157
So many related issues, I won't list them one by one.

--rm is a client side flag which caused lots of problems:

  1. if client lost connection to daemon, including client crash or be killed, there's no way to clean garbage container.
  2. if docker stop a --rm container, this container won't be autoremoved.
  3. if docker daemon restart, container is also left over.
  4. bug: docker run --rm busybox fakecmd will exit without cleanup.

In a word, client side --rm flag isn't sufficient for garbage collection. Move the --rm flag to daemon will be more reasonable.

What this commit do is:

  1. implement a --rm on daemon side, adding one flag AutoRemove into HostConfig.
  2. allow run --rm -d, no conflicting --rm and -d any more, auto-remove can work on detach mode.
  3. docker restart a --rm container will succeed, the container won't be autoremoved.

This commit will help a lot for daemon to do garbage collection for temporary containers for short term job.

Signed-off-by: Zhang Wei zhangwei555@huawei.com

1334551250-0

@WeiZhang555
Copy link
Contributor Author

And if we gracefully shut down daemon, container will be auto removed, but if we forcefully shut down daemon(for example, press CTRL+C three time on daemon), container will be left over. I'm still working on this.

Also test cases are on working.

ping @vdemeester @duglin @tianon @calavera for design review.

@tianon
Copy link
Member

tianon commented Mar 2, 2016

Your description of the proposed behavior seems sane IMO 👍

(So happy to see someone tackling this again 😄)

@WeiZhang555 WeiZhang555 force-pushed the move-rm-to-daemon branch 2 times, most recently from 346a55c to 16bfba2 Compare March 2, 2016 06:32
@WeiZhang555 WeiZhang555 force-pushed the move-rm-to-daemon branch 4 times, most recently from 92300d6 to 3702383 Compare March 2, 2016 13:25
@phemmer
Copy link
Contributor

phemmer commented Mar 2, 2016

Happy to see this feature. Do we want to also allow something like --rm=always and --rm=on-success, similar to the restart policy (with the default --rm behaving like --rm=always)? That way if a container fails for some reason, we give the user the option of inspecting it.
This wouldn't have to be implemented in this PR since it would a new feature.

@WeiZhang555
Copy link
Contributor Author

@phemmer Is there any scenario or benefit for --rm=always style user interface? It seems complicated and unnecessary from my point of view.

So my current thought is keeping daemon side --rm flag similar to previous behavior, which means --rm is a bool option instead of string option.

I'm glad to hear more feedbacks from you 😄

@@ -39,8 +39,10 @@ func (daemon *Daemon) containerRestart(container *container.Container, seconds i
return err
}

if err := daemon.containerStart(container); err != nil {
return err
if !container.HostConfig.AutoRemove {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this one. I think we should allow the client to restart a container w/o it being removed. Granted this means that "docker stop" and "docker start" will not be the exact same as "docker restart" in this case but I think this is what the user would expect - otherwise they wouldn't be trying to do "docker restart" at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is limited by current design of restart policy, if we run docker stop on one container, it will stop immediately no matter what its restart policy is. According to our previous discussion, --rm should mean "delete the container when the container stops and won't restart any more", so if it stops, the container is removed, there's no need to start it again, and the start is bound to fail.

That's why I'm saying:
"4. docker restart a --rm container will behave like a docker stop, container will be stopped and removed."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also restricted by technique, I can't find a method to distinguish stop command from docker restart or pure docker stop, I can only detect the container is stopped and should be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if you don't add this if-statement then I think it'll act the way the end user expects. There's a difference between "docker stop" and "docker restart". Stop is asking for the container to fully stop running. Restart is just asking for it to be rebooted NOT stopped - not unlike a daemon reboot would. If we don't do this then there's no difference between "docker stop" and "docker restart" - and I don't think that's correct. A restart is the user's way of explicitly telling us that they don't want the container to be fully stopped, otherwise they would just use "stop".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally agree with you about the behavior, but I think remove this if clause won't make it work. Maybe I need to do some trick, for example, set --rm=false before restart, and restore it after restart. I'll make some try.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to play with it too- one thing to try is to set the restart policy to "always" temporarily so that we don't need to explicitly call start ourselves :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid setting restart policy to always won't work, if you docker stop a container with restart policy "always", it will stop and don't restart. This is strange, I would expect it will restart no matter how it is stopped.

I guess this is also limited by technique.

@duglin
Copy link
Contributor

duglin commented Mar 2, 2016

Overall design looks good!! Just one question about "docker restart".

@estesp
Copy link
Contributor

estesp commented Mar 2, 2016

Design seems good and looks like behavior is conforming to test expectations, except for one test: TestExternalVolumeDriverUnnamed is not getting removal of the volume properly, it seems.

@duglin's question is interesting, but was an impossible case in current --rm; once stopped your container was always gone, so there was no way to even consider restart of a auto-removed container.

@WeiZhang555
Copy link
Contributor Author

@estesp I'll try to fix the test case.
I'm planning to play a trick for docker restart, to set the "AutoRemove" flag to false before container stop and restore it after container stop. Then the docker restart can ignore AutoRemove flag.
I make a little test and it works, what do you think of this?

@WeiZhang555
Copy link
Contributor Author

Code for docker restart is updated, it's a little tricky but works. So I'll define current behavior of docker restart as:

4. `docker restart` a `--rm` container will succeed, the container won't be autoremoved.

What do you think of this? About bahavior and code implementation. @duglin @estesp

@duglin
Copy link
Contributor

duglin commented Mar 2, 2016

@WeiZhang555 yes something like that looks good. I need to think more about the use of the defer in that case but in general yes!

// set AutoRemove flag to false before stop so the container won't be
// removed during restart process
autoRemove := container.HostConfig.AutoRemove
defer func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you think I'm being paranoid, but I'd prefer this:

    // set AutoRemove flag to false before stop so the container won't be
    // removed during restart process
    autoRemove := container.HostConfig.AutoRemove

    container.HostConfig.AutoRemove = false
    err := daemon.containerStop(container, seconds)
    container.HostConfig.AutoRemove = autoRemove

    if err != nil {
        return err
    }

    if err := daemon.containerStart(container); err != nil {
        return err
    }

because I'm worried about the defer resetting the container.HostConfig.AutoRemove when perhaps it shouldn't. For example, normally I wouldn't expect containerStart() to change that value but you never know what might happen in the future. So to prevent unexpected side-effects of the defer, I think it would be safer to just clear and then reset AutoRemove right around the containerStop() since that's really the only code we need to be worried about.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good, I will modify as per your suggestion 😄

@duglin
Copy link
Contributor

duglin commented Mar 2, 2016

keep forgetting that this is still in design review, so making it official: SGTM

@thaJeztah thaJeztah added the status/failing-ci Indicates that the PR in its current state fails the test suite label Mar 3, 2016
@thaJeztah
Copy link
Member

Design sgtm as well, some questions / thoughts:

  • do we want AutoRemove to be a boolean in HostConfig, or make it a string with a default (e.g. "on-stop"). This would allow future expansion without having to change its type
  • how will this interact with older clients? i.e. a docker 1.10 client will do the remove client-side. oh, think this would work correctly, because older clients won't pass the "remove" policy to the daemon, so should be ok
  • new clients talking to an older daemon; do we want to support that? i.e. should the client be aware it's talking to an older daemon and (in that case), do the remove client-side as we do right now?

@vdemeester
Copy link
Member

new clients talking to an older daemon; do we want to support that? i.e. should the client be aware it's talking to an older daemon and (in that case), do the remove client-side as we do right now?

Good point, what should we do in case of DOCKER_API_VERSION=… ? 👼

@duglin
Copy link
Contributor

duglin commented Mar 3, 2016

Don't we have a policy of not supporting newer clients with older daemons? If nothing else I think the daemon will complain, no?

@thaJeztah
Copy link
Member

We don't really support new client + older daemon, so should probably be fine. Guess the daemon will silently ignore the option, just the user may be surprised that the container is not removed in that case

@WeiZhang555
Copy link
Contributor Author

do we want AutoRemove to be a boolean in HostConfig, or make it a string with a default (e.g. "on-stop"). This would allow future expansion without having to change its type

Yes, a string type will be better for future extension, but I can't identify its scenarios clearly. For example:

  • "--rm" can represent "when" to auto remove, so "--rm=on-stop" and "--rm=?", what can be another value?
  • "--rm" can be "How", so "--rm=rm-with-volume" or "--rm=rm-without-volumes", but I think current default behavior is already good enough, which means always remove with anonymous volumes, if I understand it right.

So maybe let "--rm bool" only do simple auto clean work is already good enough?

how will this interact with older clients? i.e. a docker 1.10 client will do the remove client-side. oh, think this would work correctly, because older clients won't pass the "remove" policy to the daemon, so should be ok

Yes, it will work.

new clients talking to an older daemon; do we want to support that? i.e. should the client be aware it's talking to an older daemon and (in that case), do the remove client-side as we do right now?

Ah, this is awful, I prefer not support this. Just did a quick test, new client+older daemon, it reports:

$ docker run -tid --rm busybox sh
docker: Error response from daemon: client is newer than server (client API version: 1.23, server API version: 1.21).
See 'docker run --help'.

Older daemon did a good job, I think this is already good enough.

What is everyone thinking of these?

@icecrime icecrime removed the status/failing-ci Indicates that the PR in its current state fails the test suite label Mar 3, 2016
@codingground
Copy link

Hi,

May I know when docker 1.13.0 is coming out?

@thaJeztah
Copy link
Member

@codingground release candidates are available for testing now https://github.com/docker/docker/releases

@codingground
Copy link

Thanks ThaJeztah. Its running great and --rm option with server is lovely. Now I'm able to create upto 1000 instances with ease and my Coding Ground is up and running without any further issue.

http://www.tutorialspoint.com/codingground.htm

@tiborvass
Copy link
Contributor

@codingground thanks for confirming!

@907th
Copy link

907th commented Aug 1, 2017

This seems not to work with docker-compose.

@cpuguy83
Copy link
Member

cpuguy83 commented Aug 1, 2017

@907th Not sure what that means, but if you have a specific issue with docker compose, please open an issue on github.com/docker/compose.

Thanks.

@thaJeztah
Copy link
Member

@907th please don't comment on old PR's and issues, I answered on your other comment; #28747 (comment)

@thaJeztah
Copy link
Member

I'm locking the conversation on this PR. If you arrive here to report a bug, please open a new issue with details. Commenting on closed PR's is not the right place to report bugs, as they easily go unnoticed, and may miss the required information.

@moby moby locked and limited conversation to collaborators Aug 1, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.