{"id":13460399,"url":"https://github.com/waltergcc/42-inception","last_synced_at":"2025-03-24T19:32:04.653Z","repository":{"id":203980589,"uuid":"694434890","full_name":"waltergcc/42-inception","owner":"waltergcc","description":"A gateway to the DevOps universe through Docker and Docker Compose for deploying a functional web server using NGINX, Wordpress and a MariaDB with a complete Guide.","archived":false,"fork":false,"pushed_at":"2024-08-20T21:17:44.000Z","size":1906,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-29T06:33:26.060Z","etag":null,"topics":["docker","docker-compose","inception-42","mariadb","nginx","virtual-machine","wordpress"],"latest_commit_sha":null,"homepage":"","language":"Makefile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/waltergcc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-09-21T01:53:59.000Z","updated_at":"2024-10-04T19:09:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"09d50781-dfb4-49e6-aaaa-05749a75cf5c","html_url":"https://github.com/waltergcc/42-inception","commit_stats":null,"previous_names":["waltergcc/42-inception"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waltergcc%2F42-inception","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waltergcc%2F42-inception/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waltergcc%2F42-inception/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waltergcc%2F42-inception/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/waltergcc","download_url":"https://codeload.github.com/waltergcc/42-inception/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245338415,"owners_count":20599038,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","inception-42","mariadb","nginx","virtual-machine","wordpress"],"created_at":"2024-07-31T10:00:41.257Z","updated_at":"2025-03-24T19:32:04.371Z","avatar_url":"https://github.com/waltergcc.png","language":"Makefile","funding_links":[],"categories":["WELCOME"],"sub_categories":["**Inception**"],"readme":"# Inception\n\nThis project is an introduction to the DevOps world. Its purpose is to introduce us to the use of docker and docker-compose to deploy a small web server that use the NGINX server with a Wordpress website and a MariaDB database. It's a simple project, but it's very important to understand the DevOps basic concepts. \n\n## Grade: 100/100\n\n# The Inception Guide\nThis project will cover concepts that we didn't see previously, so I recommend you to start backward to front in your PC, then you try it in the VM. On this page I'll leave a guide that will follow this order. At the end, you will have a VM with docker and docker-compose installed, and you'll be able to deploy a wordpress website with a mariadb database hosted with NGINX server.\n\n## Table of Contents\n- [1. The Containers](#1-the-containers)\n\t- [1.1. mariaDB](#11-mariadb)\n\t\t- [1.1.1. Dockerfile](#111-dockerfile)\n\t\t- [1.1.2. 50-server.cnf](#112-50-servercnf)\n\t\t- [1.1.3. setup.sh](#113-setupsh)\n\t\t- [1.1.4. Test the mariadb container](#114-test-the-mariadb-container)\n\t- [1.2. Wordpress](#12-wordpress)\n\t\t- [1.2.1. Dockerfile](#121-dockerfile)\n\t\t- [1.2.2. www.conf](#122-wwwconf)\n\t\t- [1.2.3. wp-config.php](#123-wp-configphp)\n\t\t- [1.2.4. setup.sh](#124-setupsh)\n\t\t- [1.2.5. Test the wordpress container](#125-test-the-wordpress-container)\n\t- [1.3. NGINX](#13-nginx)\n\t\t- [1.3.1. The Dockerfile](#131-the-dockerfile)\n\t\t- [1.3.2. server.conf](#132-serverconf)\n\t\t- [1.3.3. nginx.conf](#133-nginxconf)\n\t\t- [1.3.4. Test the nginx image](#134-test-the-nginx-image)\n- [2. Docker-compose](#2-docker-compose)\n\t- [2.1. docker-compose.yml](#21-docker-composeyml)\n\t- [2.2. .env](#22-env)\n\t- [2.3. docker-compose test](#23-docker-compose-test)\n- [3. The Makefile](#3-the-makefile)\n- [4. The VM](#4-the-vm)\n\t- [4.1. VM creation](#41-vm-creation)\n\t- [4.2. Debian installation](#42-debian-installation)\n\t- [4.3. VM Setup](#43-vm-setup)\n\t\t- [4.3.1. Add user as sudo](#431-add-user-as-sudo)\n\t\t- [4.3.2. Enable Shared Folders](#432-enable-shared-folders)\n\t\t- [4.3.3. Install Docker and docker-compose](#433-install-docker-and-docker-compose)\n\t\t- [4.3.4. Install make and hostsed](#434-install-make-and-hostsed)\n- [5. The Website](#5-the-website)\n\t- [5.1. Add your files in the VM](#51-add-your-files-in-the-vm)\n\t- [5.2. Start the containers](#52-start-the-containers)\n\t- [5.3. Credentials check](#53-credentials-check)\n\t- [5.4. mariaDB check](#54-mariadb-check)\n\t\n\n## 1. The Containers\n\nFirst of all, you need to understand the basic of `docker`. I'll leave a guide that helped me with the docker and start my first `container`.\n\nFollow the link: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04\n\n**PS:** I very much recommend you follow the part of the guide above that teach how to create a non-root user for the docker. This will help you a lot in the future.\n\nNow, we'll create our owns containers one per service. We'll create a folder with the service name, then inside we'll create the `Dockerfile` and the folder `conf` and `tools` when it's necessary.\n\nI'll cover the important things that you need to know on each service, but inside the repository you can find the files with comments to see how it works too. Every time something new appears, I'll try to explain what it's, but the next time I'll only show the command. Therefore, the first services will have more explanations than the last one.\n\n**Disclaimer:** The subject informs that we need to use the penultimate stable version of debian or alpine. The latest stable debian version in September 2023 is debian 12 (bookworm). You can check this [here](https://www.debian.org/releases/). Because all of that, I used the debian 11 (bullseye) for all images.\n\n### 1.1. mariaDB\nFiles: [Dockerfile](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/mariadb/Dockerfile), [conf/50-server.cnf](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/mariadb/conf/50-server.cnf), [tools/setup.sh](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/mariadb/tools/setup.sh)\n\n#### 1.1.1. Dockerfile\n1. Use the debian 11 (bullseye) image\n```Dockefile\nFROM debian:bullseye\n```\n2. Indicates that this container will be listening on port 3306\n```Dockerfile\nEXPOSE 3306\n```\n3. Update the system and install the mariadb-server only. The `--no-install-recommends` and `--no-install-suggests` flags are used to avoid installing unnecessary packages. I used the the commands with `\u0026\u0026` to avoid creating unnecessary layers. You can check more about the best practices [here](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/). the `rm -rf /var/lib/apt/lists/*` is used to clean the apt cache and avoid unnecessary files in the image.\n```Dockerfile\nRUN\tapt update \u0026\u0026 \\\n\tapt install -y --no-install-recommends --no-install-suggests \\\n\tmariadb-server \u0026\u0026 \\\n\trm -rf /var/lib/apt/lists/*\n```\n4. Copy the configuration file to the container. The first argument is the file path in the host, and the second is the file path that will receive the file.\n```Dockerfile\nCOPY\tconf/50-server.cnf /etc/mysql/mariadb.conf.d/\n```\n5. Copy the setup script to the container and change its permissions\n```Dockerfile\nCOPY\ttools/setup.sh /bin/\nRUN\tchmod +x /bin/setup.sh\n```\n6. Execute the setup script then start the database server. At the end of the script, it'll call the `mysqld_safe` command to start the database server.\n```Dockerfile\nCMD\t[\"setup.sh\", \"mysqld_safe\"]\n```\n#### 1.1.2. 50-server.cnf\nIt's a default file without the commented lines. The important thing here is change this: `port=3306`.\n\n#### 1.1.3. setup.sh\n1. Start the database server\n```bash\nservice mariadb start\n```\n2. To check if all is ok, we'll declare these variables in the own script, but in the final version we'll have a .env file with all the variables. So you need to remove these declaration lines.\n```bash\nDB_NAME=thedatabase\nDB_USER=theuser\nDB_PASSWORD=abc\nDB_PASS_ROOT=123\n```\n3. Create the database and the users with its passwords and permissions.\n```bash\nmariadb -v -u root \u003c\u003c EOF\nCREATE DATABASE IF NOT EXISTS $DB_NAME;\nCREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASSWORD';\nGRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'%' IDENTIFIED BY '$DB_PASSWORD';\nGRANT ALL PRIVILEGES ON $DB_NAME.* TO 'root'@'%' IDENTIFIED BY '$DB_PASS_ROOT';\nSET PASSWORD FOR 'root'@'localhost' = PASSWORD('$DB_PASS_ROOT');\nEOF\n```\n4. Prepare to restart the server to apply the changes. The `sleep` command is used to avoid errors before stopping the server.\n```bash\nsleep 5\nservice mariadb stop\n```\n5. Restart the server with the command passed as argument in the `Dockerfile`.\n```bash\nexec $@\n```\n#### 1.1.4. Test the mariadb container\nNow, you can build your container and tests it. Inside the folder `mariadb`, run the following command. `build` is the command to build the image, and `-t` is the tag name and `mariadb` is the name that I recommend and `.` indicates that the `Dockerfile` is in the current folder.\n```bash\ndocker build -t mariadb .\n```\nThen, run the container with the following command. `run` is the command to run the container, `-d` is the flag to run the container in background, and `mariadb` is the name of the image that we want to run.\n```bash\ndocker run -d mariadb\n```\nNow, run the following command to check if the container is running and get its ID.\n```bash\ndocker ps -a\n```\nWith the ID copied, run the next command to get inside the container. `exec` is the command to execute a command inside the container, `-it` is the flag to run the command in interactive mode, and `ID` is the ID of the container and `/bin/bash` is the command that we want to execute, in this case we want to use its terminal.\n```bash\ndocker exec -it copiedID /bin/bash\n```\nNow, you are inside the container. Run the following command to check if the database is created correctly and running. \n```bash\nmysql -u theuser -p thedatabase\n```\nif you see the the prompt `MariaDB [thedatabase]\u003e` it means that all is ok. Too see the tables, run the following command. For now, we don't have any table, so it'll return an empty set, But at the end of the project, it'll have some tables created by wordpress.\n```bash\nSHOW TABLES;\n```\nNow, to exit mysql, run `exit` then run `exit` again to exit the container. So it's all working, then we'll clean our container test. To stop the container, remove it and the image run the following commands.\n```bash\ndocker rm -f $(docker ps -aq) \u0026\u0026  docker rmi -f $(docker images -aq)\n```\n\n### 1.2. Wordpress\nFiles: [Dockerfile](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/wordpress/Dockerfile), [conf/wp-config.php](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/wordpress/conf/wp-config.php), [conf/www.conf](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/wordpress/conf/www.conf), [tools/setup.sh](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/wordpress/tools/setup.sh)\n\n#### 1.2.1. Dockerfile\n1. Use the debian 11 (bullseye) image\n2. Indicates that this container will be listening on port 9000\n3. Set a variable to use in the next commands. `ARG` is only avaliable in the build time.\n```Dockerfile\nARG\tPHPPATH=/etc/php/7.4/fpm\n```\n4. Update the system and install `ca-certificates`, `php7.4-fpm`, `php7.4-mysql`, `wget` and `tar`.\n5. After the php installation, it's running, so we need to stop it to change the configuration file.\n```Dockerfile\nRUN\tservice php7.4-fpm stop\n```\n6. Copy the configuration file to the php folder, then change some values in the php config files. \n```Dockerfile\nCOPY\tconf/www.conf ${PHPPATH}/pool.d/\nRUN\t\tsed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${PHPPATH}/php.ini \u0026\u0026 \\\n\t\tsed -i \"s/listen = \\/run\\/php\\/php$PHP_VERSION_ENV-fpm.sock/listen = 9000/g\" ${PHPPATH}/pool.d/www.conf \u0026\u0026 \\\n\t\tsed -i 's/;listen.mode = 0660/listen.mode = 0660/g' ${PHPPATH}/pool.d/www.conf \u0026\u0026 \\\n\t\tsed -i 's/;daemonize = yes/daemonize = no/g' ${PHPPATH}/pool.d/www.conf\n```\n7. Download the wordpress CLI, change its permissions and move it to the `bin/wp` folder.\n```Dockerfile\nRUN\twget --no-check-certificate https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \u0026\u0026 \\\n\tchmod +x wp-cli.phar \u0026\u0026 \\\n\tmv wp-cli.phar /usr/local/bin/wp\n```\n8. Create some folders needed by the wordpress files and change its owner to `www-data` user.\n```Dockerfile\nRUN\tmkdir -p /run/php/ \u0026\u0026 \\\n\tmkdir -p /var/run/php/ \u0026\u0026 \\\n\tmkdir -p /var/www/inception/\n\nRUN\tchown -R www-data:www-data /var/www/inception/\n```\n9. Copy the wp-config.php and the setup script to the container and change its permissions\n10. Execute the setup script then start the php server. `--nodaemonize` is used to avoid the php server to run in background.\n```Dockerfile\nCMD\t[\"setup.sh\", \"php-fpm7.4\", \"--nodaemonize\"]\n```\n#### 1.2.2. www.conf\nIt's a default file that the most important thing here is change the user, group and port.\n```conf\nuser = www-data\ngroup = www-data\nlisten = 9000\n```\n#### 1.2.3. wp-config.php\nIt's a default file. The important thing here is change some lines to use our database. For now, we'll use test values, but after we need to change it to the .env variables.\n```php\ndefine( 'DB_NAME', getenv('thedatabase') );\ndefine( 'DB_USER', getenv('theuser') );\ndefine( 'DB_PASSWORD', getenv('abc') );\ndefine( 'DB_HOST', getenv('mariadb') );\ndefine( 'WP_HOME', getenv('https://login.42.fr') );\ndefine( 'WP_SITEURL', getenv('https://login.42.fr') );\n\n```\n#### 1.2.4. setup.sh\n1. Change the owner of the wordpress files to `www-data` user.\n```bash\nchown -R www-data:www-data /var/www/inception/\n```\n2. Move the wp-config.php file to the wordpress folder if it isn't there.\n```bash\nif [ ! -f /var/www/inception/wp-config.php ]; then\n\tmv /tmp/wp-config.php /var/www/inception/\nfi\n```\n3. Create the temp var to be used now, but at the end, we'll have a .env file with all the variables. So you need to remove these declaration lines.\n```bash\nWP_URL=login.42.fr\nWP_TITLE=Inception\nWP_ADMIN_USER=theroot\nWP_ADMIN_PASSWORD=123\nWP_ADMIN_EMAIL=theroot@123.com\nWP_USER=theuser\nWP_PASSWORD=abc\nWP_EMAIL=theuser@123.com\nWP_ROLE=editor\n```\n4. Dowload the wordpress files.\n```bash\nsleep 10\nwp --allow-root --path=\"/var/www/inception/\" core download || true\n```\n5. If the wordpress files aren't there, create install wordpress and set it, if not move foward.\n```bash\nif ! wp --allow-root --path=\"/var/www/inception/\" core is-installed;\nthen\n    wp  --allow-root --path=\"/var/www/inception/\" core install \\\n        --url=$WP_URL \\\n        --title=$WP_TITLE \\\n        --admin_user=$WP_ADMIN_USER \\\n        --admin_password=$WP_ADMIN_PASSWORD \\\n        --admin_email=$WP_ADMIN_EMAIL\nfi;\n```\n6. Create the non-admin user and set its role.\n```bash\nif ! wp --allow-root --path=\"/var/www/inception/\" user get $WP_USER;\nthen\n    wp  --allow-root --path=\"/var/www/inception/\" user create \\\n        $WP_USER \\\n        $WP_EMAIL \\\n        --user_pass=$WP_PASSWORD \\\n        --role=$WP_ROLE\nfi;\n```\n7. Download another theme and activate it. It's not necessary, but I did because I don't like the default theme.\n```bash\nwp --allow-root --path=\"/var/www/inception/\" theme install raft --activate \n```\n8. start the php server in foreground.\n```bash\nexec $@\n```\n#### 1.2.5. Test the wordpress container\nGo to the wordpress folder and run the following command .\n```bash\ndocker build -t wordpress .\ndocker run -d wordpress\ndocker ps -a\ndocker exec -it copiedID /bin/bash\n```\nNow, you are inside the container. Run the following command to check if the wordpress files are there. The sleep here is used to give time to the container to download the files.\n```bash\nsleep 30 \u0026\u0026 ls /var/www/inception/\n```\nIf you see the wordpress files, it means that all is ok. At the moment we won't check if the containers is talking with each other because we'll do it with the compose file. So, exits the container and let's clean our container test.\n```bash\ndocker rm -f $(docker ps -aq) \u0026\u0026  docker rmi -f $(docker images -aq)\n```\n### 1.3. NGINX\nFiles: [Dockerfile](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/nginx/Dockerfile), [conf/server.conf](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/nginx/conf/server.conf), [conf/nginx.conf](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/requirements/nginx/conf/nginx.conf)\n\n#### 1.3.1. The Dockerfile\n1. Use the debian 11 (bullseye) image\n2. Indicates that this container will be listening on port 443\n3. Update the system and install `nginx`, `openssl` only\n4. Define the ARG to use in the next commands. At the final version, we'll have a .env file with all the variables, so you need to remove these declaration lines and keep the line that call all variables. \n```Dockerfile\nARG\tCERT_FOLDER=/etc/nginx/certs/\nARG\tCERTIFICATE=/etc/nginx/certs/certificate.crt\nARG\tKEY=/etc/nginx/certs/certificate.key\nARG\tCOUNTRY=BR\nARG\tSTATE=BA\nARG\tLOCALITY=Salvador\nARG\tORGANIZATION=42\nARG\tUNIT=42\nARG\tCOMMON_NAME=login.42.fr\n```\n5. Create the folder for the certificates and generate these. It'll create a self-signed certificate that will be valid for 365 days. The `subj` flag is used to set the certificate information.\n```Dockerfile\nRUN\tmkdir -p ${CERT_FOLDER} \u0026\u0026 \\\n\topenssl req -newkey rsa:4096 -x509 -sha256 -days 365 -nodes \\\n\t-out ${CERTIFICATE} \\\n\t-keyout ${KEY} \\\n\t-subj \"/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${UNIT}/CN=${COMMON_NAME}\"\n```\n6. Copy the configuration files to the container and complete the server.conf file with the variables that will be passed by the .env file.\n```Dockerfile\nCOPY\tconf/nginx.conf\t/etc/nginx/\nCOPY\tconf/server.conf\t/etc/nginx/conf.d/\n\nRUN\techo \"\\tserver name ${COMMON_NAME};\\n\\\n\t\\tssl_certificate ${CERTIFICATE};\\n\\\n\t\\tssl_certificate_key ${KEY};\\n\\\n\t}\" \u003e\u003e /etc/nginx/conf.d/server.conf\n```\n7. Create the folder for the wordpress files and change its owner to `www-data` user.\n```Dockerfile\nRUN\tmkdir -p /var/www/\nRUN\tchown -R www-data:www-data /var/www/\n```\n8. Start the nginx server in foreground.\n```Dockerfile\nCMD\t[\"nginx\", \"-g\", \"daemon off;\"]\n```\n#### 1.3.2. server.conf\nThe important thing here is change the set the port to 443 and ssl protocols to TLSv1.2 and the root folder to `/var/www/inception/`.\n```conf\nlisten 443 ssl;\nlisten [::]:443 ssl;\nssl_protocols TLSv1.2;\nroot /var/www/inception/;\nindex index.php index.html;\n```\nAt the end, the file has missing lines that will be completed in the Dockerfile. These are the information about the certificates that will be passed by the .env file. It's important that we never public files with confidential information.\n\n#### 1.3.3. nginx.conf\nThe important thing here is change the user to `www-data` and set communication with php-fpm to port 9000 to use the wordpress files.\n```conf\nuser www-data;\nupstream php7.4-fpm\n{\n\tserver wordpress:9000;\n}\n```\n#### 1.3.4. Test the nginx image\nGo to the nginx folder and run the following command. This time we don't run the container because it need to connect with the wordpress container. And we'll do it with the compose file. We'll the built command only to check if the image is ok then we'll remove it.\n```bash\ndocker build -t nginx .\ndocker images\ndocker rmi -f nginx\n```\n## 2. Docker-compose\nNow that we have all Dockerfiles working well, we'll create the docker-compose file to run all containers together. Before we start, we need to create setup the docker-compose plugin. \n\nCheck if the plugin is already installed with the command:\n```bash\ndocker compose version\n```\nIf it's not installed, run the following command:\n```bash\nsudo apt-get install docker-compose-plugin\n```\nFiles: [requirements](https://github.com/waltergcc/42-inception/tree/main/inception/srcs/requirements), [docker-compose.yml](https://github.com/waltergcc/42-inception/blob/main/inception/srcs/docker-compose.yml), .env\n\nNow you'll create a folder called `requirements` and inside it put all the folders that we created before. Then, create a file called `docker-compose.yml` and a file called `.env`.\n\n### 2.1. docker-compose.yml\nStart it with the following line to start the services definition.\n```yml\nservices:\n```\nThen define the mariadb service. It's field are self-explanatory. Build is where the Dockerfile is, volumes is where the database files will be saved in the container, networks is the network that the container will use, init is used to run the setup.sh script, restart is used to restart the container if it fails, and env_file is the file that contains the variables that will be used in the container.\n```yml\n  mariadb:\n    container_name: mariadb\n    build: ./requirements/mariadb/\n    volumes:\n      - database:/var/lib/mysql/\n    networks:\n      - all\n    init: true\n    restart: on-failure\n    env_file:\n      - .env\n```\nThe wordpress service is similar to the mariadb service, but it has a depends_on field that indicates that the wordpress container will only start after the mariadb container is running and volume and the build path are different.\n```yml\n  wordpress:\n    container_name: wordpress\n    build: ./requirements/wordpress/\n    volumes:\n      - wordpress_files:/var/www/inception/\n    networks:\n      - all\n    init: true\n    restart: on-failure\n    env_file:\n      - .env\n    depends_on:\n      - mariadb\n```\nthe NGINX service depends on the wordpress service and has a ports field that indicates that the container will be listening on port 443. The build field beyound the path, it has some arguments that will be used in the Dockerfile given by the .env file.\n```yml\nnginx:\n    container_name: nginx\n    build:\n      context: ./requirements/nginx/\n      args:\n        CERT_FOLDER: ${CERT_FOLDER}\n        CERTIFICATE: ${CERTIFICATE}\n        KEY: ${KEY}\n        COUNTRY: ${COUNTRY}\n        STATE: ${STATE}\n        LOCALITY: ${LOCALITY}\n        ORGANIZATION: ${ORGANIZATION}\n        UNIT: ${UNIT}\n        COMMON_NAME: ${COMMON_NAME}\n    ports:\n      - '443:443'\n    volumes:\n      - wordpress_files:/var/www/inception/\n    networks:\n      - all\n    init: true\n    restart: on-failure\n    env_file:\n      - .env\n    depends_on:\n      - wordpress\n```\n\nThe volumes define the local host folder that will be used to save the database and the wordpress files. The subject informs that the data must be in user home directory. This volumes will work like a shared folder between the host and the containers.\n```yml\nvolumes:\n\n  database:\n    driver: local\n    driver_opts:\n      type: none\n      o: bind\n      device: ~/data/database\n\n  wordpress_files:\n    driver: local\n    driver_opts:\n      type: none\n      o: bind\n      device: ~/data/wordpress_files\n```\nThe networks define the network that the containers will use to communicate with each other. This is like a virtual switch that will connect the containers. \n```yml\nnetworks:\n  all:\n    driver: bridge\n```\n### 2.2. .env\nIn this file, we'll put all the variables that we'll use in the docker-compose file. It's important that we never public files with confidential information. You'll put your .env file in the repo only in the evaluation time. Don't forget to remove the test variables that we used before in `mariadb/tools/setup.sh`, `wordpress/conf/wp-config.php`, `wordpress/tools/setup.sh` and `nginx/Dockerfile`. \n\nIn the nginx Dockerfile we'll keep this line:\n```Dockerfile\nARG\tCERT_FOLDER CERTIFICATE KEY COUNTRY STATE LOCALITY ORGANIZATION UNIT COMMON_NAME\n```\nNow, the .env file will have the following variables:\n\n```bash\n# Database settings\nDB_NAME=thedatabase\nDB_USER=theuser\nDB_PASSWORD=abc\nDB_PASS_ROOT=123\nDB_HOST=mariadb\n\n# Wordpress settings\nWP_URL=login.42.fr\nWP_TITLE=Inception\nWP_ADMIN_USER=theroot\nWP_ADMIN_PASSWORD=123\nWP_ADMIN_EMAIL=theroot@123.com\nWP_USER=theuser\nWP_PASSWORD=abc\nWP_EMAIL=theuser@123.com\nWP_ROLE=editor\nWP_FULL_URL=https://login.42.fr\n\n# SSL settings\nCERT_FOLDER=/etc/nginx/certs/\nCERTIFICATE=/etc/nginx/certs/certificate.crt\nKEY=/etc/nginx/certs/certificate.key\nCOUNTRY=BR\nSTATE=BA\nLOCALITY=Salvador\nORGANIZATION=42\nUNIT=42\nCOMMON_NAME=login.42.fr\n```\n### 2.3. docker-compose test\nNow, all is setup correctly, so we can start the containers together. Go to the folder that contains the docker-compose.yml file and run the following command:\n```bash\ndocker compose up\n```\nIf all is ok, you'll see the containers running and the terminal won't return the prompt. Now to test, go to your browser and type the following address:\n```bash\nhttps://localhost\n```\nIf all is ok, you can see the wordpress page. We're close to the end, but we need to do some more things. Let's clean our test. First, stop the compose with `ctrl + c` then run the following command to clean the containers, images, volumes and networks.\n```bash\ndocker stop $(docker ps -qa) \u0026\u0026 \\\n\tdocker rm -f $(docker ps -qa) \u0026\u0026 \\\n\tdocker rmi -f $(docker images -qa) \u0026\u0026 \\\n\tdocker volume rm $(docker volume ls -q) \u0026\u0026 \\\n\tdocker network rm $(docker network ls -q) 2\u003e /dev/null\n```\n## 3. The Makefile\nFiles: [srcs](https://github.com/waltergcc/42-inception/tree/main/inception/srcs), \n [Makefile](https://github.com/waltergcc/42-inception/blob/main/inception/Makefile)\n\nBefore all, create a folder called `srcs` and put all files that we created before inside it.\n\nInstall the `hostsed` package to make easy the way to put our host url in the `/etc/hosts` file. Run the following command:\n```bash\nsudo apt-get install hostsed\n```\nNow, we'll create a Makefile to run the docker-compose commands. In my Makefile I've implemented some more commands, but in a simple way, it must have at lest two rules: `up` and `down`.\n```Makefile\nNAME\t\t= inception\nSRCS\t\t= ./srcs\nCOMPOSE\t\t= $(SRCS)/docker-compose.yml\nHOST_URL\t= login.42.fr\n```\nThe up rule will create the folders that will be used to save the database and the wordpress files, add the host url to the `/etc/hosts` file, then run the docker-compose command.\n```Makefile\nup:\n\tmkdir -p ~/data/database\n\tmkdir -p ~/data/wordpress_files\n\tsudo hostsed add 127.0.0.1 $(HOST_URL)\n\tdocker compose -p $(NAME) -f $(COMPOSE) up --build || (echo \" $(FAIL)\" \u0026\u0026 exit 1)\n```\nThe down rule will remove the host url from the `/etc/hosts` file, then run the docker-compose command to stop the containers.\n```Makefile\n\tsudo hostsed rm 127.0.0.1 $(HOST_URL)\n\tdocker compose -p $(NAME) down\n```\nAfter that, if will want, you can create more rules. But for now. Our Makefile is ready to use, so in its folder, run `make up`, so you can go to your browser and type the following address:\n```bash\nhttps://login.42.fr\n```\nIf all is ok, you can see the wordpress page. Now, to stop the containers, press in the running terminal `Ctrl + C` then run `make down`.\n\nNow, Our needed files are ready. So we can go to the VM setup.\n\n## 4. The VM\nThis stage will have a lot of steps, but after that you're be able to deploy your website in your VM, so let's go.\n\n### 4.1. VM creation\n1. Download debian image. I prefer to use the Debian 11. Follow the link:\nhttps://cdimage.debian.org/cdimage/archive/11.7.0/amd64/iso-cd/debian-11.7.0-amd64-netinst.iso\n2. Open the VirtualBox and create a new VM as Linux Debian 64 bits.\n3. Set the RAM to 4096 MB\n4. Create a dynamic VDI with at least 30 GB\n5. Go to the VM settings \u003e System \u003e Motherboard and set the boot order to Optical, Hard Disk, Network.\n6. Then at processor tab, set the number of processors to 4.\n7. In the display menu, set the video memory to 128 MB.\n8. In the audio menu, disable the audio.\n9. In the network menu, set the network to NAT.\n10. In the storage, select the CD icon and select the debian image that you downloaded.\n11. Now start your VM.\n\n### 4.2. Debian installation\n1. Select install\n2. then follow the normal installation steps, choosing region, user, password, etc. Nothing special here.\n3. In the partition menu, select the guided - use entire disk - LVM\n4. After that, select separate var/ tmp/ home/ partitions and Confirm it.\n5. In the software selection, select only XFCE, Webserver, SSH server and standard system utilities.\n6. In the GRUB menu, select yes and select the disk that you created.\n7. At the end, your VM will reboot with the debian installed.\n\n### 4.3. VM setup\n\n#### 4.3.1. Add user as Sudo\nAccess as root and add the user to the sudo group.\n```bash\nsu -\nusermod -aG sudo user\n```\nAfter that, add the user into sudoers file.\n```bash\nsudo visudo\n```\nThen add the following line in the end of the file and save it.\n```bash\nuser ALL=(ALL) ALL\n```\nNow, reboot the VM.\n\n#### 4.3.2. Enable the Shared folder\n1. In your main PC, create a folder in your home directory called `shared` . This folder will be used to share files between your main PC and the VM.\n2. In the VirtualBox settings \u003e Shared Folders, add a new shared folder with the name `shared` and the path to the folder that you created in your main PC and check the auto-mount and make permanent options.\n3. Now, in the VM, at the VirtualBox menu \u003e Devices \u003e select insert Guest Additions CD image.\n4. Open the terminal in the CD folder and run the following command.\n```bash\nsudo sh VBoxLinuxAdditions.run\nsudo reboot\n```\n5. add your user to the vboxsf group and define your user as owner of the shared folder.\n```bash\nsudo usermod -a -G vboxsf your_user\nsudo chown -R your_user:users /media/\n```\n6. Logout and login again to apply the changes. Now, you can see the shared folder in the `/media` folder as a external device.\n7. (Optional) If you want to enable the copy and paste between the VM and your main PC, go to the VM menu \u003e Devices \u003e Shared Clipboard \u003e Bidirectional. With this option, you can copy and paste text between the VM and your main PC.\n\n#### 4.3.3. Install Docker and docker-compose\nPrepare the docker repository installation\n```bash\n# Add Docker's official GPG key:\nsudo apt-get update\nsudo apt-get install ca-certificates curl gnupg\nsudo install -m 0755 -d /etc/apt/keyrings\ncurl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg\nsudo chmod a+r /etc/apt/keyrings/docker.gpg\n\n# Add the repository to Apt sources:\necho \\\n  \"deb [arch=\"$(dpkg --print-architecture)\" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \\\n  \"$(. /etc/os-release \u0026\u0026 echo \"$VERSION_CODENAME\")\" stable\" | \\\n  sudo tee /etc/apt/sources.list.d/docker.list \u003e /dev/null\nsudo apt-get update\n```\nThen install docker and plugins\n```bash\nsudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n```\nNow add your user to the docker group. It's important use the docker commands without sudo.\n```bash\nsudo usermod -aG docker your_user\nsu - your_user\nsudo reboot\n```\nNow check if the docker is working well with the following command:\n```bash\ndocker run hello-world\n```\n#### 4.3.4. Install make and hostsed\n```bash\nsudo apt-get install -y make hostsed\n```\n## 5. The Website\n\n### 5.1. Add your files in the VM\n1. Copy your repo link in your main PC and go to the shared folder. Then clone it or copy and paste your files in the shared folder.\n2. Copy your confidential .env file from your main PC to the VM. Paste it in folder srcs, inside the shared folder.\n\n### 5.2. Start the containers\n1. Go to the root of your project and run `make up`\n2. Go to your browser and type the following address:\n```bash\nhttps://login.42.fr\n```\nIf all is ok, you can see the wordpress page.\n### 5.3. Credentials check\n1. Try to input the follow link in your browser. If all is ok, you can't connect to the database because you'll try to connect with wrong port.\n```bash\nhttp://login.42.fr\n```\n2. Go back to right link, click in the lock icon in the left of the address bar and click in the certificate option to see the certificate information.\n3. Now, enter in your browser with the following link to acess the wordpress admin page. Try to login with the admin user and the user. If all is ok, you can see the admin page dashboard.\n```bash\nhttps://login.42.fr/wp-admin\n```\n\n### 5.4. mariaDB check\nOpen another terminal and keep the terminal with the compose running. On this other terminal, run the following command to enter in the mariadb container.\n```bash\ndocker exec -it mariadb /bin/bash\n```\nThen run the command to enter in the mysql\n```bash\nmysql -u your_user -p db_name\n```\nThen run the command to see the tables\n```bash\nSHOW TABLES;\n```\nIf you see the tables, it means that all is ok. If you want to see the database, run the following command:\n```bash\nSELECT * FROM table_name\\G;\n```\nAnd if you want to delete a row in a table, run the following command:\n```bash\nDELETE FROM table_name WHERE column_name = some_value;\n```\nAfter that, you can exit the mysql and the container and all your project work is done. Congratulations!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaltergcc%2F42-inception","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwaltergcc%2F42-inception","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaltergcc%2F42-inception/lists"}