You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Terraform Cloud时,能否让null_resource在本地执行脚本?

Terraform Cloud中Docker镜像构建推送的问题与解决方案

问题背景

我通过Terraform Cloud结合Terraform开展基础设施即代码(IaC)工作,目标是创建Azure Container App。原本计划用带有local-exec provisioner的null_resource执行脚本,完成Docker镜像构建并推送到Azure Container Registry(ACR),但由于Terraform Cloud运行在远程环境,脚本无法按预期执行。

现有Terraform配置

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "East US"
}

resource "azurerm_container_registry" "acr" {
  name                = "myUniqueACRName"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  sku                 = "Basic"
  admin_enabled       = true
}

resource "null_resource" "deploy_image_acr" {
  triggers = {
    deploy_time = timestamp()
  }

  provisioner "local-exec" {
    command = "./deploy_to_acr.sh ${var.client_id} ${var.client_secret} ${var.tenant_id} ${var.subscription_id} ${azurerm_container_registry.acr.name} ${var.image_name}"
  }

  depends_on = [azurerm_container_registry.acr]
}

配套Bash脚本

#!/bin/bash

# Login to Azure with the Service Principal
az login --service-principal -u "$1" -p="$2" --tenant "$3"

# Set the desired subscription
az account set --subscription "$4"

# Remove all existing images
for repo in $(az acr repository list --name "$5" --output tsv); do
  az acr repository delete --name "$5" --repository "$repo" --yes
done

# Build and push the new image
docker build -t <image_name> . 

az acr login --name $5

docker tag <image_name> $5.azurecr.io/<image_name>

docker push $5.azurecr.io/<image_name>

核心问题

在Terraform Cloud中执行该配置时,local-exec provisioner无法正常工作,因为它的设计初衷是在Terraform运行的本地机器上执行,而Terraform Cloud默认使用远程执行环境。

我有两个问题:

  1. 使用Terraform Cloud时,是否可以让null_resource或其他资源中定义的脚本在我的本地机器上执行?
  2. 如果无法本地执行,我可以采用哪些替代方法在部署流程中运行Docker命令或脚本?

解决方案

问题1:能否让脚本在本地机器执行?

可以,有两种可行方式:

  • 切换到Terraform Cloud本地执行模式:在工作区设置中,将执行模式从默认的"远程执行"改为"本地执行"。这种模式下,Terraform Cloud仅负责存储状态文件、提供变量管理和触发执行,实际的terraform apply会在你的本地机器上运行,local-exec自然会在本地执行脚本。
  • 本地运行Terraform并连接Terraform Cloud状态后端:保持工作区为远程执行模式,但在本地机器上运行terraform init(配置Terraform Cloud为状态后端)和terraform apply。此时local-exec会在你的本地环境执行,状态文件仍会同步到Terraform Cloud。

问题2:无法本地执行时的替代方案

如果必须使用Terraform Cloud的远程执行环境,推荐以下几种替代方法:

1. 使用Azure Container Registry任务(ACR Tasks)

直接利用ACR的内置能力构建并推送镜像,无需依赖本地或Terraform Cloud环境的Docker。通过Terraform的azurerm_container_registry_task资源定义构建任务,ACR会在云端完成镜像构建:

resource "azurerm_container_registry_task" "image_build" {
  name                = "image-build-task"
  container_registry_name = azurerm_container_registry.acr.name
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location

  platform {
    os           = "Linux"
    architecture = "amd64"
  }

  source {
    type = "Local"
    # 如果代码在Git仓库,可以用Git类型并指定仓库地址
    context = filebase64("path/to/your/docker/context")
  }

  docker_step {
    dockerfile_path = "Dockerfile"
    image_names     = ["${azurerm_container_registry.acr.name}.azurecr.io/${var.image_name}:latest"]
    push_enabled    = true
  }

  trigger {
    base_image_trigger {
      name = "base-image-update"
      type = "Runtime"
    }
  }
}

创建任务后,可以通过azurerm_container_registry_task_run资源手动触发构建,或者设置自动触发(比如代码提交、基础镜像更新)。

2. 整合CI/CD流水线

将镜像构建推送环节从Terraform流程中分离,交给专门的CI/CD工具(如GitHub Actions、Azure DevOps Pipelines)处理:

  • 第一步:CI/CD流水线拉取代码,构建Docker镜像并推送到ACR;
  • 第二步:触发Terraform Cloud执行基础设施部署,直接引用ACR中已存在的镜像部署Azure Container App。
    这种方式职责分离,更符合IaC最佳实践,也避免了Terraform环境依赖Docker的问题。

3. 使用自定义Terraform Cloud Runner

Terraform Cloud允许使用自定义Runner,你可以创建包含Docker daemon和Azure CLI的自定义镜像,将Runner部署在自己的环境或云端。这样远程执行环境就具备了运行Docker命令的能力,原有的local-exec脚本就能正常执行。

4. 使用Terraform Docker Provider

通过Terraform的docker provider直接管理镜像构建和推送,但需要确保Terraform Cloud环境中Docker daemon可用(通常需要自定义Runner):

provider "docker" {
  host = "unix:///var/run/docker.sock"
  # 如果需要通过ACR认证,可以配置registry_auth
  registry_auth {
    address = "${azurerm_container_registry.acr.name}.azurecr.io"
    username = azurerm_container_registry.acr.admin_username
    password = azurerm_container_registry.acr.admin_password
  }
}

resource "docker_image" "app" {
  name         = "${azurerm_container_registry.acr.name}.azurecr.io/${var.image_name}:latest"
  build {
    context = "./path/to/docker/context"
    dockerfile = "Dockerfile"
  }
}

resource "docker_registry_image" "app" {
  name = docker_image.app.name
  image_id = docker_image.app.id
}

内容的提问来源于stack exchange,提问作者Hiten Samalia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:15:23