Run Terraform commands on Self Hosted Web
360
Run Terraform commands on self hosted Web
What does this image do? Terraform binary is bundled into a docker image which also contains Python Flask and Celery. Flask hosted the web and can be used as a REST Endpoint or Plain web. Celery (optional but recommended) can be used to fork out the actual execution of the terraform command in another container. The image is same for both the Flask and Celery, just the run commands vary - see docker-compose for container configuration details
Why the docker for TF? Typically Terraform(TF) code needs a command line to issue TF CLI commands to enable infrastrcuture management. For managing the same server where TF is installed is understandable. However, most of the time TF is being used to manage remote infrstructure. Dedicating a machine or a VM just for TF seems a waste of resources. Hence this repo hosts the TF executable within a docker container. However, as there is no "Server /Service" of TF, executing TF executable from a docker container does not solve the complete problem. The solution is to bundle the TF executable with a Web app/framework like Flask would allow to create simple API which can take "commands" and run the TF executable with corresponding CLI command.
What does it contain? This repo contains a Dockerfile which takes the base image of python, then adds a TF executable from TF image. The simple python programs written with flask framework define endpoints for each of the TF CLI commands. The actual TF files can be mapped to a bind volume and modified / updated. Celery is also imported in the source code and hence a Celery worker container can also be started with the same command
Why Celery? The image is quite capable of running on its own (in a flask container). However, terraform execution and its output is a stream of JSON files as it runs stepwise in the intended target to provision the relevant infrastructure. This can take long time. Hence, the browser session might actually timeout before the execution completes. While the terraform code will still complete its intended activity, the user / REST client would not know the output. Hence, Celery container (from the same image) and a redis container (standard image from dockerhub) is needed to offload the terraform execution in the celery container. However, certain environment vars are to be supplied to enable this transition.
Hence, there are following provision with this image
celery to enable command execution to be offloaded to celery container.How to Run?
Define the docker-compose.yaml container (as described below) to have minimally Flask.
Commands:
terraform initterraform plan --auto-approveterraform apply --auto-approveterraform destroy --auto-approve # Be careful with this command!Note: Auto Approval option is used in both plan and apply as the web page cannot wait for the prompt
to say YES as is normally the case in TF CLI
docker-compose.yaml
services:
flask:
container_name: flask
image: manjurn/terraform-cloud
command: "python3 -m flask run --host=0.0.0.0"
depends_on:
- redis
ports:
- 5000:5000
volumes:
- /path/to/terraform/src:/terrasrc # Using Bind Mount - change the host side to point to where terraform source files are located. Not needed if the EXEC_MODE: celery is specified
environment:
WEB_HOOK_URL: https://myhomeassistant/api/webhook/terra_status # Example of Self hosted Home Assistant site which provide webhook capability
OUTPUT: external
EXEC_MODE: celery
CELERY_BROKER_URL: 'redis://redis:6379'
CELERY_RESULT_BACKEND: 'redis://redis:6379'
networks:
- terra-network
celery:
container_name: celery
image: manjurn/terraform-cloud
command: "celery -A app.celery worker --loglevel=info"
depends_on:
- redis
networks:
- terra-network
volumes:
- /path/to/terraform/src:/terrasrc # Using Bind Mount - change the host side to point to where terraform source files are located
environment:
WEB_HOOK_URL: https://myhomeassistant/api/webhook/terra_status # Example of Self hosted Home Assistant site which provide webhook capability
OUTPUT: external
CELERY_BROKER_URL: 'redis://redis:6379'
CELERY_RESULT_BACKEND: 'redis://redis:6379'
redis:
image: redis
container_name: redis
networks:
- terra-network
networks:
terra-network:
Ports:
5000:5000 when running the container to
to enable access from host. In kubernetes, define appropriate Service typesVolumes:
/terrasrc. Hence this could be mounted in
volumes as $HOME/terraform/src:/terrasrc
Note: Terraform source files should be provided as a volume and mapped to container's /terrasrc.Kubernetes Manifest Sample Kubenetes Manifest file -
kind: Namespace
apiVersion: v1
metadata:
name: terra-cloud-ns
---
kind: Service
apiVersion: v1
metadata:
name: terra-cloud-svc
namespace: terra-cloud-ns
labels:
app: terra-cloud
spec:
type: ClusterIP
ports:
- name: terra-port
port: 5000
selector:
app: terra-cloud
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: terra-cloud-app
namespace: terra-cloud-ns
labels:
app: terra-cloud
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: terra-cloud
template:
metadata:
labels:
app: terra-cloud
spec:
containers:
- name: terra-cloud-container
image: manjurn/terraform-cloud
# imagePullPolicy: IfNotPresent
command: ['python3']
args: ['-m', 'flask', 'run', '--host=0.0.0.0']
env:
# - name: WEB_HOOK_URL
# value: https://myhomeassistant/api/webhook/terra_status
# - name: OUTPUT
# value: external
# - name: EXEC_MODE
# value: celery
#- name: CELERY_BROKER_URL
# value: 'redis://redis:6379'
#- name: CELERY_RESULT_BACKEND
# value: 'redis://redis:6379'
ports:
- containerPort: 5000
protocol: TCP
volumeMounts:
- name: vol-terra-loc
mountPath: /terrasrc
volumes:
- name: vol-terra-loc
hostPath:
path: /path/to/terraform/source/files
Content type
Image
Digest
sha256:a40d40b48…
Size
77.4 MB
Last updated
almost 3 years ago
docker pull manjurn/terraform-cloud