├── .gitignore ├── srcs ├── requirements │ ├── nginx │ │ ├── .dockerignore │ │ ├── conf │ │ │ └── default.conf │ │ └── Dockerfile │ ├── wordpress │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ └── tools │ │ │ └── wp-install.sh │ ├── .DS_Store │ └── mariadb │ │ ├── Dockerfile │ │ ├── tools │ │ └── create-db.sh │ │ └── conf │ │ └── 50-server.cnf └── docker-compose.yml ├── Makefile └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /srcs/requirements/nginx/.dockerignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /srcs/requirements/wordpress/.dockerignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /srcs/requirements/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zmoussam/Inception/HEAD/srcs/requirements/.DS_Store -------------------------------------------------------------------------------- /srcs/requirements/nginx/conf/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | # SSL/TLS Configuration 3 | listen 443 ssl; 4 | ssl_protocols TLSv1.2 TLSv1.3; 5 | ssl_certificate /etc/nginx/ssl/inception.crt; 6 | ssl_certificate_key /etc/nginx/ssl/inception.key; 7 | 8 | # Root, index, and server_name 9 | root /var/www/html; 10 | server_name localhost; 11 | index index.php; 12 | 13 | location / { 14 | try_files $uri $uri/ =404; 15 | } 16 | 17 | location ~ \.php$ { 18 | include snippets/fastcgi-php.conf; 19 | fastcgi_pass wordpress:9000; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /srcs/requirements/mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Dockerfile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: zmoussam +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2023/10/20 13:00:54 by zmoussam #+# #+# # 9 | # Updated: 2023/10/20 17:01:53 by zmoussam ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | 14 | FROM debian:buster 15 | 16 | RUN apt update -y && apt-get upgrade -y && apt install -y mariadb-server 17 | 18 | RUN mkdir -p /var/run/mysqld \ 19 | && chown -R mysql:mysql /run/mysqld \ 20 | && chmod 777 /run/mysqld 21 | 22 | COPY ./conf/50-server.cnf /etc/mysql/mariadb.conf.d/50-server.cnf 23 | 24 | COPY ./tools/create-db.sh . 25 | 26 | RUN chmod +x create-db.sh 27 | 28 | EXPOSE 3306 29 | 30 | ENTRYPOINT ["bash","./create-db.sh"] 31 | -------------------------------------------------------------------------------- /srcs/requirements/wordpress/Dockerfile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Dockerfile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: zmoussam +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2023/10/20 13:01:58 by zmoussam #+# #+# # 9 | # Updated: 2023/10/20 15:51:16 by zmoussam ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | # dockerfile for wordpress installation 14 | 15 | # base image 16 | FROM debian:bullseye 17 | 18 | # maintainer 19 | RUN apt update && apt upgrade -y \ 20 | && apt install -y php7.4 php7.4-curl php7.4-mysql php7.4-fpm curl 21 | 22 | RUN mkdir -p /run/php 23 | 24 | RUN mkdir -p /var/www/html 25 | 26 | RUN chown -R www-data:www-data /var/www/html 27 | 28 | RUN chmod -R 755 /var/www/html 29 | 30 | COPY ./tools/wp-install.sh /wp-install.sh 31 | 32 | RUN chmod +x /wp-install.sh 33 | 34 | EXPOSE 9000 35 | 36 | ENTRYPOINT ["/wp-install.sh", "php-fpm7.4", "-F"] 37 | 38 | -------------------------------------------------------------------------------- /srcs/requirements/mariadb/tools/create-db.sh: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # create-db.sh :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: zmoussam +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2023/10/20 13:00:51 by zmoussam #+# #+# # 9 | # Updated: 2023/10/20 17:10:09 by zmoussam ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | #!bin/bash 14 | 15 | service mysql start; 16 | # sleep 5; 17 | 18 | if [ ! -d "/var/lib/mysql/${SQL_DATABASE}" ] 19 | then 20 | echo "Creating database: ${SQL_DATABASE}" 21 | 22 | mysql -e "CREATE DATABASE IF NOT EXISTS \`${SQL_DATABASE}\`;" 23 | 24 | mysql -e "CREATE USER IF NOT EXISTS \`${SQL_USER}\`@'localhost' IDENTIFIED BY '${SQL_USER_PASSWORD}';" 25 | 26 | mysql -e "GRANT ALL PRIVILEGES ON \`${SQL_DATABASE}\`.* TO \`${SQL_USER}\`@'%' IDENTIFIED BY '${SQL_USER_PASSWORD}';" 27 | 28 | mysql -e "FLUSH PRIVILEGES;" 29 | fi 30 | service mysql stop; 31 | exec mysqld_safe -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Makefile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: zmoussam +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2023/10/20 13:00:31 by zmoussam #+# #+# # 9 | # Updated: 2023/10/20 15:59:25 by zmoussam ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | # Color variables 14 | GREEN=\033[0;32m 15 | NC=\033[0m 16 | 17 | all: 18 | @echo "$(GREEN)Building... \nPlease wait a few seconds !$(NC)" 19 | @mkdir -p /home/zmoussam/data 20 | @mkdir -p /home/zmoussam/data/wordpress 21 | @mkdir -p /home/zmoussam/data/database 22 | @docker-compose -f ./srcs/docker-compose.yml up -d --build > /dev/null 23 | @echo "$(GREEN)Building done, you can now access the services !$(NC)" 24 | 25 | clean: 26 | @echo "$(GREEN)Cleaning and removing all volumes... \nPlease wait a few seconds !$(NC)" 27 | @docker-compose -f ./srcs/docker-compose.yml down --rmi all --volumes > /dev/null 28 | @sudo rm -rf /home/zmoussam/data 29 | @echo "$(GREEN)Cleaning and removing all volumes done !$(NC)" 30 | 31 | re: fclean all 32 | -------------------------------------------------------------------------------- /srcs/requirements/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Dockerfile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: zmoussam +#+ +:+ +#+ # 7 | # +#+#+#+#+#+ +#+ # 8 | # Created: 2023/10/20 13:01:31 by zmoussam #+# #+# # 9 | # Updated: 2023/10/20 13:01:37 by zmoussam ### ########.fr # 10 | # # 11 | # **************************************************************************** # 12 | 13 | FROM debian:bullseye 14 | 15 | RUN apt-get update -y && apt-get upgrade -y \ 16 | && apt-get install -y nginx 17 | 18 | RUN mkdir -p /etc/nginx/ssl 19 | 20 | RUN apt-get install openssl -y && apt-get clean 21 | RUN openssl req -x509 -nodes \ 22 | -out /etc/nginx/ssl/inception.crt \ 23 | -keyout /etc/nginx/ssl/inception.key \ 24 | -subj "/C=MA/ST=Grand Casablanca/L=Casablanca/O=42/OU=42/CN=localhost/UID=zmoussam" 25 | 26 | RUN chmod 755 /var/www/html 27 | 28 | RUN chown -R www-data:www-data /var/www/html 29 | 30 | RUN mkdir -p /etc/nginx/conf.d 31 | 32 | COPY ./conf/default.conf /etc/nginx/sites-available/default 33 | 34 | EXPOSE 443 35 | 36 | # run the master process nginx 37 | ENTRYPOINT [ "nginx", "-g", "daemon off;" ] -------------------------------------------------------------------------------- /srcs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | nginx: 5 | ports: 6 | - "443:443" 7 | build: 8 | context: ./requirements/nginx 9 | dockerfile: Dockerfile 10 | container_name: nginx 11 | image: nginx:inception 12 | restart: always 13 | env_file: .env 14 | volumes: 15 | - wordpress:/var/www/html 16 | networks: 17 | - inception-network 18 | depends_on: 19 | - wordpress 20 | 21 | mariadb: 22 | build: 23 | context: ./requirements/mariadb 24 | dockerfile: Dockerfile 25 | container_name: mariadb 26 | image: mariadb:inception 27 | restart: always 28 | env_file: .env 29 | volumes: 30 | - mariadb:/var/lib/mysql 31 | networks: 32 | - inception-network 33 | 34 | wordpress: 35 | build: 36 | context: ./requirements/wordpress 37 | dockerfile: Dockerfile 38 | container_name: wordpress 39 | image: wordpress:inception 40 | restart: always 41 | volumes: 42 | - wordpress:/var/www/html 43 | env_file: .env 44 | depends_on: 45 | - mariadb 46 | networks: 47 | - inception-network 48 | 49 | volumes: 50 | mariadb: 51 | name: mariadb-data 52 | driver: local 53 | driver_opts: 54 | type: none 55 | o: bind 56 | device: /home/zmoussam/data/database 57 | wordpress: 58 | name: wordpress 59 | driver: local 60 | driver_opts: 61 | type: none 62 | o: bind 63 | device: /home/zmoussam/data/wordpress 64 | networks: 65 | inception-network: 66 | name: inception-network 67 | driver: bridge 68 | -------------------------------------------------------------------------------- /srcs/requirements/wordpress/tools/wp-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # **************************************************************************** # 3 | # # 4 | # ::: :::::::: # 5 | # wp-install.sh :+: :+: :+: # 6 | # +:+ +:+ +:+ # 7 | # By: zmoussam +#+ +:+ +#+ # 8 | # +#+#+#+#+#+ +#+ # 9 | # Created: 2023/10/20 13:02:02 by zmoussam #+# #+# # 10 | # Updated: 2023/10/20 15:48:18 by zmoussam ### ########.fr # 11 | # # 12 | # **************************************************************************** # 13 | 14 | 15 | ## change directory to /var/www/html where we will install wordpress 16 | # where the volume is mounted 17 | cd /var/www/html/; 18 | 19 | ## download wordpress source code 20 | # source code will be downloaded to /var/www/html/wordpress folder 21 | # > dev/null to hide the output of curl command (progress bar) 22 | # -O to write output to a file 23 | if [ ! -f "/var/www/html/wp-config.php" ]; 24 | then 25 | echo "Downloading wordpress source code"; 26 | 27 | curl -O https://wordpress.org/latest.tar.gz > /dev/null; 28 | 29 | ## download wp-cli to manage wordpress from command line 30 | # source code will be downloaded to /var/www/html/wp-cli.phar 31 | # -O to write output to a file 32 | # > dev/null to hide the output of curl command, it a good practice 33 | curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar > /dev/null; 34 | 35 | ## make wp-cli.phar executable 36 | chmod +x wp-cli.phar; 37 | 38 | mv wp-cli.phar /usr/local/bin/wp; 39 | 40 | tar -xvf latest.tar.gz; 41 | 42 | rm latest.tar.gz; 43 | 44 | mv wordpress/* .; 45 | 46 | rm -rf wordpress; 47 | 48 | touch /var/www/html/wp-config.php; 49 | 50 | cp /var/www/html/wp-config-sample.php /var/www/html/wp-config.php; 51 | 52 | sed -i '36 s/\/run\/php\/php7.4-fpm.sock/9000/' /etc/php/7.4/fpm/pool.d/www.conf; 53 | 54 | sed -i 's/database_name_here/'$SQL_DATABASE'/g' /var/www/html/wp-config.php; 55 | 56 | sed -i 's/username_here/'$SQL_USER'/g' /var/www/html/wp-config.php; 57 | 58 | sed -i 's/password_here/'$SQL_USER_PASSWORD'/g' /var/www/html/wp-config.php; 59 | 60 | sed -i 's/localhost/'$WORDPRESS_DB_HOST'/g' /var/www/html/wp-config.php; 61 | 62 | wp core install --url=$DOMAIN_NAME --title="Inception" --admin_user=$WP_ADMIN_USER --admin_password=$WP_ADMIN_PASSWORD --admin_email=$WP_ADMIN_EMAIL --allow-root; 63 | 64 | wp user create $WP_USER $WP_USER_EMAIL --user_pass=$WP_USER_PASSWORD --role='author' --allow-root; 65 | 66 | fi 67 | 68 | exec "$@"; 69 | -------------------------------------------------------------------------------- /srcs/requirements/mariadb/conf/50-server.cnf: -------------------------------------------------------------------------------- 1 | # 2 | # These groups are read by MariaDB server. 3 | # Use it for options that only the server (but not clients) should see 4 | # 5 | # See the examples of server my.cnf files in /usr/share/mysql 6 | 7 | # this is read by the standalone daemon and embedded servers 8 | [server] 9 | 10 | # this is only for the mysqld standalone daemon 11 | [mysqld] 12 | 13 | # 14 | # * Basic Settings 15 | # 16 | user = mysql 17 | pid-file = /run/mysqld/mysqld.pid 18 | socket = /run/mysqld/mysqld.sock 19 | port = 3306 20 | basedir = /usr 21 | datadir = /var/lib/mysql 22 | tmpdir = /tmp 23 | lc-messages-dir = /usr/share/mysql 24 | #skip-external-locking 25 | 26 | # Instead of skip-networking the default is now to listen only on 27 | # localhost which is more compatible and is not less secure. 28 | bind-address = 0.0.0.0 29 | 30 | # 31 | # * Fine Tuning 32 | # 33 | #key_buffer_size = 16M 34 | #max_allowed_packet = 16M 35 | #thread_stack = 192K 36 | #thread_cache_size = 8 37 | # This replaces the startup script and checks MyISAM tables if needed 38 | # the first time they are touched 39 | #myisam_recover_options = BACKUP 40 | #max_connections = 100 41 | #table_cache = 64 42 | #thread_concurrency = 10 43 | 44 | # 45 | # * Query Cache Configuration 46 | # 47 | #query_cache_limit = 1M 48 | query_cache_size = 16M 49 | 50 | # 51 | # * Logging and Replication 52 | # 53 | # Both location gets rotated by the cronjob. 54 | # Be aware that this log type is a performance killer. 55 | # As of 5.1 you can enable the log at runtime! 56 | #general_log_file = /var/log/mysql/mysql.log 57 | #general_log = 1 58 | # 59 | # Error log - should be very few entries. 60 | # 61 | log_error = /var/log/mysql/error.log 62 | # 63 | # Enable the slow query log to see queries with especially long duration 64 | #slow_query_log_file = /var/log/mysql/mariadb-slow.log 65 | #long_query_time = 10 66 | #log_slow_rate_limit = 1000 67 | #log_slow_verbosity = query_plan 68 | #log-queries-not-using-indexes 69 | # 70 | # The following can be used as easy to replay backup logs or for replication. 71 | # note: if you are setting up a replication slave, see README.Debian about 72 | # other settings you may need to change. 73 | #server-id = 1 74 | #log_bin = /var/log/mysql/mysql-bin.log 75 | expire_logs_days = 10 76 | #max_binlog_size = 100M 77 | #binlog_do_db = include_database_name 78 | #binlog_ignore_db = exclude_database_name 79 | 80 | # 81 | # * Security Features 82 | # 83 | # Read the manual, too, if you want chroot! 84 | #chroot = /var/lib/mysql/ 85 | # 86 | # For generating SSL certificates you can use for example the GUI tool "tinyca". 87 | # 88 | #ssl-ca = /etc/mysql/cacert.pem 89 | #ssl-cert = /etc/mysql/server-cert.pem 90 | #ssl-key = /etc/mysql/server-key.pem 91 | # 92 | # Accept only connections using the latest and most secure TLS protocol version. 93 | # ..when MariaDB is compiled with OpenSSL: 94 | #ssl-cipher = TLSv1.2 95 | # ..when MariaDB is compiled with YaSSL (default in Debian): 96 | #ssl = on 97 | 98 | # 99 | # * Character sets 100 | # 101 | # MySQL/MariaDB default is Latin1, but in Debian we rather default to the full 102 | # utf8 4-byte character set. See also client.cnf 103 | # 104 | character-set-server = utf8mb4 105 | collation-server = utf8mb4_general_ci 106 | 107 | # 108 | # * InnoDB 109 | # 110 | # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. 111 | # Read the manual for more InnoDB related options. There are many! 112 | 113 | # 114 | # * Unix socket authentication plugin is built-in since 10.0.22-6 115 | # 116 | # Needed so the root database user can authenticate without a password but 117 | # only when running as the unix root user. 118 | # 119 | # Also available for other users if required. 120 | # See https://mariadb.com/kb/en/unix_socket-authentication-plugin/ 121 | 122 | # this is only for embedded server 123 | [embedded] 124 | 125 | # This group is only read by MariaDB servers, not by MySQL. 126 | # If you use the same .cnf file for MySQL and MariaDB, 127 | # you can put MariaDB-only options here 128 | [mariadb] 129 | 130 | # This group is only read by MariaDB-10.3 servers. 131 | # If you use the same .cnf file for MariaDB of different versions, 132 | # use this group for options that older servers don't understand 133 | [mariadb-10.3] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project Title 2 | 3 | A Small Infrastructure with Docker Compose 4 | 5 | Screen Shot 2023-10-22 at 12 13 47 PM 6 | 7 | ## Description 8 | 9 | This project sets up a small infrastructure composed of different services, each running in a dedicated Docker container. It includes NGINX with TLSv1.2 or TLSv1.3, WordPress with php-fpm, and MariaDB. The setup also involves volumes for the WordPress database and website files, along with a docker-network for inter-container communication. 10 | 11 | ## Installation 12 | 13 | ### Prerequisites 14 | 15 | - Docker 16 | - Docker Compose 17 | 18 | ### Clone the repository 19 | 20 | ``` 21 | git clone https://github.com/zmoussam/Inception 22 | ``` 23 | 24 | ### Environment Variables 25 | 26 | Create a .env file at the root of the srcs directory with the following variables: 27 | ``` 28 | SQL_DATABASE=... 29 | SQL_USER=.... 30 | SQL_USER_PASSWORD=... 31 | MYSQL_ROOT_PASSWORD=... 32 | 33 | WORDPRESS_DB_HOST=... 34 | DOMAIN_NAME=... 35 | WP_USER=... 36 | WP_USER_PASSWORD=... 37 | WP_USER_EMAIL=... 38 | WP_ADMIN_USER=... 39 | WP_ADMIN_PASSWORD=... 40 | WP_ADMIN_EMAIL=... 41 | ``` 42 | The `.env` file located at the root of the `srcs` directory is used to define various environment variables that are utilized within the Docker Compose configuration. These variables are essential for configuring the services and containers within the infrastructure. 43 | 44 | Here's a brief explanation of the key variables and their usage: 45 | 46 | - `SQL_ROOT_PASSWORD`: Specifies the password for the root user of the MariaDB database. This password is crucial for accessing the root account and performing administrative tasks. 47 | 48 | - `SQL_USER`: Sets the username for accessing the MariaDB database. This user is used by the WordPress application to interact with the database. 49 | 50 | - `SQL_PASSWORD`: Defines the password for the MariaDB user specified in `MYSQL_USER`. It is used for authentication when accessing the MariaDB database. 51 | 52 | - `SQL_DATABASE`: Specifies the name of the MariaDB database that will be used by the WordPress application. 53 | 54 | These environment variables are referenced in the Docker Compose file for the respective services, ensuring that sensitive information is not hardcoded in the configuration files. By using environment variables, the configuration can be easily managed and updated without directly modifying the source code. 55 | 56 | ### Build and Run 57 | 58 | Navigate to the project directory and run the following command: 59 | 60 | ``` 61 | make 62 | ``` 63 | This command will handle the building of Docker images, creation of containers, and the configuration of the infrastructure based on the provided rules. 64 | 65 | ### Project Setup Rules 66 | 67 | The project adheres to several key rules and guidelines to ensure the proper setup and functioning of the infrastructure. Some of the important rules are as follows: 68 | 69 | 1. **Docker Compose Usage**: The project utilizes Docker Compose to manage the multi-container infrastructure, ensuring seamless orchestration and deployment of the services. 70 | 71 | 2. **Custom Dockerfiles**: Each service in the infrastructure has its own Dockerfile, and the images are built from scratch, without relying on pre-existing or external images. 72 | 73 | 3. **Container Management**: Services are containerized individually, and the project strictly adheres to the practice of one service per container, ensuring a modular and scalable architecture. 74 | 75 | 4. **Performance Optimization**: Containers are built using either the penultimate stable version of Alpine or Debian, chosen for their lightweight nature and efficient performance. 76 | 77 | 5. **Security Measures**: Sensitive information such as passwords and credentials are not hardcoded in the Dockerfiles. Instead, the project uses environment variables and a `.env` file to manage and secure sensitive data. 78 | 79 | 6. **Network Configuration**: Inter-container communication is established through a dedicated docker-network, with the explicit prohibition of using `network: host` or `--link` for networking. 80 | 81 | 7. **NGINX Configuration**: NGINX is configured to exclusively accept connections through port 443, utilizing the TLSv1.2 or TLSv1.3 protocol for enhanced security and data encryption. 82 | 83 | These guidelines ensure the robustness, security, and efficient functioning of the infrastructure while adhering to best practices and industry standards. 84 | 85 | ### Basic Commands 86 | 87 | - To build a Docker image: 88 | ``` 89 | docker build -t image_name 90 | ``` 91 | - To run a Docker container: 92 | ``` 93 | docker run -d --name container_name image_name 94 | ``` 95 | - To stop a Docker container: 96 | ``` 97 | docker stop container_name 98 | ``` 99 | - To remove a Docker container: 100 | ``` 101 | docker rm container_name 102 | ``` 103 | - To build and start Docker services using Docker Compose: 104 | ``` 105 | docker-compose up -d 106 | ``` 107 | 108 | - To stop Docker services using Docker Compose: 109 | ``` 110 | docker-compose down 111 | ``` 112 | - To access the MariaDB container: 113 | ``` 114 | docker exec -it mariadb_container_name mysql -u username -p 115 | ``` 116 | - To access the WordPress container: 117 | ``` 118 | docker exec -it wordpress_container_name bash 119 | ``` 120 | - To reload NGINX configuration: 121 | ``` 122 | nginx -s reload 123 | ``` 124 | - To test NGINX configuration: 125 | ``` 126 | nginx -t 127 | ``` 128 | - To view NGINX logs: 129 | ``` 130 | tail -f /var/log/nginx/error.log 131 | ``` 132 | ### Accessing the Infrastructure 133 | 134 | Once the setup is complete, you can access the infrastructure through the domain name specified in the project requirements. 135 | 136 | 137 | 138 | --------------------------------------------------------------------------------