Introduction:
Docker has revolutionized the way applications are deployed and run, providing a lightweight and consistent environment across different platforms. Amazon EC2, a popular cloud computing service, allows users to deploy virtual servers in the cloud. In this guide, we'll walk you through the process of pulling a Docker image from Docker Hub and running a container on an EC2 instance using Infrastructure as Code (IaC).
Prerequisites:
Before you begin, ensure you have the following prerequisites in place:
- An AWS account with the necessary permissions to create EC2 instances.
- The AWS CLI installed on your local machine.
- Terraform installed on your local machine.
Step 1: Create an EC2 Key Pair
To securely access your EC2 instance, you'll need an SSH key pair. If you don't have one, create a new key pair using the AWS Management Console or the AWS CLI.
aws ec2 create-key-pair --key-name YourKeyName --query 'KeyMaterial' --output text > YourKeyName.pem
chmod 400 YourKeyName.pem
Alternatively, you can use ssh-keygen to create the key-pair on your computer.
Generate SSH key pair
ssh-keygen -t rsa -b 2048 -f YourKeyName
Set appropriate permissions
chmod 400 YourKeyName
Replace YourKeyName with a preferred name for your key pair.
2. Create a main.tf file
touch main.tf
Update main.tf
Modify the aws_instance resource block in main.tf to include the key_name parameter:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-west-2"
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr_block
tags = {
"Name" = "Production ${var.main_vpc_name}"
}
}
# Create a subnet
resource "aws_subnet" "web" {
vpc_id = aws_vpc.main.id
cidr_block = var.web_subnet
availability_zone = var.subnet_zone
tags = {
Name = "Web Subnet"
}
}
resource "aws_internet_gateway" "my_web_igw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.main_vpc_name} IGW"
}
}
resource "aws_default_route_table" "main_vpc_default_rt" {
default_route_table_id = aws_vpc.main.default_route_table_id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.my_web_igw.id
}
tags = {
Name = "my-default-rt"
}
}
resource "aws_default_security_group" "default_sec_group" {
vpc_id = aws_vpc.main.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 5000
to_port = 5000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1" # any protocol
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
"Name" = "Default Security Group"
}
}
# Create a new Key Pair
resource "aws_key_pair" "terraform_ssh_pair" {
key_name = "terraform_rsa"
public_key = file(var.ssh_public_key)
}
data "aws_ami" "latest_amazon_linux2" {
owners = [ "amazon" ]
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-kernel-*-x86_64-gp2"]
}
filter {
name = "architecture"
values = [ "x86_64" ]
}
}
resource "aws_instance" "web-server" {
ami = data.aws_ami.latest_amazon_linux2.id
instance_type = "t2.micro"
subnet_id = aws_subnet.web.id
vpc_security_group_ids = [aws_default_security_group.default_sec_group.id]
associate_public_ip_address = true
user_data = file("script.sh")
key_name = aws_key_pair.terraform_ssh_pair.key_name
tags = {
"Name" : "My Public Web Server"
}
}
The user_data is contained in script.sh below. This installs an apache server (to confirm if everything worked correctly). It also installs docker, terraform and runs an nginx docker container as well. You can modify the script to suit your requirements.
#!/bin/bash
# update vm and install server
sudo yum -y update && sudo yum -y install httpd
sudo systemctl start httpd && sudo systemctl enable httpd
sudo echo "<h1>Deployed via Terraform</h1>" > /var/www/html/index.html
# install terraform
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum -y install terraform
sudo touch ~/.bashrc
sudo terraform -install-autocomplete
# install docker
sudo yum -y install docker
sudo systemctl start docker
sudo amazon-linux-extras install docker
sudo service docker start
sudo usermod -aG docker ec2-user
sudo chkconfig docker on
sudo yum install -y git
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo systemctl enable docker
sudo docker run -d -p 8080:80 nginx
3. Create a variables.tf file
touch variables.tf
Update variables.tf
variable "vpc_cidr_block" {
type = string
description = "cidr block for the main vpc"
default = "10.0.0.0/16"
}
variable "web_subnet" {
type = string
description = "cidr block for the web subnet"
default = "10.0.10.0/24"
}
variable "subnet_zone" {
type = string
description = "availability zone for subnet zone"
# subnet_zone was set as environment variable
}
variable "ssh_public_key" {
type = string
description = "public key that permits ssh connection to the ec2 instance"
}
variable "main_vpc_name" {
type = string
description = "name of the main vpc"
}
variable "my_public_ip" {
description = "my public ip address"
}
4. Create an output.tf file
touch output.tf
Update the output.tf file with the configuration below which provides the public IP address of the instance upon creation.
output "public_ip" {
description = "The public IP address of the EC2 instance."
value = aws_instance.web-server.public_ip
}
5. Usage
- Follow the previous steps to clone the repository, customize configurations, and run terraform apply.
- After the Terraform apply, you will find the public IP address and the path to the local SSH private key in the outputs.
- Use the following command to SSH into the EC2 instance:
ssh -i YourKeyName ec2-user@<public_ip>
Replace YourKeyName with the name of your private key file and with the actual public IP address.
Now, you can securely access your EC2 instance using the generated SSH key pair.
Top comments (0)