Howdy,Kloudy!
January 12, 2023

Dockerize the Full-Stack application built using PowerShell (Pode & PSHTML)

Posted on January 12, 2023  •  6 minutes  • 1209 words  
Views
Table of contents

Introduction

I have recorded the demonstration of spinning up the full-stack application built using PowerShell (Pode & PSHTML). Feel free to leave your comments

Disclaimer

Prerequisites

Run a Full-Stack Application Locally (Windows Box)

We aren’t building an application with real-time data that visually pleases the end users. Instead, we intend to collect and store the employee information in the MySQL table. So, let us build a simple page showing useless data and a form to get employee information and insert it in the employee table as a row with an auto incremental employee id.

High-Level Diagram

Ful-Stack

Solution

First, decide the data you need to collect and store in the MySQL table. In my case, I need to get the user’s first name, last name, city, country and mobile number.

Project Structure

📦howdykloudy
┣ 📂app
┃ ┣ 📂views
┃ ┃ ┗ 📜index.ps1
┃ ┣ 📜app.ps1
┃ ┗ 📜Dockerfile
┣ 📂dump
┃ ┗ 📜dump.sql
┣ 📜docker-compose.yml
┣ 📜minikube-deployment.yml
┗ 📜README.md

Script to Create a MYSQL Table

create table employee (
    id int not null AUTO_INCREMENT primary key,
    first_name varchar(255),
    last_name varchar(255),
    city varchar(255),
    country varchar(255),
    mobile varchar(255)
)

id int not null AUTO_INCREMENT primary key - For each record insertion, we see the ID value incremented by 1. For example, the first record in the database looks like below

IDFirstNameLastNameCityCountryMobile
1ChenVBengaluruIndia+91 0123456789

and the subsequent calls continue to store records as illustrated below

IDFirstNameLastNameCityCountryMobile
1ChenVBengaluruIndia+91 0123456789
2ChenVBengaluruIndia+91 0123456789

User Interface (Web Front-End)

#region - Form
form -action "/formdata" -method "post" -enctype 'multipart/form-data' -content {
    Div -Class 'form-group' -Content {
        h5 -Content 'Employee Form' -Style 'text-align:center'
        input -type text -name 'first_name' -Attributes @{'data-role' = "materialinput"; 'data-icon' = "<span class=mif-first>"; 'data-cls-line' = 'bg-darkCyan'; 'data-cls-label' = 'fg-darkCyan'; 'data-cls-informer' = 'fg-darkCyan'; 'data-cls-icon' = 'fg-darkCyan' ; 'placeholder' = 'First Name' } -required
        input -type text -name 'last_name' -Attributes @{'data-role' = "materialinput"; 'data-icon' = "<span class=mif-last>"; 'data-cls-line' = 'bg-darkCyan'; 'data-cls-label' = 'fg-darkCyan'; 'data-cls-informer' = 'fg-darkCyan'; 'data-cls-icon' = 'fg-darkCyan' ; 'placeholder' = 'Last Name' } -required
        input -type text -name 'city' -Attributes @{'data-role' = "materialinput"; 'data-icon' = "<span class=mif-location-city>"; 'data-cls-line' = 'bg-darkCyan'; 'data-cls-label' = 'fg-darkCyan'; 'data-cls-informer' = 'fg-darkCyan'; 'data-cls-icon' = 'fg-darkCyan' ; 'placeholder' = 'City' } -required
        input -type text -name 'country' -Attributes @{'data-role' = "materialinput"; 'data-icon' = "<span class=mif-flag>"; 'data-cls-line' = 'bg-darkCyan'; 'data-cls-label' = 'fg-darkCyan'; 'data-cls-informer' = 'fg-darkCyan'; 'data-cls-icon' = 'fg-darkCyan' ; 'placeholder' = 'Country' } -required
        input -type tel -name 'mobile' -Attributes @{'data-role' = "materialinput"; 'data-icon' = "<span class=mif-mobile>"; 'data-cls-line' = 'bg-darkCyan'; 'data-cls-label' = 'fg-darkCyan'; 'data-cls-informer' = 'fg-darkCyan'; 'data-cls-icon' = 'fg-darkCyan' ; 'placeholder' = 'Mobile' } -required
    }
    div -class 'form-group' -content {
        button -class 'button bg-darkCyan outline rounded fg-white' -content 'Submit'
    }
}
#endregion

{IMAGE}

On Submit (Insert Records into MySQL)

Docker Compose

Docker Compose is a tool to run multi-container Docker applications. Below is the YAML definition

version: '3.8'
networks:
  howdy_kloudy:
    name: howdy_kloudy
services:
  mysql:
    image: mysql
    restart: always
    container_name: db-mysql
    networks:
      - howdy_kloudy
    ports:
      - 3306:3306
    environment:
      - MYSQL_DATABASE=local_db
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    volumes:
      - ./dump:/docker-entrypoint-initdb.d

  podeui:
    build: ./app
    image: podeui
    networks:
      - howdy_kloudy
    ports:
      - "3000:3000"
PS C:\Projects\howdykloudy> docker-compose up --build --detach

Images In Use

Images In Use

Now access the application from the local host.

UI

UI

Response

Response

Refer the records in the MySQL table

First Record

Second record

Second Record

Okay, it’s working as expected! We see records are available in the table.

Run on Minikube

Nothing interesting, right? Let us add spice by running our application on Minikube. I spent a few hours establishing the connection between containers in a POD. Yeah, I know it’s simple and easy, but for me, it’s not. I failed to establish the connection between my UI and DB.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podeui
  labels:
    app: multi-contianer
spec:
  replicas: 1
  selector:
    matchLabels:
      app: multi-contianer
  template:
    metadata:
      labels:
        app: multi-contianer
    spec:
      containers:
        - name: podeui
          image: chenv/podeui:v3
          ports:
            - containerPort: 3000
          resources: {}
        - name: db-mysql
          image: mysql
          env:
            - name: MYSQL_DATABASE
              value: "local_db"
            - name: MYSQL_ALLOW_EMPTY_PASSWORD
              value: "yes"
          resources: {}
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: mysql-initdb
              mountPath: /docker-entrypoint-initdb.d
            - mountPath: "/var/lib/mysql"
              subPath: "mysql"
              name: mysql-data
      volumes:
        - name: mysql-initdb
          configMap:
            name: mysql-initdb-config
        - name: mysql-data
          persistentVolumeClaim:
            claimName: mysql-data-disk
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-initdb-config
data:
  init.sql: |
    CREATE DATABASE IF NOT EXISTS local_db;
    USE local_db;
    create table employee (id int not null AUTO_INCREMENT primary key, first_name varchar(255), last_name varchar(255), city varchar(255),country varchar(255), mobile varchar(255));    
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data-disk
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Yes, the YAML above is self-explanatory. Just a few highlights

Now, let us get on action

PS C:\Projects\howdykloudy> minikube start

minkube start

PS C:\Projects\howdykloudy> kubectl get pods -A

list pods

PS C:\Projects\howdykloudy> minikube service podeui 

Access the application :)

kubectl exec {POD-NAME} -it --namespace default --container db-mysql -- /bin/bash

list pods

Summary

I plan to extend this application and share my Kubernetes learnings. So, stay tuned to get to know more on the below

Social Networking

Let us stay connected to learn, share and grow!