Description
I want to stop a running container and remove its image in one single puppet run
(without having to build custom puppet Stages or simillar, just to get the correct order of execution).
This is not possible :-/
docker::run { 'containername': ensure => absent, image => 'dockerimage:v1' } # an imagename **must** be set even with ensure absent
docker::image { 'Remove old container': ensure => absent, image => dockerimage, image_tag => 'v1' }
When run, this generates a puppet conflict:
unable to remove repository reference "dockerimage:v1" (must force) - container 57999c03407c is using its referenced image 2cbd348acfa3
(note: No other docker::-commands in the manifest are run due to "Skipping because of failed dependencies", so the container is not stopped either, where a second puppet run would probably have successfully removed the image)
So the image can't be removed because a running container is using it.
I now try to stop the container before removing its image.
But no matter if I add a require
to the docker::image
declaration:
docker::image { 'Remove old container': ensure => absent, image => dockerimage, image_tag => 'v1', require => Docker::Run['containername'] }
nor if I add a before
to the docker::run
declaration:
docker::run { 'containername': ensure => absent, image => 'dockerimage:v1', before => Docker::Image['Remove old container'] }
...I get a dependency cycle in both cases:
Exec[docker rmi dockerimage:v1] =>
Docker::Image[Remove old container] =>
Docker::Run[containername] =>
Service[docker-containername] =>
Docker::Run[containername] =>
Docker::Image[Remove old container] =>
Exec[docker rmi dockerimage:v1] =>
...and so on...
My guess is that this could be solved by having docker::run
not depend on the image resource if and when ensure
is set to absent
. I mean, when you want to stop a container you only need its name, not what image it uses.
PS: I'm also missing a prune
option in this puppetlabs module, to clean unused images from the filesystem, so I don't have to build a custom Exec to run: docker image prune --force --filter="label=app=containername"
PPS: My current workaround:
docker::run { 'containername': ensure => absent, image => 'dockerimage:v1', notify => Exec['Remove old container image'] }
exec { 'Remove old container image': command => "/usr/bin/docker image rm dockerimage:v1 && /usr/bin/docker image prune --force --filter='label=app=containername'", refreshonly => true }