hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.61k stars 4.65k forks source link

Cannot use public Docker images with new 'docker_image_name' argument, without using 'docker_registry_url' #22652

Open Erzangel opened 1 year ago

Erzangel commented 1 year ago

Is there an existing issue for this?

Community Note

Terraform Version

1.4.6

AzureRM Provider Version

3.65.0

Affected Resource(s)/Data Source(s)

azurerm_linux_web_app

Terraform Configuration Files

resource "azurerm_resource_group" "default" {
  name     = "example-tf-webapp"
  location = "France Central"
}

resource "azurerm_service_plan" "app_service_plan" {
  name                = "example-webapp-asp"
  resource_group_name = azurerm_resource_group.default.name
  location            = azurerm_resource_group.default.location
  os_type             = "Linux"
  sku_name            = "B1"
}

resource "azurerm_linux_web_app" "this" {
  name                = "example-webapp"
  resource_group_name = azurerm_resource_group.default.name
  location            = azurerm_resource_group.default.location
  service_plan_id     = azurerm_service_plan.app_service_plan.id
  site_config {
    always_on         = true
    ftps_state        = "FtpsOnly"
    app_command_line  = ""
    worker_count      = 1
    use_32_bit_worker = false
    health_check_path = ""
    application_stack {
      docker_image_name        = "nginx:latest"
    }
  }
  https_only                = true
  client_affinity_enabled   = false
}

Debug Output/Panic Output

Terraform successfully applies, but the webapp does not work.

When inspecting logs in the Deployment Center, we see the following:

2023-07-24T10:07:42.988Z INFO - Pulling image: /nginx:latest
2023-07-24T10:07:43.006Z ERROR - DockerApiException: Docker API responded with status code=BadRequest, response={"message":"invalid reference format"}

Expected Behaviour

The image from the default Docker registry (https://docker.io, which is the one used on images hosted on https://hub.docker.com) should be pulled by default.

Note: This was the case when using the old docker_image variable.

Actual Behaviour

The image cannot be pulled, and Docker returns an "invalid reference format" error due to the image starting with an unnecessary /.

This is most likely caused by this function in main/internal/services/appservice/helpers/fx_strings.go, which simply puts a / before the image name when no docker registry URL is used.

It is possible to fix this behavior by explicitly setting the docker_registry_url parameter to"https://docker.io", which is the default used by Docker.

Steps to Reproduce

  1. terraform apply
  2. Try to access the webapp on Azure, and notice the application error
  3. Check that the Docker pull failed in the Deployment Center -> Logs

Important Factoids

No response

References

https://github.com/hashicorp/terraform-provider-azurerm/blob/main/internal/services/appservice/helpers/fx_strings.go#L289

xiaxyi commented 1 year ago

Thanks @Erzangel for raising this issue, have you tried to put the docker_registry_url property in the config like below:

site_config {
    application_stack {
      docker_image_name   = "nginx:latest"
      docker_registry_url = "https://index.docker.io"
    }
  }
Erzangel commented 1 year ago

This does indeed work. I was however surprised to have to explicitly specify the default Docker endpoint, which was not required for the fields used in previous versions of azurerm, or for Docker itself.

As I upgraded from 3.54 to 3.65, I missed that the docker_registry_url was required along with docker_image_name, as specified here.

However, I am wondering whether or not this docker_registry_url should be required to reach the default Docker registry. Just like how you can use Docker's docker pull appsvcsample/static-site:latest without explicitly specifying a registry, it is intuitive to do the same with any Docker-related component.

I am not familiar with Go, but it seems like the necessary adjustments would need to be performed on this function: https://github.com/hashicorp/terraform-provider-azurerm/blob/main/internal/services/appservice/helpers/fx_strings.go#L289

xiaxyi commented 1 year ago

Thanks @Erzangel for the feedback, actually, if you try creating the docker based web app in the Azure portal, you will need to choose the registry: image The docker hub is not the default one, at least to my understanding, please feel free to correct me if there is any misunderstanding.

In the previous provider, the registry URL is exposed in app_setting and it looks like:

resource "azurerm_linux_web_app" "test" {
  name                = "example-web-app"
  location            = azurerm_resource_group.test.location
  resource_group_name = azurerm_resource_group.test.name
  service_plan_id     = azurerm_service_plan.test.id

  app_settings = {
    "DOCKER_REGISTRY_SERVER_URL"          = "https://index.docker.io"
    "DOCKER_REGISTRY_SERVER_USERNAME"     = ""
    "DOCKER_REGISTRY_SERVER_PASSWORD"     = ""
    "WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"
  }

  site_config {
    application_stack {
      docker_image     = "example"
      docker_image_tag = "example tag"
    }
  }
}

In Terraform azurerm 3.0 provider, to avoid any breaking change, we are not making the registry url as a required field, but in 4.0 provider, it will be a required field.

Feel free to let me know if you have any question.

akarimkhanitrk commented 1 week ago

I am also running to issue with with diffrent error:

│ "site_config.0.application_stack.0.dotnet_version": only one of
│ `site_config.0.application_stack.0.docker_image_name,site_config.0.application_stack.0.dotnet_version,site_config.0.application_stack.0.go_version,site_config.0.application_stack.0.java_version,site_config.0.application_stack.0.node_version,site_config.0.application_stack.0.php_version,site_config.0.application_stack.0.python_version,site_config.0.application_stack.0.ruby_version`
│ can be specified, but `site_config.0.application_stack.0.docker_image_name,site_config.0.application_stack.0.node_version` were specified.
resource "azurerm_linux_web_app" "app" {
  for_each = { for app in var.web_app : app.name => app if var.create }
  name                                     = "app-${each.value.name}-${var.name_prefix}"
  resource_group_name                      = var.resource_group_name
  location                                 = var.location
  service_plan_id                          = azurerm_service_plan.web_app[each.value.name].id
  https_only                               = each.value.https_only
  client_certificate_enabled               = each.value.client_certificate_enabled
  client_certificate_mode                  = each.value.client_certificate_mode
  ftp_publish_basic_authentication_enabled = each.value.ftp_publish_basic_authentication_enabled
  app_settings                             = each.value.app_settings
  virtual_network_subnet_id                = var.shared_appservice_subnet_id

  identity {
    type = "SystemAssigned"
  }

  dynamic "sticky_settings" {
    for_each = each.value.sticky_settings != null ? [each.value.sticky_settings] : []
    content {
      app_setting_names       = sticky_settings.value.app_setting_names
      connection_string_names = sticky_settings.value.connection_string_names
    }
  }

  site_config {
    ...
    application_stack {
      node_version = "18-lts"
      docker_image_name        = "samples/nginx:latest"
      docker_registry_url      = "https://xxx.azurecr.io"
      docker_registry_username = "xxx"
      docker_registry_password = "xxx"
    }
}