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-000001
These Docker-backed AMIs have the resource tag
ec2_vm_manager:docker
and can be listed with the following command:$ awslocal ec2 describe-images --filters Name=tag:ec2_vm_manager,Values=docker
All other AMIs are ‘mocked’ and are based off the community edition of LocalStack. Attempting to launch Dockerised instances with these AMIs will return
InvalidAMIID.NotFound
error.
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.