kreuzwerker / terraform-provider-docker

Terraform Docker provider
Mozilla Public License 2.0
613 stars 187 forks source link

Ports on stopped container force replacement #77

Open mavogel opened 3 years ago

mavogel commented 3 years ago

This issue was originally opened by @Temikus as https://github.com/hashicorp/terraform-provider-docker/issues/211. It was migrated here as a result of the community provider takeover from @kreuzwerker. The original body of the issue is below.


Looks like this may be a reoccurrence of https://github.com/hashicorp/terraform/issues/19294

λ terraform -v
Terraform v0.12.12
+ provider.docker v2.5.0

Starting with a recent upgrade of the provider (sadly I do not remember which one I've upgraded from) docker provider started forcing recreation of containers that have ports published.

Repro:

1) Fire up this example container:

resource "docker_container" "btsync" {
       image = "resilio/sync"
       name = "btsync"
       capabilities {
         add  = ["NET_ADMIN"]
       }
       ports {
              internal = 8888
              external = 8888
       }
       ports {
              internal = 55555
       }
       log_driver = "json-file"
       log_opts = {
              max-size = "10m"
              max-file = 3
       }
       volumes {
              host_path = "/etc/localtime"
              container_path = "/etc/localtime"
              read_only = true
              }
       restart= "on-failure"
       max_retry_count = 3
       # Do not ensure that the container is running
       must_run="false"
}

2) terraform apply 3) ssh onto the host 4) docker kill btsync 5) terraform plan EXPECTED BEHAVIOUR:

Note that this doesn't happen with another container that's also stopped but doesn't have ports defined, here's the example config:

resource "docker_container" "speedtest_exporter" {
  image = "nlamirault/speedtest_exporter"
  name = "speedtest"
  hostname = "speedtest"

  networks_advanced {
    name = docker_network.homelab.name
    aliases = ["speedtest", "speedtest.docker"]
  }

  volumes {
    host_path = "/etc/localtime"
    container_path = "/etc/localtime"
    read_only = true
  }

  restart= "on-failure"
  max_retry_count = 3
  # Do not ensure that the container needs to be running
  must_run="false"
}
github-actions[bot] commented 3 years ago

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] commented 3 years ago

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.

Junkern commented 1 year ago

We are currently reading the ports data from the container.NetworkSettings.Ports, which is {} when the container has exited. However, we can get the full port information from HostConfig.PortBindings, but we still have a problem: The ports attribute of the docker_container resource is of type TypeList, which is a "ordered collection of items". We cannot map the order between the ports and the data from HostConfig.PortBindings

That could be solved, though, by changing the type of ports to TypeSet ("unordered collection of items"). This change is also mentioned inside https://github.com/kreuzwerker/terraform-provider-docker/issues/88

And the nice thing is: This is not a breaking change, because an ordered list is actually a subtype of an unordered list, so this should not create an issues when upgrading.

Hence, the next step is to change the ports type, then we can fix this issue