terraform-provider-docker icon indicating copy to clipboard operation
terraform-provider-docker copied to clipboard

changing `context` location in `docker_registry_image` resource fails to build image in Windows only

Open wblakecannon opened this issue 2 years ago • 5 comments

Versions:

Terraform: 1.0.11
kreuzwerker/docker: 2.15.0
aws: 3.69.0
Docker: 20.10.11

Hello. I am working with a company and implementing Terraform to their builds. In order to keep from redoing all their code base, I am adding a terraform directory to their existing code and adding the Terraform there. I know this is a little tricky with the docker_registry_image as it seems the provider wants the source code and Docker imaage inside the Terraform working directory, so I'm doing a workaround to get that to work. My workaround works with Unix (Linux/macOS) but it does not work with Windows. I receive the error: Error: Error building docker image: unable to build context: unable to read build context - CreateFile C: The system cannot find the file specified.

main.tf

terraform {
  backend "s3" {
    bucket = "xxx"
    key    = "xxx.tfstate"
    region = "us-west-1"
  }

  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = ">= 2.8.0"
    }
  }
}

provider "aws" {
  region  = var.region
  profile = "default"
}

provider "docker" {
  host = local.os_check == "Windows" ? "npipe:////.//pipe//docker_engine" : null

  registry_auth {
    address  = local.ecr_address
    username = data.aws_ecr_authorization_token.token.user_name
    password = data.aws_ecr_authorization_token.token.password
  }
}

data "external" "os" {
  working_dir = path.module
  program     = ["printf", "{\"os\": \"Linux\"}"]
}

resource "docker_registry_image" "image" {
  name = format("%v:%v", aws_ecr_repository.repo.repository_url, "latest")

  build {
    context = trimsuffix("${path.cwd}", "/terraform") # DOES NOT WORK IN WINDOWS BUT WORKS IN UNIX
    dockerfile = "Dockerfile"
  }
}

var.tf:

locals {
  ecr_address    = format("%v.dkr.ecr.%v.amazonaws.com", data.aws_caller_identity.current.account_id, var.region)
  ecr_image_name = format("%v/%v:%v", local.ecr_address, aws_ecr_repository.repo.id, "latest")
  os_check       = data.external.os.result.os == "Windows" ? "Windows" : "Linux"
}

variable "region" {
  default = "us-west-1"
}

tree:

|-- Dockerfile
|-- Scripts
|   `-- local-invoke-dev.bat
|-- entry.sh
|-- hrrr.py
`-- terraform
    |-- main.tf
    |-- printf.cmd
    `-- var.tf

Output of plan:

  # docker_registry_image.image will be created
  + resource "docker_registry_image" "image" {
      + id                   = (known after apply)
      + insecure_skip_verify = false
      + keep_remotely        = false
      + name                 = "xxx.dkr.ecr.us-west-1.amazonaws.com/xxx:latest"
      + sha256_digest        = (known after apply)

      + build {
          + context    = "C:/Users/xxx/source/repos/xxx/xxx:506589686c3d0c3c58f829e0e75a60161c2aa08da96b2268b5e30f4cebe614a3"
          + dockerfile = "Dockerfile"
        }
    }

Since it doesn't work in Windows, the company is unable to do a local deploy using the following deploy-dev.bat. file:

@echo off
cd ../terraform
terraform init
terraform workspace new dev
terraform workspace select dev
terraform apply -auto-approve

This will eventually be fixed via CI/CD pipelines running Linux, but local deploys are currently needed for testing.

wblakecannon avatar Dec 17 '21 17:12 wblakecannon

I am wondering if it is passing the correct argument to CreateFile.

The CreateFile function can also open disk devices. To open the first disk of your computer, it is necessary to use the \\.\PhysicalDrive0 name; to open the C: partition, use the \\. \C : name.

wblakecannon avatar Dec 17 '21 17:12 wblakecannon

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days. If you don't want this issue to be closed, please set the label pinned.

github-actions[bot] avatar Feb 16 '22 10:02 github-actions[bot]

I am having a similar problem, not sure if its caused by the same issue. I also have my terraform files in a /terraform directory of the project, so hence want to build ...

resource "docker_registry_image" "image" {
  name = "registry.digitalocean.com/myregistry/image:latest"
  build{
    auth_config{
      host_name = "registry.digitalocean.com"
    }
    context = ".."
  }
}
Error building docker image: unable to build context: read ..\terraform\terraform.tfstate: The process cannot access the file because another process has locked a portion of the file.

mrbrianevans avatar Apr 26 '22 21:04 mrbrianevans

Same problem also for me on windows (with docker desktop installed). In my case the error says that the a file is not present inside the context but exactly the same code with exactly the same dockerfile works on linux or mac. Error building docker image: 0: COPY failed: file not found in build context or excluded by .dockerignore: stat : file does not exist I sincerly don't know if I've ever seen something more buggy than docker_registry_image... :-)

andrekiba avatar May 09 '22 15:05 andrekiba

@mavogel could you please help on this? Passing a windows full path like D:\projects\test\src doesn't work. Looking at the attached image this is what I have inside an src folder that is the root folder of my .net core solution.

context

I want this folder as the build context. You can also see that there are CrazyBike.Buy, CrazyBike.Assembler, CrazyBike.Shipper : these are 3 different projects --> 3 different docker images that I want to build. Notice that inside the src I have the related dockerfiles : Dockerfile.buy, Dockerfile.assembler, Dockerfile.shipper. I think each Dockerfile should be inside the related project folder but seems also that docker_registry_image is not able to locate the docker file if it is not placed AT THE ROOT of the build context, can you confirm this? So I tried to put them at the root directly inside the src. This structure works trying to build on mac or linux but not on windows. As mentioned before I receive an error like: Error building docker image: 0: COPY failed: file not found in build context or excluded by .dockerignore: stat CrazyBike.Assembler/CrazyBike.Assembler.csproj: file does not exist You see COPY failed just because inside the Dockerfile this is the first instruction that tries to use the build context. I also tried removing the .dockerignore files but this is not the problem (again, it works on mac or linux with .dockerignore in place). Please can someone help on this?

andrekiba avatar May 10 '22 03:05 andrekiba

In the past 6 months we have improved a lot on the build block, e.g. making path handling OS specific. The build block of the docker_registry_image is now deprecated, please use docker_image!

Closing this for now. If you notice any bugs, please open a new issue! Thanks :)

Junkern avatar Jan 05 '23 13:01 Junkern

@Junkern Has the documentation not been updated to mention these changes? docker_image doesn't seem to push to AWS ECR. At least I can't figure out the combination of docker_image.build.auth_config to make it push with the current documentation. docker_registry_image doesn't mention build block as deprecated.

Apparently the tfplugindocs, which creates the documenation, can only handle a Deprecated parameter when it is for a primitive field. build is a complex field so it does not work. I will update the documentation to include that directly in the description.

We are doing the change to have simpler code (only one resource for building a docker image) and to also be more aligned with the docker cli. In docker there is also a docker build and a docker push command.

You use the docker_image to build your image (basically copy over the build from docker_registry_image) and then use docker_registry_image to push it to ECR:

resource "docker_image" "foo_image" {
  provider = "docker.private"
  name     = "somename"
  build {
   // your build params
  }
}

resource "docker_registry_image" "foo" {
  provider             = "docker.private"
  name                 = docker_image.foo_image.name
  insecure_skip_verify = true
  keep_remotely        = true
}

Junkern avatar Jan 09 '23 09:01 Junkern