diff --git a/z1/Dockerfile b/z1/Dockerfile new file mode 100644 index 0000000..5e6f0cf --- /dev/null +++ b/z1/Dockerfile @@ -0,0 +1,20 @@ +# Use an official lightweight Python image +FROM python:3.8-slim + +# Set the working directory in the container +WORKDIR /app + +# Copy the application code into the container +COPY app.py /app/ + +# Install required Python packages: Flask and MySQL connector +RUN pip install flask mysql-connector-python + +# Expose port 5000 for the Flask app +EXPOSE 5000 + +# Set the environment variable for Flask +ENV FLASK_APP=app.py + +# Run the Flask application +CMD ["flask", "run", "--host=0.0.0.0", "--port=5000"] diff --git a/z1/README.md b/z1/README.md new file mode 100644 index 0000000..206bfa5 --- /dev/null +++ b/z1/README.md @@ -0,0 +1,65 @@ +# Docker Web Application + +## Overview +This is a Dockerized web application consisting of two services: +- **Web Service:** A simple Python Flask application serving HTTP endpoints. +- **Database Service:** A MySQL 8.0 database that stores its data in a persistent volume. + +The web service demonstrates basic functionality and includes an endpoint (`/dbtest`) to test connectivity with the database service. + +## Deployment Requirements +- **Docker:** Ensure Docker is installed and running. +- **Docker Compose:** Version 3.8 or later is required to run the multi-container application. + +## Application Architecture +- **Virtual Network:** + A custom Docker network `app-network` is used to allow seamless communication between containers. + +- **Named Volume:** + A persistent volume `db_data` is defined to store MySQL database data, ensuring data persistence between container restarts. + +## Container Configurations +- **Web Service Container:** + - **Image:** Custom built from the provided `Dockerfile`. + - **Port:** Exposes port `5000`. + - **Environment Variables:** Set for database connectivity (e.g., `MYSQL_HOST`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE`). + - **Restart Policy:** Configured to always restart on failure. + +- **Database Service Container:** + - **Image:** Official `mysql:8.0` image. + - **Ports:** Exposes port `3306`. + - **Environment Variables:** Defines `MYSQL_ROOT_PASSWORD` and `MYSQL_DATABASE` for initial configuration. + - **Volume:** Uses named volume `db_data` for data persistence. + - **Restart Policy:** Configured to always restart on failure. + +## Used Containers +- **web:** The Flask-based web server. +- **db:** The MySQL database server. + +## How to Use the Application + +1. **Prepare the Application:** + Run the following command to build images and create required networks/volumes: + ```bash + ./prepare-app.sh + +2. **Start the Application:** + Launch the containers with: + ./start-app.sh + You should see a message: + Running app ... + The app is available at http://localhost:5000 + +3. **Interact with the Application:** + + • Open your web browser and go to http://localhost:5000 to view the home page. + • Visit http://localhost:5000/status for the application status. + • Visit http://localhost:5000/dbtest to test the database connectivity. + +4. **Stop the Application:** + To stop all running services without removing their state: + ./stop-app.sh + +5. **Remove the Application:** + When you want to completely remove all containers, networks, and volumes: + ./remove-app.sh \ No newline at end of file diff --git a/z1/app.py b/z1/app.py new file mode 100644 index 0000000..12e132e --- /dev/null +++ b/z1/app.py @@ -0,0 +1,37 @@ +from flask import Flask, jsonify +import os +import mysql.connector +from mysql.connector import Error + +app = Flask(__name__) + +@app.route("/") +def home(): + # Basic endpoint to verify that the app is running + return "Hello, world! The app is working." + +@app.route("/status") +def status(): + # Returns the status of the application + return jsonify(status="OK") + +@app.route("/dbtest") +def dbtest(): + # Attempts to connect to the MySQL database using environment variables + try: + connection = mysql.connector.connect( + host="db", + user=os.environ.get("MYSQL_USER", "root"), + password=os.environ.get("MYSQL_PASSWORD", "example"), + database=os.environ.get("MYSQL_DATABASE", "exampledb"), + port=3306 + ) + if connection.is_connected(): + connection.close() + return "Successfully connected to the database." + except Error as e: + return f"Error connecting to database: {e}" + +if __name__ == "__main__": + # Run the app on port 5000 and make it accessible from any network interface + app.run(debug=True, host="0.0.0.0", port=5000) diff --git a/z1/docker-compose.yaml b/z1/docker-compose.yaml new file mode 100644 index 0000000..511c7fd --- /dev/null +++ b/z1/docker-compose.yaml @@ -0,0 +1,38 @@ +version: '3.8' + +services: + web: + build: . + ports: + - "5000:5000" + depends_on: + - db + restart: always + environment: + # Environment variables for connecting to the database + MYSQL_HOST: db + MYSQL_USER: "root" + MYSQL_PASSWORD: "example" + MYSQL_DATABASE: "exampledb" + networks: + - app-network + + db: + image: mysql:8.0 + restart: always + environment: + MYSQL_ROOT_PASSWORD: "example" + MYSQL_DATABASE: "exampledb" + volumes: + - db_data:/var/lib/mysql + ports: + - "3306:3306" + networks: + - app-network + +networks: + app-network: + driver: bridge + +volumes: + db_data: diff --git a/z1/prepare-app.sh b/z1/prepare-app.sh new file mode 100644 index 0000000..3070787 --- /dev/null +++ b/z1/prepare-app.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# prepare-app.sh: Prepares the Docker application environment. +# This script builds Docker images, and creates necessary networks and named volumes. + +# Build the Docker images defined in docker-compose.yaml +docker-compose build + +# Create the application network if it doesn't exist (optional, as docker-compose creates one automatically) +docker network create app-network 2>/dev/null || echo "Network 'app-network' already exists." + +# Create the named volume for MySQL database persistence (optional, docker-compose will create it if missing) +docker volume create db_data 2>/dev/null || echo "Volume 'db_data' already exists." + +echo "Preparing app completed." diff --git a/z1/remove-app.sh b/z1/remove-app.sh new file mode 100644 index 0000000..3647838 --- /dev/null +++ b/z1/remove-app.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# remove-app.sh: Removes all Docker application services and cleans up networks and volumes. +# This script removes all resources created by prepare-app.sh. + +docker-compose down --volumes --remove-orphans + +echo "Removed app." diff --git a/z1/start-app.sh b/z1/start-app.sh new file mode 100644 index 0000000..e7ba5e7 --- /dev/null +++ b/z1/start-app.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# start-app.sh: Starts the Docker application services. +# This script launches all containers in detached mode and configures them to restart on failure. + +docker-compose up -d + +echo "Running app ..." +echo "The app is available at http://localhost:5000" diff --git a/z1/stop-app.sh b/z1/stop-app.sh new file mode 100644 index 0000000..4bb82f0 --- /dev/null +++ b/z1/stop-app.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# stop-app.sh: Stops the Docker application services without removing containers or volumes. +# This ensures the current state is maintained even if configuration changes later. + +docker-compose stop + +echo "Stopping app..."