Introduction
In this blog, we will walk through deploying an AWS EC2 instance using Terraform Modules and setting up a custom Dockerized multi-container application using Docker Compose. This is a great project for those looking to enhance their Terraform, Docker, and AWS skills while automating infrastructure provisioning.
Prerequisites
Before we begin, ensure you have:
✅ Terraform installed → Download Here
✅ AWS CLI installed and configured → Run aws configure
✅ An AWS Key Pair (to SSH into the instance)
✅ A Dockerized custom application (a simple web app)
Project Overview
We will create:
✔️ An EC2 instance with a security group allowing SSH and HTTP traffic
✔️ Terraform Modules for better reusability
✔️ Docker installation via Terraform's user_data
✔️ A custom multi-container application using Docker Compose
Step 1: Define the Terraform Provider
Create a file named provider.tf
and specify AWS as the provider:
provider "aws" {
region = "us-east-1" # Change this as needed
}
Step 2: Create a Terraform Module for EC2 Instance
Create a new folder modules/ec2
and inside it, create main.tf
, variables.tf
, and outputs.tf
files.
modules/ec2/main.tf
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI (update if needed)
instance_type = var.instance_type
key_name = var.key_name
security_groups = [var.security_group]
user_data = file("${path.module}/install_docker.sh")
tags = {
Name = var.instance_name
}
}
modules/ec2/variables.tf
variable "instance_type" {}
variable "key_name" {}
variable "security_group" {}
variable "instance_name" {}
modules/ec2/outputs.tf
output "public_ip" {
value = aws_instance.web.public_ip
}
Step 3: Define Security Group Module
Create a new folder modules/security_group
and define security rules.
modules/security_group/main.tf
resource "aws_security_group" "ec2_sg" {
name = "terraform-sg"
description = "Allow SSH and HTTP"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Allows SSH access
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Allows HTTP access
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] # Allows all outbound traffic
}
}
Step 4: Install Docker and Docker Compose
Create a shell script install_docker.sh
inside modules/ec2
:
#!/bin/bash
sudo yum update -y
sudo yum install docker -y
sudo systemctl start docker
sudo systemctl enable docker
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
Step 5: Deploy a Multi-Container App using Docker Compose
Create a docker-compose.yml
file on the EC2 instance after provisioning:
version: '3.8'
services:
app:
image: my-custom-app:latest
ports:
- "5000:5000"
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydb
Run the following commands on the instance:
docker-compose up -d
Step 6: Deploy with Terraform
Initialize Terraform
terraform init
Preview the Changes
terraform plan
Apply the Configuration
terraform apply -auto-approve
Terraform will output the public IP address of the instance.
Step 7: Access the Deployed Application
Once the deployment is complete, open your browser and visit:
http://<your-instance-ip>:5000
Your custom web app should now be running successfully! 🎉
Step 8: Destroy the Resources (Optional)
To clean up everything and avoid AWS charges, run:
terraform destroy -auto-approve
Conclusion
In this blog, we:
✅ Used Terraform Modules for better reusability
✅ Deployed an EC2 instance with Terraform
✅ Installed Docker and Docker Compose
✅ Ran a custom multi-container application
✅ Allowed SSH & HTTP traffic with a Security Group
✅ Outputted the Public IP for easy access
This is a major step towards Infrastructure as Code (IaC) and automating DevOps workflows.
💡 Next Steps:
- Add more containers to the application
- Implement auto-scaling with AWS ECS
- Use Terraform remote state for better scalability
Have questions or suggestions? Drop them in the comments! 🚀
Top comments (0)