I'm executing this in order to locally build a docker image using terraform. Succeeds on the first run, but fails at every other try with Error: failed to read dockerfile: unexpected EOF
unless I completely and manually remove the terraform.tfstate
file.
terraform {
backend "local" {}
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~>3.0.2"
}
# other providers
}
provider "docker" {
}
resource "docker_image" "dbx_kedro_img" {
name = "docker-build-test:latest"
build {
context = "."
dockerfile = "./Dockerfile"
}
}
I tried modifying the version to docker-build-test:latest2
or docker-build-test2:latest
, running terraform state rm docker_image.dbx_kedro_img
, removing the local docker images and containers, without success. only thing that works is to manually delete the terraform.tfstate
. Any idea welcome.
docker rm $(docker ps -aq) # not useful
docker rmi $(docker images -q) -f # idem
terraform state rm docker_image.dbx_kedro_img # idem
my dockerfile:
# Use a lightweight base image
FROM alpine:latest
#
# Set the command to run when the container starts
CMD ["echo", "Hello, World3!"]
EDIT: same behaviour after adding a trigger like this, fails after the first try, even when modifying the image name.
# not useful
resource "docker_image" "dbx_kedro_img" {
name = "docker-build-test5:latest"
build {
context = "."
dockerfile = "./Dockerfile"
}
triggers = {
always_rebuild = timestamp()
}
}
I have had a look at the provider and also ran it in debug mode. The issue as I replicated is like this. I created a directory and added to it two files. Dockerfile
and main.tf
$ ls -1
Dockerfile
main.tf
I run terraform apply
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
I update the tag in the main.tf and run the apply again and it gives an error.
╷
│ Error: failed to read dockerfile: unexpected EOF
│
│
│
│ with docker_image.dbx_kedro_img,
│ on main.tf line 10, in resource "docker_image" "dbx_kedro_img":
│ 10: resource "docker_image" "dbx_kedro_img" {
│
I then set TF_LOG=debug
and run the apply again. Thankfully the provider has written some decent logging so we can see whats going on here.
2025-01-22T22:19:33.805Z [INFO] provider.terraform-provider-docker_v3.0.2.exe: 2025/01/22 22:19:33 [DEBUG] Building docker image: timestamp=2025-01-22T22:19:33.805Z
2025-01-22T22:19:33.805Z [INFO] provider.terraform-provider-docker_v3.0.2.exe: 2025/01/22 22:19:33 [DEBUG] DockerClientVersion: 1.41, minBuildKitDockerVersion: 1.39: timestamp=2025-01-22T22:19:33.805Z
2025-01-22T22:19:33.805Z [INFO] provider.terraform-provider-docker_v3.0.2.exe: 2025/01/22 22:19:33 [DEBUG] Enabling BuildKit: timestamp=2025-01-22T22:19:33.805Z
2025-01-22T22:19:33.806Z [INFO] provider.terraform-provider-docker_v3.0.2.exe: 2025/01/22 22:19:33 [DEBUG] contextDir: timestamp=2025-01-22T22:19:33.806Z
2025-01-22T22:19:33.806Z [INFO] provider.terraform-provider-docker_v3.0.2.exe: 2025/01/22 22:19:33 [DEBUG] relDockerfile: timestamp=2025-01-22T22:19:33.806Z
2025-01-22T22:19:33.806Z [INFO] provider.terraform-provider-docker_v3.0.2.exe: 2025/01/22 22:19:33 [DEBUG] Excludes: []: timestamp=2025-01-22T22:19:33.806Z
2025-01-22T22:19:35.930Z [DEBUG] provider.terraform-provider-docker_v3.0.2.exe: time="2025-01-22T22:19:35Z" level=error msg="Can't add file \\\\?\\C:\\Projects\\GoLand\\playground_terraform\\docker\\terraform.tfstate to tar: read \\\\?\\C:\\Projects\\GoLand\\playground_terraform\\docker\\terraform.tfstate: The process cannot access the file because another process has locked a portion of the file."
2025-01-22T22:19:35.931Z [DEBUG] provider.terraform-provider-docker_v3.0.2.exe: time="2025-01-22T22:19:35Z" level=error msg="Can't add file \\\\?\\C:\\Projects\\GoLand\\playground_terraform\\docker\\terraform.tfstate.backup to tar: archive/tar: missed writing 180 bytes"
2025-01-22T22:19:35.931Z [DEBUG] provider.terraform-provider-docker_v3.0.2.exe: time="2025-01-22T22:19:35Z" level=error msg="Can't close tar writer: archive/tar: missed writing 180 bytes"
2025-01-22T22:19:36.473Z [ERROR] provider.terraform-provider-docker_v3.0.2.exe: Response contains error diagnostic: @caller=github.com/hashicorp/terraform-plugin-go@v0.14.3/tfprotov5/internal/diag/diagnostics.go:55
diagnostic_summary=
| failed to read dockerfile: unexpected EOF
|
tf_proto_version=5.3 tf_provider_addr=provider @module=sdk.proto diagnostic_detail="" diagnostic_severity=ERROR tf_req_id=f814d0e2-913a-36ef-5484-7c7ba4b34bd5 tf_resource_type=docker_image tf_rpc=ApplyResourceChange timestamp=2025-01-22T22:19:36.473Z
Essentially whats happening here is that the state file is written to the current directory. The same one as the dockerfile and the context. So when you run the apply a second time, now the state files are trying to be included in the context to be sent to the docker socket. However the state files are already locked by the terraform process at the OS. So are not able to be added to the docker context.
This results in the ambiguous error about unexpected EOF when reading the docker file.
if I put my Docker file in a sub directory and set my context and docker file to the subdir it all seems to work fine.
$ ls -1
docker-build
main.tf
$ ls -1 docker-build/
Dockerfile
resource "docker_image" "dbx_kedro_img" {
name = "docker-build-test:latest2"
build {
context = "./docker-build"
dockerfile = "./Dockerfile"
}
}
After I run the terraform apply when changing the tag name I get
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.