DEV Community

Yash Sonawane
Yash Sonawane

Posted on

1 1 1 1 1

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! 🚀

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs