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

如何通过Terraform将ECR中Docker镜像部署到EC2运行Node.js应用

基于Terraform将Node.js Docker镜像从ECR部署到AWS EC2

你已完成Node.js应用Docker镜像推送至AWS ECR的步骤,以下是对提供的Terraform代码的优化与补充,实现完整部署流程:

现有代码

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

# 配置AWS Provider
provider "aws" {
  region  = var.region
  profile = "whatsnxt"
}

resource "tls_private_key" "rsa_4096" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

// 创建用于SSH连接EC2的密钥对
resource "aws_key_pair" "key_pair" {
  key_name   = var.key_name
  public_key = tls_private_key.rsa_4096.public_key_openssh
}

resource "local_file" "private_key" {
  content  = tls_private_key.rsa_4096.public_key_pem
  filename = var.key_name

  provisioner "local-exec" {
    command = "chmod 400 ${var.key_name}"
  }
}

resource "aws_instance" "web" {
  ami                    = var.ami
  instance_type          = var.instance_type
  vpc_security_group_ids = [aws_security_group.main.id]
  key_name               = aws_key_pair.key_pair.key_name
  tags = {
    Name = var.instance_name
  }
  user_data = <<-EOF
                    #!/bin/bash
                    sudo apt-get update -y
                    sudo apt-get install ca-certificates curl gnupg
                    sudo install -m 0755 -d /etc/apt/keyrings
                    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
                    sudo chmod a+r /etc/apt/keyrings/docker.gpg
                    echo \
                    "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
                    "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
                    sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
                    sudo apt-get update -y
                    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
                  EOF  

  root_block_device {
    volume_size           = 15
    delete_on_termination = true
  }
}

data "aws_ecr_image" "service_image" {
    repository_name = "ecr_whatsnxt_repo"
    image_tag       = "dev-v1"
}

resource "aws_default_vpc" "default" {
  tags = {
    Name = "默认Web服务器VPC"
  }
}

resource "aws_security_group" "main" {
  name        = "Web服务器安全组"
  description = "Web服务器安全组规则"
  vpc_id      = aws_default_vpc.default.id

  # ingress {
  #   protocol  = "-1"
  #   self      = true
  #   from_port = 3000
  #   to_port   = 0
  #   cidr_blocks = ["0.0.0.0/0"]
  # }

  ingress {
    from_port   = 80
    to_port     = 3000
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 3000
    to_port     = 3000
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

关键优化与补充步骤

1. 修复SSH私钥生成错误

现有代码中local_file.private_key输出的是公钥,无法用于SSH连接EC2,需修改为私钥:

resource "local_file" "private_key" {
  content  = tls_private_key.rsa_4096.private_key_pem
  filename = "${var.key_name}.pem"

  provisioner "local-exec" {
    command = "chmod 400 ${var.key_name}.pem"
  }
}

2. 完善用户数据:拉取ECR镜像并启动Node.js容器

在现有user_data末尾添加以下内容,实现自动登录ECR、拉取镜像并启动容器:

# 安装AWS CLI用于ECR登录
sudo apt-get install awscli -y

# 自动获取AWS账号ID与区域(需提前添加对应数据源)
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=${var.region}

# 登录ECR仓库
aws ecr get-login-password --region $REGION | sudo docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com

# 拉取指定ECR镜像
sudo docker pull ${data.aws_ecr_image.service_image.repository_url}:${data.aws_ecr_image.service_image.image_tag}

# 启动Node.js容器,映射主机3000端口到容器3000端口
sudo docker run -d --name node-app -p 3000:3000 ${data.aws_ecr_image.service_image.repository_url}:${data.aws_ecr_image.service_image.image_tag}

# 设置容器开机自启
sudo docker update --restart=always node-app

同时需在代码中添加自动获取账号ID的数据源:

data "aws_caller_identity" "current" {}

3. 优化安全组规则

可将现有两个TCP入站规则合并,简化配置:

ingress {
  from_port   = 80
  to_port     = 3000
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
}

4. 补充变量定义(创建variables.tf文件)

添加以下内容避免变量未定义报错:

variable "region" {
  description = "AWS区域"
  type        = string
  default     = "us-east-1" # 替换为你的目标区域
}

variable "key_name" {
  description = "EC2密钥对名称"
  type        = string
  default     = "ec2-node-key"
}

variable "ami" {
  description = "Ubuntu系统AMI ID(需匹配你的区域)"
  type        = string
  default     = "ami-0c7217cdde317cfec" # Ubuntu 22.04 us-east-1,需按需替换
}

variable "instance_type" {
  description = "EC2实例类型"
  type        = string
  default     = "t2.micro"
}

variable "instance_name" {
  description = "EC2实例名称标签"
  type        = string
  default     = "nodejs-web-server"
}

5. 添加输出配置(创建outputs.tf文件)

方便部署后直接获取EC2公网IP与SSH命令:

output "ec2_public_ip" {
  description = "EC2实例公网IP"
  value       = aws_instance.web.public_ip
}

output "ssh_command" {
  description = "SSH连接EC2实例的命令"
  value       = "ssh -i ${var.key_name}.pem ubuntu@${aws_instance.web.public_ip}"
}

完整部署流程

  1. 确保AWS CLI已配置好whatsnxt对应的凭证
  2. 创建上述variables.tf与outputs.tf文件
  3. 执行terraform init初始化Terraform环境
  4. 执行terraform plan预览部署计划
  5. 执行terraform apply确认并完成部署

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:45:56