Hello everyone.
I have a terraform project that uses the data resource to look up an AMI that is present in my AWS account.
I want to add LocalStack to the terraform project for local development and testing. Since LS emulates AWS services, I am not able to share/copy the AMI with LS. Moreover, I am unable to share the EBS block storage snapshot with LS.
Do you perhaps have any recommendations, suggestions to resolve this ?
This is a static archive of the LocalStack Discuss forum that was taken as of January 2025 and is read only.
Hi @jnax09,
Please have a look at our documentation Elastic Compute Cloud (EC2) | Docs (localstack.cloud),
Base Images
LocalStack uses a naming scheme to recognise and manage the containers and images associated with it. Containers are named
localstack-ec2.<InstanceId>, while images are taggedlocalstack-ec2/<AmiName>:<AmiId>.The Docker backend treats Docker images with the above naming scheme as AMIs. For example, the following command can be used to associate the Ubuntu Focal image as
ami-000001.$ docker tag ubuntu:focal localstack-ec2/ubuntu-focal-ami:ami-000001These Docker-backed AMIs have the resource tag
ec2_vm_manager:dockerand can be listed with the following command:$ awslocal ec2 describe-images --filters Name=tag:ec2_vm_manager,Values=dockerAll other AMIs are ‘mocked’ and are based off the community edition of LocalStack. Attempting to launch Dockerised instances with these AMIs will return
InvalidAMIID.NotFounderror.
Thank for your reply @Marcel
This indeed works well with “public” AMIs/images. In my case, however, the AMI is a custom one and it is privately owned by my AWS account.
Could you please explain the steps you are taking?
In my terraform project, I have a data resource that looks up an AMI.
data "aws_ami" "centos5_ami" {
most_recent = true
owners = ["*********"]
filter {
name = "image-id"
values = ["ami-***********"]
}
}
As you can see the AMI is privately owned by my AWS.
I start Localstack using the following docker compose file:
version: "3.8"
services:
localstack:
container_name: localstack
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
environment:
- MAIN_DOCKER_NETWORK=localstack_default
- DEBUG=${DEBUG-}
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
networks:
- localstack_default
networks:
localstack_default:
name: localstack_default
When I proceed to run terraform plan, it is successful. However, upon running terraform apply, I get an error message about the AMI not found, which makes sense.
I don’t know whether it is possible but I have been trying to find a way to copy/share the AMI with Localstack. However, since Localstack enables us to emulate AWS services locally, I have been having a hard time figuring it out.
I hope that makes sense.
You will have to download the image on your local machine and tag it like I mentioned it in my previous comment.
Okay I will find a way to download the AMI locally and tag it accordingly. I will let you know how that goes.
Hey @Marcel. I have given this a try on a public AMI.
Here is what I have done:
- I pulled the amazonlinux image:
docker pull amazonlinux - then I tagged it accordingly:
docker tag amazonlinux localstack-ec2/amazonlinux-ami:ami-000001
In my terraform project, I made the following change.
FROM:
data "aws_ami" "amazonlinux" {
most_recent = true
owners = ["137112412989"]
filter {
name = "name"
values = ["amzn2-ami-hvm-2.0*-x86_64-gp2"]
}
}
resource "aws_instance" "bastion" {
ami = "data.aws_ami.amazonlinux.id"
source_dest_check = false
instance_type = var.instance_type
subnet_id = var.subnet_id
key_name = var.key_name
vpc_security_group_ids = compact(split(",", var.security_groups))
monitoring = true
associate_public_ip_address = true
user_data = file(format("%s/user_data.sh", path.module))
root_block_device {
encrypted = true
}
TO:
resource "aws_instance" "bastion" {
ami = "ami-000001"
source_dest_check = false
instance_type = var.instance_type
subnet_id = var.subnet_id
key_name = var.key_name
vpc_security_group_ids = compact(split(",", var.security_groups))
monitoring = true
associate_public_ip_address = true
user_data = file(format("%s/user_data.sh", path.module))
root_block_device {
encrypted = true
}
Upon running terraform apply, I get the following error which I haven’t figured not yet.
Error: creating EC2 Instance: MissingParameter: The request must contain the parameter size or snapshotId
status code: 400, request id: 37720c40-e508-49eb-9540-b17bec8ce11e
on modules/vpc/stack-bastion/main.tf line 67, in resource "aws_instance" "bastion":
67: resource "aws_instance" "bastion" {
Upon describing the ami-000001, this is what is returned:
{
"Images": [
{
"Architecture": "arm64",
"CreationDate": "2023-08-07T19:40:41.794331038Z",
"ImageId": "ami-000001",
"ImageLocation": "docker",
"ImageType": "machine",
"Public": true,
"KernelId": "None",
"OwnerId": "000000000000",
"RamdiskId": "ari-1a2b3c4d",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"Ebs": {
"DeleteOnTermination": false,
"SnapshotId": "snap-6d53f169",
"VolumeSize": 15,
"VolumeType": "standard"
}
}
],
"Description": "None",
"Hypervisor": "xen",
"ImageOwnerAlias": "amazon",
"Name": "amazonlinux-ami",
"RootDeviceName": "/dev/sda1",
"RootDeviceType": "standard",
"Tags": [
{
"Key": "ec2_vm_manager",
"Value": "docker"
}
],
"VirtualizationType": "None"
}
]
}
What do you think I am missing or getting wrong ?
Hi @jnax09,
I have tried it and had to remove monitoring as it is not implemented. Otherwise, it got deployed.
As you mentioned, steps before:
$ docker pull amazonlinux
$ docker tag amazonlinux localstack-ec2/amazonlinux-ami:ami-000002
$ awslocal ec2 describe-images --filters Name=tag:ec2_vm_manager,Values=docker | grep ImageId
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.0.0/24"
}
resource "aws_security_group" "security_group" {
vpc_id = aws_vpc.vpc.id
}
resource "aws_key_pair" "deployer" {
key_name = "deployer-key"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 email@example.com"
}
resource "aws_instance" "bastion" {
ami = "ami-000002"
source_dest_check = false
instance_type = "t2.micro"
subnet_id = aws_subnet.subnet.id
key_name = aws_key_pair.deployer.id
vpc_security_group_ids = [aws_security_group.security_group.id]
associate_public_ip_address = true
user_data = file(format("%s/user_data.sh", path.module))
root_block_device {
encrypted = true
volume_size = 8
}
}
Thanks @Marcel. Besides removing monitoring, I see that you’ve added volume_size
Yes, I forgot to mention that it was necessary to add that.
Info in the documentation: AWS::EC2::Instance Ebs - AWS CloudFormation (amazon.com)
Indeed. Thanks @Marcel.
I have another blocker but unrelated to this. I will create another discussion for it.