Skip to content

Instantly share code, notes, and snippets.

@jmlrt
Last active March 14, 2022 23:01
Show Gist options
  • Save jmlrt/1b8dd5b84b88de52a8f776fb62104a63 to your computer and use it in GitHub Desktop.
Save jmlrt/1b8dd5b84b88de52a8f776fb62104a63 to your computer and use it in GitHub Desktop.
docker instance quick provisioning

Docker EC2 instance provisioning

Provision EC2 instance in the defined AWS region and with Docker installed

Requirements

  • Make
  • Ansible & Terraform (or Docker to use these tools inside containers)
  • AWS Command Line Interface (pip install awscli)
  • AWS credentials with the permission to provision EC2 instance, Security Group & IAM instance role

Usage

make provisioning region="us-east-1"
make destroy region="us-east-1"
[defaults]
callback_whitelist=dense
host_key_checking=False
retry_files_enabled=False
deprecation_warnings=False
#!/bin/sh
#
# Retrieve the public IP used to reach Internet in JSON format
ip=$(curl http://checkip.amazonaws.com)
echo "{\"ip\": \"${ip}\"}"
.PHONY : provisioning destroy
SHELL := /bin/bash
# Default commands for Ansible and Terraform using Docker containers
# To use local Ansible and Terraform binaries: make all ANSIBLE_CMD=ansible-playbook TERRAFORM_CMD=terraform
ANSIBLE_CMD := docker run --rm --env="USER_ID=$(shell id -u)" --volume $(shell pwd):/tmp --workdir /tmp ansible/ansible:latest ansible-playbook
TERRAFORM_CMD := docker run --rm --user $(shell id -u) --volume $(shell pwd):/root --workdir /root/ hashicorp/terraform:0.11.11
# Default region used to launch EC2 instance
region := us-east-1
provisioning:
$(TERRAFORM_CMD) init
$(TERRAFORM_CMD) apply -auto-approve -var "region=$(region)"
$(ANSIBLE_CMD) --private-key=.ssh/id_rsa --inventory=hosts provisioning.yml
destroy:
$(TERRAFORM_CMD) init
$(TERRAFORM_CMD) destroy --auto-approve -var "region=$(region)"
---
- hosts: ec2-instance
remote_user: centos
gather_facts: no
become: yes
vars:
users:
- github-user-1
- github-user-2
tasks:
- name: ensure ssh is started
become: false
local_action:
module: wait_for
host={{ ansible_host }}
port=22
delay=10
- name: ensure ssh public keys are deployed
authorized_key:
user: "{{ ansible_user }}"
state: present
key: "https://github.com/{{ item }}.keys"
with_items: "{{ users }}"
- name: ensure docker is installed
yum:
name: docker
state: present
- name: ensure docker is started
systemd:
name: docker
state: started
- name: ensure epel repository is enabled
yum:
name: epel-release
state: present
update_cache: yes
- name: ensure pip is installed
yum:
name: python-pip
state: present
- name: ensure docker python library is installed
pip:
name: docker
state: present
- name: ensure awscli is installed
pip:
name: awscli
state: present
provider "aws" {
region = "${var.region}"
}
# Generate SSH private key used to configure EC2 instance
resource "tls_private_key" "test" {
algorithm = "RSA"
rsa_bits = 4096
}
# Copy SSH private key to disk
resource "local_file" "private_key" {
content = "${tls_private_key.test.private_key_pem}"
filename = ".ssh/id_rsa"
provisioner "local-exec" {
command = "chmod 600 .ssh/id_rsa"
}
}
resource "aws_key_pair" "test" {
key_name = "test-key"
public_key = "${tls_private_key.test.public_key_openssh}"
}
resource "aws_instance" "test" {
ami = "${data.aws_ami.centos.id}"
instance_type = "t3.small"
key_name = "${aws_key_pair.test.key_name}"
vpc_security_group_ids = ["${aws_security_group.allow_ssh.id}"]
associate_public_ip_address = "true"
root_block_device {
volume_type = "gp2"
volume_size = "8"
delete_on_termination = true
}
tags = "${local.tags}"
volume_tags = "${local.tags}"
# Generate Ansible Inventory used to configure EC2 instance
provisioner "local-exec" {
command = "echo test-instance ansible_host=${aws_instance.test.public_dns} > hosts"
}
}
# Allow SSH connection from the instance which is running Terraform
resource "aws_security_group" "allow_ssh" {
name = "allow_ssh"
description = "Allow SSH traffic"
vpc_id = "${data.aws_vpc.default.id}"
ingress {
from_port = 22
to_port = 22
protocol = "TCP"
cidr_blocks = ["${data.external.public_ip.result.ip}/32"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = "${local.tags}"
}
variable "region" {
default = "us-east-1"
}
data "aws_vpc" "default" {
default = true
}
data "aws_subnet_ids" "default" {
vpc_id = "${data.aws_vpc.default.id}"
}
# Get latest CentOS AMI
data "aws_ami" "centos" {
most_recent = true
filter {
name = "owner-alias"
values = ["aws-marketplace"]
}
filter {
name = "name"
values = ["CentOS Linux 7 *"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
# TODO: replace it by http provider (cf. https://github.com/terraform-providers/terraform-provider-aws/blob/master/examples/eks-getting-started/workstation-external-ip.tf)
# Get localhost public IP used to connect to the EC2 instance
data "external" "public_ip" {
program = ["sh", "get_public_ip.sh"]
}
locals {
tags = {
Name = "test-instance"
Environment = "test"
}
}
# EC2 Instance public DNS hostname
output "instance_public_dns" {
value = "${aws_instance.test.public_dns}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment