I’m confused about the image property in the docker_container resource of a terraform tf file.
The following contents you see in all the tutorials:
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.latest
name = "tutorial"
ports {
internal = 80
external = 8000
}
}
This pulls the latest image.
But if you want a previous image, you need to specify the Digest, like this:
resource "docker_image" "nginx" {
name = "nginx:1.22.0@sha256:f2dfca5620b64b8e5986c1f3e145735ce6e291a7dc3cf133e0a460dca31aaf1f"
keep_locally = false
}
Then you need to create a container on that image with the docker_container Resource.
But there is no way you can specify that previous image tag or digest.
Things like image = docker_image.nginx:1.22.0@sha256:f2dfca5620b64b8e5986c1f3e145735ce6e291a7dc3cf133e0a460dca31aaf1f all fail. Various syntax versions are tried (quotes, no-quotes, etc, etc). They all result in an error.
The only way I could get this working was with the following:
resource "docker_image" "nginx" {
name = "nginx:1.22.0@sha256:f2dfca5620b64b8e5986c1f3e145735ce6e291a7dc3cf133e0a460dca31aaf1f"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.latest
name = "Terraform-Nginx"
ports {
internal = 80
external = 8000
}
}
But now I’m confused.
What does ".latest" even mean in the image property of the docker_container resource?
2
Answers
In reaction to @MarkoE's answer :
Your answer showed to use the id string:
This gave me the following error:
But from this link you provided I read:
Which made me change the code to:
(Note the docker_image.nginx.name)
And now it works. I even get the right tag in the docker images command.
Tnanks Marko
There are a couple of things to understand here. The first being the resource arguments and the second being the resource attributes [1]. In most of the providers, when you want to create a certain resource, you have to provide values for at least the required arguments. There are optional arguments as well. When a resource is successfully created, it provides a set of attributes which can be referenced in another resource. In your example, you cannot create a Docker container without specifying the image name. So instead of hardcoding the image name in the container resource, you first define the image resource and then reference its arguments/attributes in the container resource. The example you mention:
is not valid because the Docker image resource provides no arguments and attributes named
nginx:1.22.0@sha256:f2dfca5620b64b8e5986c1f3e145735ce6e291a7dc3cf133e0a460dca31aaf1f
, i.e., the provider schema knows nothing about that. The provider documentation has sections on arguments and attributes. The Docker provider documentation is lacking some of the usual elements, but in this case, the attributes seem to be denoted withRead-only
section [2]. There you will find thelatest
attribute that you use for referencing an image that was pulled. Also note that it says that the argument is deprecated:Based on the current documentation, you might want to use the following:
The syntax used when referencing attributes/arguments is always:
i.e.,
docker_image.nginx.latest
ordocker_iamge.nginx.name
.As a side note, to clear up any confusion, the way you are referencing the value for the image ID is called an implicit reference [3]. Since terraform creates resources in parallel, it helps when deciding the order in which the resources will be created. In this case the image will be pulled first and then the container will be created based on the image.
EDIT: updated the answer based on the input of @BertC.
[1] https://www.terraform.io/language/expressions/references#references-to-resource-attributes
[2] https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs/resources/image#read-only
[3] https://www.terraform.io/language/resources/behavior#resource-dependencies