Saez Arana
3 weeks ago
20 changed files with 398 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||
FROM mysql:latest |
|||
|
|||
# Copia el script SQL a la ubicación dentro del contenedor |
|||
COPY script.sql /docker-entrypoint-initdb.d/ |
@ -0,0 +1,46 @@ |
|||
# Notes Manager Application |
|||
|
|||
This is a simple notes management application developed with php and sql and deployed in kubernetes that allows you to create, read, update, and delete notes easily and efficiently. |
|||
|
|||
## Key features |
|||
|
|||
- Create Notes: You can create new notes by specifying a title and content. |
|||
- List Notes: View all existing notes in the application. |
|||
- Update Notes: Modify the title or content of an existing note. |
|||
- Delete Notes: Remove notes that are no longer needed. |
|||
|
|||
## Technologies Used |
|||
- Backend: php container |
|||
- Frontend: HTML,CSS |
|||
- Database: mysql container e |
|||
- Containers: Docker |
|||
- Container Orchestrator: Kubernetes |
|||
|
|||
## Docker images and kubernetes object |
|||
- Images: |
|||
- php from -> rafasaez/php-sql-app image |
|||
- sql from -> rafasaez/sql-app images |
|||
|
|||
- kubernetes yaml(Inside kubernetes directory): |
|||
- mysql-service.yaml -> for the service of mysql |
|||
- php-service.yaml -> for the service of php |
|||
- mysqk-statefulset.yaml -> for the statefulset of mysql |
|||
- php-deployment.yaml -> for the deployment of php |
|||
- secret-sql-password -> for the secret object where mysql password is storage |
|||
## How to run de application |
|||
- Firs you need to install kubernetes on docker |
|||
- Go to docker desktop, go to settings, kubernetes and click on enable kubernetes |
|||
- Open your terminal |
|||
- Run the following |
|||
```bash |
|||
bash prepare-app.sh |
|||
``` |
|||
- Once is evry image created run the application |
|||
```bash |
|||
bash start-app.sh |
|||
``` |
|||
- Your application should be running on port 8080 in localhost |
|||
- If you want to finish the app just run: |
|||
```bash |
|||
bash stop-app.sh |
|||
``` |
@ -0,0 +1,18 @@ |
|||
<?php |
|||
require "config/database.php"; |
|||
$db =conectarDB(); |
|||
|
|||
if ($db->connect_errno) { |
|||
// Print the connection error message |
|||
echo "Failed to connect to MySQL: " . mysqli_connect_error(); |
|||
// You can also log the error message to a file or other logging mechanism |
|||
// error_log("Failed to connect to MySQL: " . mysqli_connect_error()); |
|||
exit(); // Exit the script if there's a connection error |
|||
} |
|||
if($_POST){ |
|||
$note = mysqli_real_escape_string($db,$_POST['note']);; |
|||
$query = "insert into nota (noteContent) values ('$note')"; |
|||
mysqli_query($db,$query); |
|||
} |
|||
mysqli_close($db); |
|||
header("Location:../index.php"); |
@ -0,0 +1,9 @@ |
|||
<?php |
|||
|
|||
function conectarDB(){ |
|||
$host = 'mysql-service'; |
|||
//$host = 'mysql-service.z2.svc.cluster.local'; |
|||
$db = mysqli_connect($host,'root','password','notas'); |
|||
//$db->set_charset('utf8') |
|||
return $db; |
|||
} |
@ -0,0 +1,20 @@ |
|||
<?php |
|||
require "config/database.php"; |
|||
$db =conectarDB(); |
|||
|
|||
if ($db->connect_errno) { |
|||
// Print the connection error message |
|||
echo "Failed to connect to MySQL: " . mysqli_connect_error(); |
|||
// You can also log the error message to a file or other logging mechanism |
|||
// error_log("Failed to connect to MySQL: " . mysqli_connect_error()); |
|||
exit(); // Exit the script if there's a connection error |
|||
} |
|||
|
|||
|
|||
if($_POST){ |
|||
$noteID = $_POST['id'];; |
|||
$query = "delete from nota where id = $noteID"; |
|||
mysqli_query($db,$query); |
|||
} |
|||
mysqli_close($db); |
|||
header("Location:../index.php"); |
@ -0,0 +1,21 @@ |
|||
<?php |
|||
require "config/database.php"; |
|||
$db =conectarDB(); |
|||
|
|||
if ($db->connect_errno) { |
|||
// Print the connection error message |
|||
echo "Failed to connect to MySQL: " . mysqli_connect_error(); |
|||
// You can also log the error message to a file or other logging mechanism |
|||
// error_log("Failed to connect to MySQL: " . mysqli_connect_error()); |
|||
exit(); // Exit the script if there's a connection error |
|||
} |
|||
|
|||
|
|||
if($_POST){ |
|||
$noteID = $_POST['id'];; |
|||
$note = mysqli_real_escape_string($db,$_POST['note']);; |
|||
$query = "UPDATE nota SET noteContent = '$note' where id = $noteID"; |
|||
mysqli_query($db,$query); |
|||
} |
|||
mysqli_close($db); |
|||
header("Location:../index.php"); |
@ -0,0 +1,74 @@ |
|||
<?php |
|||
require "includes/config/database.php"; |
|||
$db =conectarDB(); |
|||
if ($db->connect_errno) { |
|||
// Print the connection error message |
|||
echo "Failed to connect to MySQL: " . mysqli_connect_error(); |
|||
// You can also log the error message to a file or other logging mechanism |
|||
// error_log("Failed to connect to MySQL: " . mysqli_connect_error()); |
|||
exit(); // Exit the script if there's a connection error |
|||
} |
|||
|
|||
$getNotes = "select * from nota" ; |
|||
$notes = mysqli_query($db,$getNotes); |
|||
if(!$notes){ |
|||
echo "Error: " . mysqli_error($db); |
|||
} |
|||
mysqli_close($db); |
|||
?> |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|||
<link rel="stylesheet" href="src/styles.css"> |
|||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" /> |
|||
<title>Document</title> |
|||
</head> |
|||
<body> |
|||
<div class="contenedor"> |
|||
|
|||
<h1>Notes manager</h1> |
|||
<form class="addNote"id="myForm" method="post" action="includes/create.php"> |
|||
<label for="note"></label> |
|||
<input name="note" id="note" type="text"> |
|||
<input class="button greenButton" type="submit" value="add"> |
|||
</form> |
|||
<div class="notas"> |
|||
<?php while($row=mysqli_fetch_array($notes)){?> |
|||
<div class="note"> |
|||
<form action="includes/edit.php"class="contenido-and-edit" onsubmit="checkSubmit(event)" method="post"> |
|||
<input type="text" class ="notaImpresa" name="note" value ="<?php echo $row['noteContent'] ?>" readonly> |
|||
<input type="hidden" name="id" value="<?php echo $row['id']?>"> |
|||
<!--Edit button--> |
|||
<button class="button greenButton"><span class="material-symbols-outlined">edit</span></button> |
|||
</form> |
|||
<!--Delete button--> |
|||
<form action="includes/delete.php" method="post"> |
|||
<input type="hidden" name="id" value="<?php echo $row['id']?>"> <!-- Aquí puedes poner el ID del elemento a eliminar --> |
|||
<button class="button redButton" type="submit" name="delete"> <span class="material-symbols-outlined">delete</span></button> |
|||
</form> |
|||
|
|||
</div> |
|||
<?php }?> |
|||
<script> |
|||
function checkSubmit(event) { |
|||
if(event.target.classList.contains("contenido-and-edit")){ |
|||
var form = event.target; |
|||
var input = form.querySelector(".notaImpresa"); |
|||
var editButton = form.querySelector(".button"); |
|||
if (input.readOnly) { |
|||
event.preventDefault(); // Prevent form submission |
|||
input.readOnly=false; |
|||
editButton.querySelector(".material-symbols-outlined").innerText = "done"; |
|||
} |
|||
} |
|||
} |
|||
|
|||
</script> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,49 @@ |
|||
#Para que podamos coger la imagen creada de docker necesitamos subirla al repositorio |
|||
#Para ello creamos la imagen como |
|||
docker build -t rafasaez/nombre-repositorio |
|||
#luego mandamos la imagen a docker hub |
|||
docker push rafasaez/nombre-repositorio |
|||
|
|||
#objecto secreto |
|||
apiVersion: v1 |
|||
kind: Secret |
|||
metadata: |
|||
name: mysql-secret |
|||
type: Opaque |
|||
data: |
|||
#En base64 ponemos nuestra contraseña encriptada |
|||
password: base64_encoded_passwordecho |
|||
|
|||
#Para encriptar se encripta en base64 por default al usar secret |
|||
echo -n 'your_password' | base64 |
|||
|
|||
|
|||
#para iteractuar con la base de datos |
|||
kubectl exec -i mysql-0 -n z2 -- mysql -h mysql-service.z2.svc.cluster.local -P80 -u root -p password < sql/script.sql |
|||
|
|||
|
|||
#problemas |
|||
#Cuando añado la informacion de los volumenes de la configuracion inicial no funciona el state ful set |
|||
#en volumemounts |
|||
- name: init-scripts |
|||
mountPath: /docker-entrypoint-initdb.d |
|||
volumeClaimTemplates: |
|||
- metadata: |
|||
name: init-scripts |
|||
spec: |
|||
accessModes: [ "ReadWriteOnce" ] |
|||
resources: |
|||
requests: |
|||
storage: 1Gi |
|||
|
|||
|
|||
#Funciona la app finalmente obte por meter la config de la base de datos directamente en el docker file para crear una nueva imagen de sql con la base configurada |
|||
#Volver a hacer lo de la ssh key |
|||
|
|||
#Conectar a la base de datos |
|||
#kubectl exec -it -n z2 mysql-0 -- mysql -u root -p notas |
|||
#Solo me deja entrar a mysql cuando ejecuto el comando de arriba |
|||
#Cuando hago delete namespace no se me guarda la informacion que tengo en la base de datos |
|||
|
|||
#cambiar a retain |
|||
kubectl patch pv <pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' |
@ -0,0 +1,11 @@ |
|||
apiVersion: v1 |
|||
kind: Service |
|||
metadata: |
|||
name: mysql-service |
|||
spec: |
|||
selector: |
|||
app: mysql |
|||
ports: |
|||
- protocol: TCP |
|||
port: 3306 |
|||
targetPort: 3306 |
@ -0,0 +1,39 @@ |
|||
apiVersion: apps/v1 |
|||
kind: StatefulSet |
|||
metadata: |
|||
name: mysql |
|||
spec: |
|||
serviceName: mysql-service |
|||
replicas: 1 |
|||
selector: |
|||
matchLabels: |
|||
app: mysql |
|||
template: |
|||
metadata: |
|||
labels: |
|||
app: mysql |
|||
spec: |
|||
containers: |
|||
- name: mysql |
|||
image: rafasaez/sql-app |
|||
ports: |
|||
- containerPort: 3306 |
|||
env: |
|||
- name: MYSQL_ROOT_PASSWORD |
|||
valueFrom: |
|||
secretKeyRef: |
|||
name: mysql-secret |
|||
key: password |
|||
volumeMounts: |
|||
- name: mysql-persistent-storage |
|||
mountPath: /var/lib/mysql |
|||
#Crea los pv necerarios |
|||
volumeClaimTemplates: |
|||
- metadata: |
|||
name: mysql-persistent-storage |
|||
spec: |
|||
accessModes: [ "ReadWriteOnce" ] |
|||
resources: |
|||
requests: |
|||
storage: 1Gi |
|||
|
@ -0,0 +1,19 @@ |
|||
apiVersion: apps/v1 |
|||
kind: Deployment |
|||
metadata: |
|||
name: php |
|||
spec: |
|||
replicas: 1 |
|||
selector: |
|||
matchLabels: |
|||
app: php |
|||
template: |
|||
metadata: |
|||
labels: |
|||
app: php |
|||
spec: |
|||
containers: |
|||
- name: php |
|||
image: rafasaez/php-sql-app:latest |
|||
ports: |
|||
- containerPort: 80 |
@ -0,0 +1,12 @@ |
|||
apiVersion: v1 |
|||
kind: Service |
|||
metadata: |
|||
name: php-service |
|||
spec: |
|||
selector: |
|||
app: php |
|||
ports: |
|||
- protocol: TCP |
|||
port: 8080 |
|||
targetPort: 80 |
|||
type: LoadBalancer |
@ -0,0 +1,4 @@ |
|||
docker build -t rafasaez/php-sql-app . |
|||
docker push rafasaez/php-sql-app |
|||
cd sql |
|||
bash prepare-sql.sh |
@ -0,0 +1,2 @@ |
|||
docker build -t rafasaez/sql-app . |
|||
docker push rafasaez/sql-app |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||
create database notas; |
|||
use notas; |
|||
|
|||
CREATE TABLE nota ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
noteContent VARCHAR(60) |
|||
); |
@ -0,0 +1,7 @@ |
|||
apiVersion: v1 |
|||
kind: Secret |
|||
metadata: |
|||
name: mysql-secret |
|||
type: Opaque |
|||
data: |
|||
password: cGFzc3dvcmQ= |
@ -0,0 +1,6 @@ |
|||
kubectl create namespace z2 |
|||
kubectl apply -f kubernetes/secret-sql-password.yaml -n z2 |
|||
kubectl apply -f kubernetes/mysql-statefulset.yaml -n z2 |
|||
kubectl apply -f kubernetes/mysql-service.yaml -n z2bas |
|||
kubectl apply -f kubernetes/php-deployment.yaml -n z2 |
|||
kubectl apply -f kubernetes/php-service.yaml -n z2 |
@ -0,0 +1 @@ |
|||
kubectl delete namespace z2 |
@ -0,0 +1,49 @@ |
|||
/* Utilities*/ |
|||
.button{ |
|||
display: inl; |
|||
color:white; |
|||
text-decoration: none; |
|||
font-weight: bold; |
|||
text-align: center; |
|||
padding: 1rem; |
|||
border-radius: 2rem; |
|||
text-transform: uppercase; |
|||
margin: 1rem 1rem; |
|||
border: none; |
|||
} |
|||
.greenButton{ |
|||
background-color: green; |
|||
} |
|||
.redButton{ |
|||
background-color: red; |
|||
width: -moz-available; |
|||
} |
|||
input[type="text"]{ |
|||
padding: 1rem; |
|||
border-radius: 2rem |
|||
} |
|||
|
|||
.contenedor{ |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
} |
|||
.note{ |
|||
background-color: bisque; |
|||
display: grid; |
|||
grid-template-columns: repeat(2,1fr); |
|||
align-items: center; |
|||
width: min-content; |
|||
padding:1rem; |
|||
border-radius: 2rem; |
|||
margin-top: 1rem; |
|||
} |
|||
.addNote{ |
|||
width: 20rem; |
|||
} |
|||
.editForm{ |
|||
display:none; |
|||
} |
|||
.contenido-and-edit{ |
|||
display: flex; |
|||
} |
Loading…
Reference in new issue