GithubHelp home page GithubHelp logo

star3am / terraform-cloudinit-container-server Goto Github PK

View Code? Open in Web Editor NEW

This project forked from christippett/terraform-cloudinit-container-server

0.0 1.0 0.0 56 KB

A batteries included cloud-init config to quickly and easily deploy a single Docker image or Docker Compose file to any Cloud™ VM.

License: MIT License

HCL 100.00%

terraform-cloudinit-container-server's Introduction

Simple Container Server w/ Terraform & Cloud-Init

GitHub tag (latest SemVer) Terraform Registry

A batteries included cloud-init config to quickly and easily deploy a single Docker image or Docker Compose file to any Cloud™ virtual machine.

What is cloud-init?

Cloud-init is the industry standard multi-distribution method for cross-platform cloud instance initialization. It is supported across all major public cloud providers, provisioning systems for private cloud infrastructure, and bare-metal installations.

Cloud-init will identify the cloud it is running on during boot, read any provided metadata from the cloud and initialize the system accordingly. This may involve setting up network and storage devices to configuring SSH access key and many other aspects of a system. Later on cloud-init will also parse and process any optional user or vendor data that was passed to the instance.

The module takes things one step further by bootstrapping an environment that hosts your containers with minimal fuss. All credit goes to the creators of cloud-init and Traefik for making this so easy.

Features

  • ☁️ This module is compatible with most major cloud providers:
    • AWS (see example)
      • Cost: USD$4.76/month
        t3a.micro • 2vCPU/1GB • 10GB HDD
    • Google Cloud Platform (see example)
      • Cost: USD$6.11/month
        e2.micro • 0.25vCPU/1GB • 10GB HDD
    • DigitalOcean (see example)
      • Cost: USD$6.00/month
        Standard Droplet • 1vCPU/1GB • 10 HDD
    • Azure
      • Cost: USD$14.73/month
        A0 • 1vCPU/0.75GB • 32GB HDD
    • (and theoretically any other platform that supports cloud-init)
  • 🌐 Installs and configures Traefik under-the-hood as the reverse proxy for your container(s)
  • 🔑 Generates and renews SSL/TLS certificates automatically using Let's Encrypt.
  • 📝 Gives you the option to provide supplementary cloud-init config file(s) to further customise the setup of your instances (example).

Requirements

The only two dependencies are for Docker and systemd to be installed on whatever virtual machine you're deploying to.

The following operating systems have been tested successfully:

Usage

The output of this module is the content of a cloud-init configuration file with everything needed to setup a VM and run your container(s). Use this as input into one of either user_data (AWS / DigitalOcean), metadata.user-data (Google Cloud) or custom_data (Azure) when creating a virtual machine.

Some providers expect this value to be base64 encoded, refer to the Terraform documentation below for details relevant to your cloud provider of choice:

Module Definition — Single Container

The easiest way to get a container up and running is to specify an image and the ports to expose as part of the container input variable. The container variable can accept any attribute found under Docker Compose's service configuration (docs), but in most cases image and ports are all that's need to get started.

Let's Encrypt is enabled by default, so we also provide a domain and letsencrypt_email.

module "docker-server" {
  source  = "christippett/container-server/cloudinit"
  version = "1.0.0"

  domain            = "example.com"
  letsencrypt_email = "[email protected]"

  container = {
    image   = "nginxdemos/hello"
    ports   = ["80"]
  }
}

Module Definition — Docker Compose

Choosing to use a Docker Compose file (docker-compose.yaml) provides greater flexibility with regards to how your containers are deployed, but requires you to manually configure your services to work with Traefik.

module "docker-server" {
  source  = "christippett/container-server/cloudinit"
  version = "1.0.0"

  domain            = "example.com"
  letsencrypt_email = "[email protected]"

  compose_file = file("docker-compose.yaml")
}

Traefik is a wonderful tool with a lot of functionality and configuration options, however it can be a bit intimidating to set up if you're not familiar with it. The four labels shown in the docker-compose.yaml file below are all you need to get a container up and running. These labels need to be added for every service defined in your Docker Compose file that you want to make available externally.

For more advanced options, refer to the official Traefik documentation.

# docker-compose.yaml

version: "3"

services:
  hello-world:
    restart: unless-stopped
    image: nginxdemos/hello
    ports:
      - "80"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.hello-world.rule=Host(`${domain}`)"
      - "traefik.http.routers.hello-world.entrypoints=websecure"
      - "traefik.http.routers.hello-world.tls=true"
      - "traefik.http.routers.hello-world.tls.certresolver=letsencrypt"
networks:
  default:
    external:
      name: web

Note:

  • 🔗 Traefik connects to services over the web Docker network by default — this network must be added for all service(s) you want exposed.
  • 🔒 Let's Encrypt is configured using the letsencrypt certificate resolver from Traefik. Refer to the example docker-compose.yaml file above for the labels used to enable and configure this feature.
  • 📋 Terraform shares the same variable interpolation syntax as Docker Compose's environment variables. We leverage this fact by parsing docker-compose.yaml as a Terraform template, providing both ${domain} and ${letsencrypt_email} as template variables. These can be used to parameterise your Docker Compose file without impacting its compatibility with other applications (such as running docker-compose locally).
  • 📊 The module provides an option for enabling Traefik's monitoring dashboard and API. When enabled, the dashboard is accessible from https://traefik.${domain}/dashboard/ and the API from https://traefik.${domain}/api/. The traefik sub-domain is currently hard-coded and cannot be changed. Don't forget to create the corresponding DNS record for the dashboard and API to be accessible.

Integration w/ Cloud Providers

AWS

resource "aws_instance" "vm" {
  ami             = "ami-0560993025898e8e8" # Amazon Linux 2
  instance_type   = "t2.micro"
  security_groups = ["sg-allow-everything-from-anywhere"]

  tags = {
    Name = "container-server"
  }

  user_data = module.docker-server.cloud_config # 👈
}

Google Cloud

resource "google_compute_instance" "vm" {
  name         = "container-server"
  project      = "my-project"
  zone         = "australia-southeast1
  machine_type = "e2-small"
  tags         = ["http-server", "https-server"]

  metadata = {
    user-data = module.docker-server.cloud_config # 👈
  }

  boot_disk {
    initialize_params {
      image = data.google_compute_image.cos.self_link
    }
  }

  network_interface {
    subnetwork         = "vpc"
    subnetwork_project = "my-project"

    access_config {
      // Ephemeral IP
    }
  }
}

Azure

resource "azurerm_linux_virtual_machine" "vm" {
  name                = "container-server"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  size                = "Standard_F2"
  admin_username      = "adminuser"

  custom_data = base64encode(module.docker-server.cloud_config) # 👈

  network_interface_ids = [
    azurerm_network_interface.example.id,
  ]

  admin_ssh_key {
    username   = "adminuser"
    public_key = file("~/.ssh/id_rsa.pub")
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "20.04-LTS"
    version   = "latest"
  }
}

DigitalOcean

resource "digitalocean_droplet" "vm" {
  name   = "container-server"
  image  = "docker-18-04"
  region = "lon1"
  size   = "s-1vcpu-1gb"

  user_data = module.docker-server.cloud_config # 👈
}

Terraform Documentation

Inputs

Name Description Type Default Required
domain The domain to deploy applications under. string n/a yes
letsencrypt_email The email address used for requesting certificates from Lets Encrypt. string n/a yes
cloudinit_part Supplementary cloud-init config used to customise the instance. list(object({ content_type : string, content : string })) [] no
compose_file The content of a Compose file used to deploy one or more services to the server. Either container or compose_file must be specified. string null no
container The container definition used to deploy a Docker image to the server. Follows the same schema as a Docker Compose service. Either container or compose_file must be specified. any {} no
docker_log_driver Custom Docker log driver (e.g. gcplogs). string "json-file" no
docker_log_opts Additional arguments/options for Docker log driver. map {} no
enable_letsencrypt Whether Lets Encrypt certificates should be automatically generated. bool true no
enable_traefik_api Whether the Traefik dashboard and API should be enabled. bool false no
letsencrypt_staging_server Whether to use the Lets Encrypt staging server (useful for testing). bool false no
traefik_api_password The password used to access the Traefik dashboard + API. string null no
traefik_api_user The username used to access the Traefik dashboard + API. string "admin" no
traefik_version The version of Traefik used by the server. string "v2.2" no

Outputs

Name Description
cloud_config Content of the cloud-init config to be deployed to a server.
docker_compose_config Content of the Docker Compose config to be deployed to a server.

terraform-cloudinit-container-server's People

Contributors

christippett avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.