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

docker_container devices forces resource replacement at all times

Open acolpan opened this issue 6 months ago • 10 comments

Terraform v1.7.2 kreuzwerker/docker v3.0.2

To reproduce this issue:

  1. Locally, provision a docker_container resource using the nested schema for devices (i.e. as below)
devices {
  host_path = "dev/net/tun"
}
  1. Create the resource (i.e. terraform apply --auto-approve)

  2. Right after the step 2, after a container resource is provisioned, please note that, at this moment, the state is not changed anywhere because it's just been provisioned, try the following command to see the state "# forces replacement" further below.

  terraform plan

  - devices { # forces replacement
      - container_path = "dev/net/tun" -> null
      - host_path      = "dev/net/tun" -> null
      - permissions    = "rwm" -> null
    }
  + devices { # forces replacement
      + host_path = "dev/net/tun"
    }

This should not happen! The "terraform plan" should come out as clean in full agreement with the current state of the docker container. Though the devices after the resource is provisioned works as expected, it does not pass the "terraform plan" state check. This probably is an issue with the kreuzwerker/docker provider where it misses the container state for the devices when it inquires the state of the container.

A sample configuration to reproduce this issue: main.tf

Please replace the PATH_TO_CONFIG_DIR and the PATH_TO_DOWNLOADS_DIR with anything that works for you.

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0.2"
    }
  }
}

provider "docker" {
  host = "unix:///var/run/docker.sock"
}

data "docker_registry_image" "qbittorrent" {
  name = "linuxserver/qbittorrent:latest"
}

resource "docker_image" "qbittorrent" {
  name          = data.docker_registry_image.qbittorrent.name
  pull_triggers = [data.docker_registry_image.qbittorrent.sha256_digest]
}

resource "docker_container" "qbittorrent" {
  name = "qbittorrent"
  capabilities {
    add = ["NET_ADMIN"]
  }

  devices {
    host_path = "dev/net/tun"
  }

  ports {
    internal = "6881"
    external = "6881"
  }
  ports {
    internal = "8090"
    external = "8090"
  }
  env = ["PUID=1000", "PGID=1000", "TZ=America/Chicago", "UMASK_SET=022", "WEBUI_PORT=8090"]
  volumes {
    host_path      = "PATH_TO_CONFIG_DIR/config"
    container_path = "/config"
  }
  volumes {
    host_path      = "PATH_TO_DOWNLOADS_DIR/downloads"
    container_path = "/downloads"
  }
  restart = "always"
  image   = docker_image.qbittorrent.image_id
}

Steps to reproduce the issue with the above configuration:

  1. Run the following command to provision the resources
terraform apply --auto-approve
  1. Verify that both the qbittorrent image as well as the container are successfully created, and the container is up and running

  2. Run the following command to verify that the state of the qbittorrent container also looks all good including the devices

terraform state show docker_container.qbittorrent
  1. Run the following command to see the state mismatch due to the devices
terraform plan

If you remove the devices, then the states, terraform's vs docker's, agree but the container does not work as expected due to the missing "dev/net/tun" set by the devices. If you keep the devices, then the container works as expected but the states do not agree, and the terraform wants to replace the container.

acolpan avatar Feb 03 '24 19:02 acolpan