-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Docker images version change do not trigger container update #3639
Comments
This bug is still around. Is this a side effect of how the docker provider manages images? Right now (0.6.15) it also seems to pull images on plan if they aren't there because of the way it's written, which seems like a major bug. |
I'm not 100% sure since I don't know much about the internals of the docker provider, but I think this would be addressed by us finishing #6430 and then converting I think what's going on here is that Terraform can't tell at plan time that changing the If the But if we turn it into a data source then that will allow Since this data sources work is likely to land soon (coming in 0.7) I'm going to repurpose this ticket to be the conversion of provider "docker" {
host = "unix:/var/run/docker.sock"
}
resource "docker_container" "my-docker-container" {
name = "my-docker-container"
image = "${data.docker_image.my-docker-image.latest}"
}
data "docker_image" "my-docker-image" {
name = "my/docker-image:0.5.2"
} |
@apparentlymart I'm not sure converting docker_image to a data source is the right way to go here; the pulling of a specific docker image onto a host seems like state of a deployment that terraform should be managing. That said, it looks to me like this bug happens because terraform is calling the same code on read as it is on update: https://github.com/hashicorp/terraform/blob/master/builtin/providers/docker/resource_docker_image_funcs.go#L24-L41 This means it's pulling images/affecting state even during terraform plan; you can observe this by deleting an image from a docker host after terraform has pulled it and then running plan and seeing it re-download the image. It seems like this behavior is counter to how terraform should work. I think this is also the cause of #6431 - terraform calls read() for the resource, attempts to pull the invalid tag and fails because it doesn't exist. Instead, it shouldn't even be able to attempt to pull an invalid tag because read should fail when the image/tag doesn't exist on the registry. The real fix here that I see would be to make terraform only pull the image on update, and change read to check the registry the image refers to in order to get the SHA stored there for the image/tag. Then, it would know the SHA during plan and would be able to diff that against the image AND container resources instead of just reading the image name and diffing that against the image resource. If people agree with that, I'd be happy to work on a PR |
Oh I see... I should've looked more closely before commenting because I didn't know this resource was actually downloading the image... I was thinking about it like "docker run" where the container creation does the image download (where necessary) as a side-effect. In which case I think using ForceNew in conjunction with what you suggested seems reasonable. The trick is that Terraform can't handle an in-place update of a computed attribute as you expect because the code dealing with the diff can't tell what changes will be made on Update. By using ForceNew Terraform sees that the whole resource is getting rebuilt and knows to generate a diff. |
I'll try to submit a PR for this soon, then. |
@apparentlymart After trying this out, I see what you mean. The only way terraform will update both the image and container in the same run is by setting ForceNew. In that case though, it recreates the container any time the image name changes, which isn't what I want either (if I'm switching to a new tag that points to the same image hash I don't want to restart). So it looks like some aspect of the data sources from #6430 are going to be needed here in order to make this case work nicely. Any suggestions on that? I don't see a way to make this work even with data sources other than by adding a new data source alongside image just to read the hash, which seems kind of clunky. It's also pretty strange to me that updating a computed field during plan/read doesn't have any effect on dependent resources, to inform their diffs during plan. |
The way I was originally conceiving it was that there'd be a data source to find containers by criteria without downloading them, and then the So in my earlier example, the I think this gets you what you want, because the I'm planning to do a similar thing with AWS AMIs, where you'd be able to find one and then spin a new EC2 instance only when the matched AMI changes. |
That would work for fixing this issue but then it turns the container resource into a container + image resource that just manages both. That seems kind of weird in the terraform model, but it would work. The other option is keeping the current image resource pretty much as is and just making it rely on a data source to get the SHA, so that it and the container resource can be updated correctly on changes. |
@apparentlymart Would it be possible to make ForceNew work for computed fields, so that reading an update to |
This is definitely an interesting case. I'm going to address your first comment first here. 😀 I'm definitely not a Docker expert (I've only used it in dev/CI systems so far, and not in production) so please do correct my assumptions here if they seem off... In my mental model of Docker I've tended to think of the local image store as just a "cache", and thus local images not as resources in their own right but just an implementation detail of booting up an image that "lives" in a remote repository. The
I'm not really convinced that Terraform is really "managing an image" in any useful sense of that term. In one case it "leaks" images and loses track of them, and in the other case it tries to exert exclusive ownership of a possibly-shared resource. So with all of that said, I would agree that there are really three different operations going on here that we're trying to model:
The first of these being a data source seems like a no-brainer to me, since that would address the concern of having it notice when a new image version is available. The part I'm less sure about is whether the second of these is worth modelling as a distinct resource or whether it should be combined into one of the others. The local image cache is a content-addressable set, so the "create" and "delete" operations here really mean "add to cache" ( Thus it felt right to me for the second operation to be a side-effect of the third, thus making the Again, please feel free to correct me if any of my reasoning above seems flawed when considering practical use of Docker! |
Now considering the question of putting Since I think there is a potential tweak to Terraform's behavior that would get the behavior you want: we could change the This would be the first example of Terraform doing something different than what the plan specified, but perhaps it's okay as long as the plan is always "more conservative" than what actually happens. That's a philosophical question that I'd want to reflect on more before forming an opinion. 😀 |
I think that's a fair point about image management. I don't see a good way for terraform to clean up old images in any implementation; it can't delete the old image immediately after downloading the new one because the container might still be running (and docker won't even allow it to be deleted if that's the case). So if it's going to leak images to the cache anyway, we might as well roll the image pull logic into the container resource and treat it as a If I understand right, we need the functionality of data sources to get terraform to turn an image name/tag into a SHA to diff against the existing container resource in the plan step. The only way to have that happen right now would be to enter the SHA itself into the container resource, which we obviously don't want to do. What's the working status of #6430 at the moment? Are data sources done enough for me to try out converting docker_image into one? |
I'm working on the data sources stuff right now, actually. As of this comment the branch is in a state where it would in theory be possible to develop a |
To work around this issue, you can do something like this: variable "docker_image_name" {
type = "string"
default = "my/docker_image:0.5.2"
}
resource "docker_container" "my_docker_container" {
name = "my_docker_container"
image = "${data.docker_image.my_docker_image.latest}"
env = [ "forceupdate=${var.docker_image_name}" ]
}
data "docker_image" "my_docker_image" {
name = "${var.docker_image_name)"
} It's not a perfect solution, but with this method any change to the name of the Docker image forces the Docker container to update. |
@apparentlymart What I've done so far lets you write this: data "docker_image" "nomad" {
name = "kyhavlov/nomad:latest"
}
resource "docker_image" "nomad" {
name = "${data.docker_image.nomad.name}"
registry_id = "${data.docker_image.nomad.id}"
}
resource "docker_container" "nomad-server" {
image = "${docker_image.nomad.latest}"
name = "nomad-server"
} I've fixed the docker_image read() behavior to just read the image id on the host instead of trying to actually pull an image, so if you have a manifest like the one above and you update the image in the registry, I should be able to have the PR up within a day or two. |
PR is up for review: #7000 |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
Problem
When i do docker image update i should run it in two step:
1. Update the image
2. Update container associated with the updated image
I think that terraform can be smart enough for handle this in one step.
My environment
My .tf declaration:
Terraform output
My version number
First plan
First apply
Second plan
Second apply
The text was updated successfully, but these errors were encountered: