Skip to content

Commit

Permalink
first
Browse files Browse the repository at this point in the history
  • Loading branch information
khanzadimahdi committed Jan 5, 2025
0 parents commit 6072a60
Show file tree
Hide file tree
Showing 14 changed files with 1,035 additions and 0 deletions.
67 changes: 67 additions & 0 deletions .github/actions/docker-build/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: 'Docker Build Action'
description: 'Builds a Docker image using a specified Dockerfile and context'

inputs:
context:
description: 'The Docker build context (path to the directory containing the Dockerfile)'
required: true
default: '.'
dockerfile:
description: 'The path to the Dockerfile (relative to the context)'
required: true
default: 'Dockerfile'
image-name:
description: 'The name of the image to build'
required: true
push:
description: 'Determines if the built image should be pushed'
required: true
default: 'no'
container-registry:
description: 'container registry address (example: ghcr.io)'
required: false
container-registry-username:
description: 'container registry username'
required: false
container-registry-password:
description: 'container registry password'
required: false

runs:
using: 'composite'

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
if: ${{ inputs.push == 'true' }}
with:
registry: ${{ inputs.container-registry }}
username: ${{ inputs.container-registry-username }}
password: ${{ inputs.container-registry-password }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Extract metadata (tags, labels) for Docker image
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ inputs.container-registry }}/${{ github.repository_owner }}/${{ inputs.image-name }}
tags: |
type=raw,value=latest,priority=200,enable={{is_default_branch}}
type=sha,enable=true,priority=100,prefix=,suffix=,format=short
- name: Build image and push (optional)
uses: docker/build-push-action@v6
with:
push: ${{ inputs.push == 'true' }}
context: ${{ inputs.context }}
file: ${{ inputs.dockerfile }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
68 changes: 68 additions & 0 deletions .github/actions/terraform/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: 'Docker Build Action'
description: 'Builds a Docker image using a specified Dockerfile and context'

inputs:
aws-access-key-id:
description: 'AWS access key id'
required: true
aws-secret-access-key:
description: 'AWS secret access key'
required: true
aws-region:
description: 'AWS region'
required: true
validate:
description: 'Determines if a round of validation should be done'
required: true
default: 'no'
plan:
description: 'Determines if terraform plan should be called'
required: true
default: 'no'
apply:
description: 'Determines if terraform apply should be called'
required: true
default: 'no'

runs:
using: 'composite'
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ inputs.aws-access-key-id }}
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
aws-region: ${{ inputs.aws-region }}

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3

- name: Terraform Format
if: ${{ inputs.validate == 'true' }}
run: terraform fmt -check
shell: bash
continue-on-error: false

- name: Terraform Init
run: terraform init
shell: bash

- name: Terraform Validate
if: ${{ inputs.validate == 'true' }}
run: terraform validate -no-color
shell: bash
continue-on-error: false

- name: Terraform Plan
if: ${{ inputs.plan == 'true' }}
run: terraform plan -no-color -input=false
shell: bash
continue-on-error: false

- name: Terraform Apply
if: ${{ inputs.apply == 'true' }}
shell: bash
run: terraform apply -auto-approve -input=false
135 changes: 135 additions & 0 deletions .github/workflows/infrastructure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: CI and CD

on:
push:
pull_request:

defaults:
run:
working-directory: ./infrastructure

env:
TF_VAR_project_name: tarhche
TF_VAR_instance_name: backend

PROXY_IMAGE_NAME: proxy

EC2_SSH_ADDRESS: ${{ secrets.EC2_SSH_ADDRESS }}
EC2_SSH_ENDPOINT: ${{ secrets.EC2_SSH_USER }}@${{ secrets.EC2_SSH_ADDRESS }}

jobs:
ci:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Terraform validate and apply
uses: ./.github/actions/terraform
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
validate: true
apply: true

- name: Build image
uses: ./.github/actions/docker-build
with:
context: ./proxy
dockerfile: ./proxy/Dockerfile
image-name: ${{ env.PROXY_IMAGE_NAME }}
push: false
container-registry: ghcr.io

cd:
runs-on: ubuntu-latest

if: ${{ format('refs/heads/{0}', github.event.repository.default_branch) == github.ref }}

needs:
- ci

permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Terraform validate and apply
uses: ./.github/actions/terraform
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
validate: true
apply: true

- name: Build and push proxy image
uses: ./.github/actions/docker-build
with:
context: ./proxy
dockerfile: ./proxy/Dockerfile
image-name: ${{ env.PROXY_IMAGE_NAME }}
push: true
container-registry: ghcr.io
container-registry-username: ${{ github.actor }}
container-registry-password: ${{ secrets.GITHUB_TOKEN }}

- name: Deploy services
run: |
# Setup ssh key
echo '${{ secrets.EC2_SSH_PRIVATE_KEY }}' > ~/ec2-key.pem
chmod 400 ~/ec2-key.pem
mkdir -p ~/.ssh
ssh-keyscan -H $EC2_SSH_ADDRESS >> ~/.ssh/known_hosts
# Ensure remote directory exists
ssh -q -i ~/ec2-key.pem -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $EC2_SSH_ENDPOINT > /dev/null 2>&1 << 'EOF'
export VOLUME_PATH='${{ secrets.VOLUME_PATH }}'
sudo mkdir -p /opt/deployment
sudo chown ${{ secrets.EC2_SSH_USER }}:${{ secrets.EC2_SSH_USER }} /opt/deployment
# create volumes directories
sudo mkdir -p $VOLUME_PATH/mongodb/db
sudo mkdir -p $VOLUME_PATH/mongodb/configdb
sudo mkdir -p $VOLUME_PATH/nats
EOF
# Copy files
scp -q -i ~/ec2-key.pem -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r ./* $EC2_SSH_ENDPOINT:/opt/deployment/ > /dev/null 2>&1
# Connect and deploy services
ssh -q -i ~/ec2-key.pem -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $EC2_SSH_ENDPOINT > /dev/null 2>&1 << 'EOF'
export VOLUME_PATH='${{ secrets.VOLUME_PATH }}'
export MONGO_USERNAME='${{ secrets.MONGO_USERNAME }}'
export MONGO_PASSWORD='${{ secrets.MONGO_PASSWORD }}'
export DASHBOARD_MONGO_USERNAME='${{ secrets.DASHBOARD_MONGO_USERNAME }}'
export DASHBOARD_MONGO_PASSWORD='${{ secrets.DASHBOARD_MONGO_PASSWORD }}'
export DASHBOARD_MONGO_MONGODB_URL='mongodb://${{ secrets.MONGO_USERNAME }}:${{ secrets.MONGO_PASSWORD }}@mongodb:27017'
export PROXY_IMAGE='${{ secrets.PROXY_IMAGE }}'
export PORTAINER_ADMIN_PASSWORD='${{ secrets.PORTAINER_ADMIN_PASSWORD }}'
# Run Docker Compose
cd /opt/deployment/
docker compose -f compose.mongodb.yaml --project-name mongodb up --pull always --detach
docker compose -f compose.mongodb_dashboard.yaml --project-name mongodb_dashboard up --pull always --detach
docker compose -f compose.nats.yaml --project-name nats up --pull always --detach
docker compose -f compose.docker.yaml --project-name docker up --pull always --detach
docker compose -f compose.docker_dashboard.yaml --project-name docker_dashboard up --pull always --detach
docker compose -f compose.app.yaml --project-name app up --pull always --detach
docker compose -f compose.frontend.yaml --project-name frontend up --pull always --detach
docker compose -f compose.proxy.yaml --project-name proxy up --pull always --detach
EOF
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.DS_Store
.vscode
.idea
/tmp

# SSH keys
/*.pem
/*.pub

# Terraform files
*.tfstate
*.tfstate.backup
.terraform/
90 changes: 90 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
export TF_VAR_project_name = tarhche
export TF_VAR_instance_name = backend

export EC2_SSH_ADDRESS = ec2-3-124-72-48.eu-central-1.compute.amazonaws.com
export EC2_SSH_USER = ubuntu
export EC2_SSH_ENDPOINT = ${EC2_SSH_USER}@${EC2_SSH_ADDRESS}
export VOLUME_PATH = ./tmp/volume_01

export MONGO_USERNAME = test
export MONGO_PASSWORD = test‍

export DASHBOARD_MONGO_USERNAME = username
export DASHBOARD_MONGO_PASSWORD = password
export DASHBOARD_MONGO_MONGODB_URL = mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@mongodb:27017

export BACKEND_NATS_URL =
export BACKEND_PRIVATE_KEY =

export BACKEND_MONGO_HOST = mongodb
export BACKEND_MONGO_PORT = 27017
export BACKEND_MONGO_SCHEME = mongodb
export BACKEND_MONGO_DATABASE_NAME = test
export BACKEND_MONGO_USERNAME = ${MONGO_USERNAME}
export BACKEND_MONGO_PASSWORD = ${MONGO_PASSWORD}

export BACKEND_MAIL_SMTP_PASSWORD =
export BACKEND_MAIL_SMTP_HOST =
export BACKEND_MAIL_SMTP_FROM =
export BACKEND_MAIL_SMTP_USERNAME =
export BACKEND_MAIL_SMTP_PORT =

export BACKEND_S3_ENDPOINT =
export BACKEND_S3_SECRET_KEY =
export BACKEND_S3_ACCESS_KEY =
export BACKEND_S3_USE_SSL = false
export BACKEND_S3_BUCKET_NAME =

export PROXY_IMAGE = ghcr.io/tarhche/proxy:latest

export APP_IMAGE = ghcr.io/tarhche/backend:latest

# username: admin
# password: admin-password (in bcrypt, a dollar-sign should be escaped by an arbitrary dollar-sign ($ --> $$))
export PORTAINER_ADMIN_PASSWORD = $$2a$$12$$4xcOa82Ni5rjgQF.v.JWi.i71OyUm3fwmfWiumgJHIAPGU.uOw3qu

export FRONTEND_IMAGE = ghcr.io/tarhche/frontend:latest
export NEXT_PUBLIC_EXTERNAL_BACKEND_BASE_URL =
export INTERNAL_BACKEND_BASE_URL = http://app
export NEXT_PUBLIC_FILES_BASE_URL =

validate:
terraform validate

fmt:
terraform fmt

init:
terraform init

state:
terraform state list

plan:
terraform plan

apply:
terraform apply
rm -f terraform.tfstate *.tfstate.*

public_key:
ssh-keygen -y -f ssh-private-key.pem > ssh-public-key.pub

ssh:
ssh -i "ssh-private-key.pem" ${EC2_SSH_ENDPOINT}

up:
docker compose -f compose.mongodb.yaml --project-name mongodb up --pull always --detach
docker compose -f compose.mongodb_dashboard.yaml --project-name mongodb_dashboard up --pull always --detach
docker compose -f compose.nats.yaml --project-name nats up --pull always --detach
docker compose -f compose.docker.yaml --project-name docker up --pull always --detach
docker compose -f compose.docker_dashboard.yaml --project-name docker_dashboard up --pull always --detach
docker compose -f compose.proxy.yaml --project-name proxy up --pull always --detach

down:
docker compose -f compose.proxy.yaml --project-name proxy down --volumes --remove-orphans
docker compose -f compose.nats.yaml --project-name nats down --volumes --remove-orphans
docker compose -f compose.docker_dashboard.yaml --project-name docker_dashboard down --volumes --remove-orphans
docker compose -f compose.docker.yaml --project-name docker down --volumes --remove-orphans
docker compose -f compose.mongodb_dashboard.yaml --project-name mongodb_dashboard down --volumes --remove-orphans
docker compose -f compose.mongodb.yaml --project-name mongodb down --volumes --remove-orphans
21 changes: 21 additions & 0 deletions compose.docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
docker:
image: docker:27-dind
networks:
- docker
deploy:
mode: replicated
replicas: 1
endpoint_mode: vip
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
runtime: sysbox-runc
# privileged: true # To test localy: enable this line and disable runtime
environment:
DOCKER_TLS_CERTDIR: "" # disable certs

networks:
docker:
name: docker
Loading

0 comments on commit 6072a60

Please sign in to comment.