如何通过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}" }
完整部署流程
- 确保AWS CLI已配置好
whatsnxt对应的凭证 - 创建上述
variables.tf与outputs.tf文件 - 执行
terraform init初始化Terraform环境 - 执行
terraform plan预览部署计划 - 执行
terraform apply确认并完成部署
内容的提问来源于stack exchange,提问作者kittu
相关产品推荐
相关产品推荐

