DEV Community

Yash Sonawane
Yash Sonawane

Posted on

Deploying a Custom Docker App with Terraform and Docker Compose

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
}
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

modules/ec2/variables.tf

variable "instance_type" {}
variable "key_name" {}
variable "security_group" {}
variable "instance_name" {}
Enter fullscreen mode Exit fullscreen mode

modules/ec2/outputs.tf

output "public_ip" {
  value = aws_instance.web.public_ip
}
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Run the following commands on the instance:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Step 6: Deploy with Terraform

Initialize Terraform

terraform init
Enter fullscreen mode Exit fullscreen mode

Preview the Changes

terraform plan
Enter fullscreen mode Exit fullscreen mode

Apply the Configuration

terraform apply -auto-approve
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)