One place for hosting & domains

      How To Manage and Use MySQL Database Triggers on Ubuntu 18.04


      The author selected the the Apache Software Foundation to receive a donation as part of the Write for DOnations program.

      Introduction

      In MySQL a trigger is a user-defined SQL command that is invoked automatically during an INSERT, DELETE, or UPDATE operation. The trigger code is associated with a table and is destroyed once a table is dropped. You can specify a trigger action time and set whether it will be activated before or after the defined database event.

      Triggers have several advantages. For instance, you can use them to generate the value of a derived column during an INSERT statement. Another use case is enforcing referential integrity where you can use a trigger to save a record to multiple related tables. Other benefits include logging user actions to audit tables as well as live-copying data across different database schemas for redundancy purposes to prevent a single point of failure.

      You can also use triggers to keep validation rules at the database level. This helps in sharing the data source across multiple applications without breaking the business logic. This greatly reduces round-trips to the database server, which therefore improves the response time of your applications. Since the database server executes triggers, they can take advantage of improved server resources such as RAM and CPU.

      In this tutorial, you’ll create, use, and delete different types of triggers on your MySQL database.

      Prerequisites

      Before you begin, make sure you have the following:

      Step 1 — Creating a Sample Database

      In this step, you’ll create a sample customer database with multiple tables for demonstrating how MySQL triggers work.

      To understand more about MySQL queries read our Introduction to Queries in MySQL.

      First, log in to your MySQL server as root:

      Enter your MySQL root password when prompted and hit ENTER to continue. When you see the mysql> prompt, run the following command to create a test_db database:

      Output

      Query OK, 1 row affected (0.00 sec)

      Next, switch to the test_db with:

      Output

      Database changed

      You’ll start by creating a customers table. This table will hold the customers’ records including the customer_id, customer_name, and level. There will be two customer levels: BASIC and VIP.

      • Create table customers(customer_id BIGINT PRIMARY KEY, customer_name VARCHAR(50), level VARCHAR(50) ) ENGINE=INNODB;

      Output

      Query OK, 0 rows affected (0.01 sec)

      Now, add a few records to the customers table. To do this, run the following commands one by one:

      • Insert into customers (customer_id, customer_name, level )values('1','JOHN DOE','BASIC');
      • Insert into customers (customer_id, customer_name, level )values('2','MARY ROE','BASIC');
      • Insert into customers (customer_id, customer_name, level )values('3','JOHN DOE','VIP');

      You’ll see the following output after running each of the INSERT commands:

      Output

      Query OK, 1 row affected (0.01 sec)

      To make sure that the sample records were inserted successfully, run the SELECT command:

      Output

      +-------------+---------------+-------+ | customer_id | customer_name | level | +-------------+---------------+-------+ | 1 | JOHN DOE | BASIC | | 2 | MARY ROE | BASIC | | 3 | JOHN DOE | VIP | +-------------+---------------+-------+ 3 rows in set (0.00 sec)

      You’ll also create another table for holding related information about the customers account. The table will have a customer_id and status_notes fields.

      Run the following command:

      • Create table customer_status(customer_id BIGINT PRIMARY KEY, status_notes VARCHAR(50)) ENGINE=INNODB;

      Next, you’ll create a sales table. This table will hold sales data related to the different customers through the customer_id column:

      • Create table sales(sales_id BIGINT PRIMARY KEY, customer_id BIGINT, sales_amount DOUBLE ) ENGINE=INNODB;

      Output

      Query OK, 0 rows affected (0.01 sec)

      You’ll add sample data to the sales data in the coming steps while testing the triggers. Next, create an audit_log table to log updates made to the sales table when you implement the AFTER UPDATE trigger in Step 5:

      • Create table audit_log(log_id BIGINT PRIMARY KEY AUTO_INCREMENT, sales_id BIGINT, previous_amount DOUBLE, new_amount DOUBLE, updated_by VARCHAR(50), updated_on DATETIME ) ENGINE=INNODB;

      Output

      Query OK, 0 rows affected (0.02 sec)

      With the test_db database and the four tables in place, you’ll now move on to work with the different MySQL triggers in your database.

      Step 2 — Creating a Before Insert Trigger

      In this step, you’ll examine the syntax of a MySQL trigger before applying this logic to create a BEFORE INSERT trigger that validates the sales_amount field when data is inserted into the sales table.

      The general syntax for creating a MySQL trigger is shown in the following example:

      DELIMITER //
      CREATE TRIGGER [TRIGGER_NAME]
      [TRIGGER TIME] [TRIGGER EVENT]
      ON [TABLE]
      FOR EACH ROW
      [TRIGGER BODY]//
      DELIMITER ;
      

      The structure of the trigger includes:

      DELIMITER //: The default MySQL delimiter is ;—it’s necessary to change it to something else in order for MySQL to treat the following lines as one command until it hits your custom delimiter. In this example, the delimiter is changed to // and then the ; delimiter is redefined at the end.

      [TRIGGER_NAME]: A trigger must have a name and this is where you include the value.

      [TRIGGER TIME]: A trigger can be invoked during different timings. MySQL allows you to define if the trigger will initiate before or after a database operation.

      [TRIGGER EVENT]: Triggers are only invoked by INSERT, UPDATE, and DELETE operations. You can use any value here depending on what you want to achieve.

      [TABLE]: Any trigger that you create on your MySQL database must be associated with a table.

      FOR EACH ROW: This statement tells MySQL to execute the trigger code for every row that the trigger affects.

      [TRIGGER BODY]: The code that is executed when the trigger is invoked is called a trigger body. This can be a single SQL statement or multiple commands. Note that if you are executing multiple SQL statements on the trigger body, you must wrap them between a BEGIN...END block.

      Note: When creating the trigger body, you can use the OLD and NEW keywords to access the old and new column values entered during an INSERT, UPDATE, and DELETE operation. In a DELETE trigger, only the OLD keyword can be used (which you’ll use in Step 4).

      Now you’ll create your first BEFORE INSERT trigger. This trigger will be associated with the sales table and it will be invoked before a record is inserted to validate the sales_amount. The function of the trigger is to check if the sales_amount being inserted to the sales table is greater than 10000 and raise an error if this evaluates to true.

      Make sure you’re logged in to the MySQL server. Then, enter the following MySQL commands one by one:

      • DELIMITER //
      • CREATE TRIGGER validate_sales_amount
      • BEFORE INSERT
      • ON sales
      • FOR EACH ROW
      • IF NEW.sales_amount>10000 THEN
      • SIGNAL SQLSTATE '45000'
      • SET MESSAGE_TEXT = 'Sale has exceeded the allowed amount of 10000.';
      • END IF//
      • DELIMITER ;

      You’re using the IF...THEN...END IF statement to evaluate if the amount being supplied during the INSERT statement is within your range. The trigger is able to extract the new sales_amount value being supplied by using the NEW keyword.

      To raise a generic error message, you use the following lines to inform the user about the error:

      SIGNAL SQLSTATE '45000'
      SET MESSAGE_TEXT = 'Sale has exceeded the allowed amount of 10000.';
      

      Next, insert a record with a sales_amount of 11000 to the sales table to check if the trigger will stop the operation:

      • Insert into sales(sales_id, customer_id, sales_amount) values('1','1','11000');

      Output

      ERROR 1644 (45000): Sale has exceeded the allowed amount of 10000.

      This error shows that the trigger code is working as expected.

      Now try a new record with a value of 7500 to check if the command will be successful:

      • Insert into sales(sales_id, customer_id, sales_amount) values('1','1','7500');

      Since the value is within the recommended range, you’ll see the following output:

      Output

      Query OK, 1 row affected (0.01 sec)

      To confirm that the data was inserted run the following command:

      The output confirms that the data is in the table:

      Output

      +----------+-------------+--------------+ | sales_id | customer_id | sales_amount | +----------+-------------+--------------+ | 1 | 1 | 7500 | +----------+-------------+--------------+ 1 row in set (0.00 sec)

      In this step you’ve tested triggers to validate data before insertion into a database.

      Next, you’ll work with the AFTER INSERT trigger to save related information into different tables.

      Step 3 — Creating an After Insert Trigger

      AFTER INSERT triggers are executed when records are successfully inserted into a table. This functionality can be used to run other business-related logics automatically. For instance, in a bank application, an AFTER INSERT trigger can close a loan account when a customer finishes paying off the loan. The trigger can monitor all payments inserted to a transaction table and close the loan automatically once the loan balance is zero.

      In this step, you’ll work with your customer_status table by using an AFTER INSERT trigger to enter related customer records.

      To create the AFTER INSERT trigger, enter the following commands:

      • DELIMITER //
      • CREATE TRIGGER customer_status_records
      • AFTER INSERT
      • ON customers
      • FOR EACH ROW
      • Insert into customer_status(customer_id, status_notes) VALUES(NEW.customer_id, 'ACCOUNT OPENED SUCCESSFULLY')//
      • DELIMITER ;

      Output

      Query OK, 0 rows affected (0.00 sec)

      Here you instruct MySQL to save another record to the customer_status table once a new customer record is inserted to the customers table.

      Now, insert a new record in the customers table to confirm your trigger code will be invoked:

      • Insert into customers (customer_id, customer_name, level )values('4','DAVID DOE','VIP');

      Output

      Query OK, 1 row affected (0.01 sec)

      Since the record was inserted successfully, check that a new status record was inserted into the customer_status table:

      • Select * from customer_status;

      Output

      +-------------+-----------------------------+ | customer_id | status_notes | +-------------+-----------------------------+ | 4 | ACCOUNT OPENED SUCCESSFULLY | +-------------+-----------------------------+ 1 row in set (0.00 sec)

      The output confirms that the trigger ran successfully.

      The AFTER INSERT trigger is useful in monitoring the lifecycle of a customer. In a production environment, customers’ accounts may undergo different stages such as account opening, suspension, and closing.

      In the following steps you’ll work with UPDATE triggers.

      Step 4 — Creating a Before Update Trigger

      A BEFORE UPDATE trigger is similar to the BEFORE INSERT trigger—the difference is when they are invoked. You can use the BEFORE UPDATE trigger to check a business logic before a record is updated. To test this, you’ll use the customers table in which you’ve inserted some data already.

      You have two levels for your customers in the database. In this example, once a customer account is upgraded to the VIP level, the account can not be downgraded to the BASIC level. To enforce such a rule, you will create a BEFORE UPDATE trigger that will execute before the UPDATE statement as shown following. If a database user tries to downgrade a customer to the BASIC level from the VIP level, a user-defined exception will be triggered.

      Enter the following SQL commands one by one to create the BEFORE UPDATE trigger:

      • DELIMITER //
      • CREATE TRIGGER validate_customer_level
      • BEFORE UPDATE
      • ON customers
      • FOR EACH ROW
      • IF OLD.level='VIP' THEN
      • SIGNAL SQLSTATE '45000'
      • SET MESSAGE_TEXT = 'A VIP customer can not be downgraded.';
      • END IF //
      • DELIMITER ;

      You use the OLD keyword to capture the level that the user is supplying when running the UPDATE command. Again, you use the IF...THEN...END IF statement to signal a generic error statement to the user.

      Next, run the following SQL command that tries to downgrade a customer account associated with the customer_id of 3:

      • Update customers set level='BASIC' where customer_id='3';

      You’ll see the following output providing the SET MESSAGE_TEXT:

      Output

      ERROR 1644 (45000): A VIP customer can not be downgraded.

      If you run the same command to a BASIC level customer, and try to upgrade the account to the VIP level, the command will execute successfully:

      • Update customers set level='VIP' where customer_id='1';

      Output

      Rows matched: 1 Changed: 1 Warnings: 0

      You’ve used the BEFORE UPDATE trigger to enforce a business rule. Now you’ll move on to use an AFTER UPDATE trigger for audit logging.

      Step 5 — Creating an After Update Trigger

      An AFTER UPDATE trigger is invoked once a database record is updated successfully. This behavior makes the trigger suitable for audit logging. In a multi-user environment, the administrator may want to view a history of users updating records in a particular table for audit purposes.

      You’ll create a trigger that logs the update activity of the sales table. Our audit_log table will contain information about the MySQL users updating the sales table, the date of the update, and the new and old sales_amount values.

      To create the trigger, run the following SQL commands:

      • DELIMITER //
      • CREATE TRIGGER log_sales_updates
      • AFTER UPDATE
      • ON sales
      • FOR EACH ROW
      • Insert into audit_log(sales_id, previous_amount, new_amount, updated_by, updated_on) VALUES (NEW.sales_id,OLD.sales_amount, NEW.sales_amount,(SELECT USER()), NOW() )//
      • DELIMITER ;

      You insert a new record to the audit_log table. You use the NEW keyword to retrieve the value of the sales_id and the new sales_amount. Also, you use the OLD keyword to retrieve the previous sales_amount since you want to log both amounts for audit purposes.

      The command SELECT USER() retrieves the current user performing the operation and the NOW() statement retrieves the value of the current date and time from the MySQL server.

      Now if a user tries to update the value of any record in the sales table, the log_sales_updates trigger will insert a new record to the audit_log table.

      Let’s create a new sales record with a random sales_id of 5 and try to update it. First, insert the sales record with:

      • Insert into sales(sales_id, customer_id, sales_amount) values('5', '2','8000');

      Output

      Query OK, 1 row affected (0.00 sec)

      Next, update the record:

      • Update sales set sales_amount='9000' where sales_id='5';

      You’ll see the following output:

      Output

      Rows matched: 1 Changed: 1 Warnings: 0

      Now run the following command to verify if the AFTER UPDATE trigger was able to register a new record into the audit_log table:

      The trigger logged the update. Your output shows the previous sales_amount and new amount registered with the user that updated the records:

      Output

      +--------+----------+-----------------+------------+----------------+---------------------+ | log_id | sales_id | previous_amount | new_amount | updated_by | updated_on | +--------+----------+-----------------+------------+----------------+---------------------+ | 1 | 5 | 8000 | 9000 | root@localhost | 2019-11-07 09:28:36 | +--------+----------+-----------------+------------+----------------+---------------------+ 1 row in set (0.00 sec)

      You also have the date and time the update was performed, which are valuable for audit purposes.

      Next you’ll use the DELETE trigger to enforce referencing integrity at the database level.

      Step 6 — Creating a Before Delete Trigger

      BEFORE DELETE triggers invoke before a DELETE statement executes on a table. These kinds of triggers are normally used to enforce referential integrity on different related tables. For example, each record on the sales table relates to a customer_id from the customers table. If a database user deleted a record from the customers table that has a related record in the sales table, you would have no way of knowing the customer associated with that record.

      To avoid this, you can create a BEFORE DELETE trigger to enforce your logic. Run the following SQL commands one by one:

      • DELIMITER //
      • CREATE TRIGGER validate_related_records
      • BEFORE DELETE
      • ON customers
      • FOR EACH ROW
      • IF OLD.customer_id in (select customer_id from sales) THEN
      • SIGNAL SQLSTATE '45000'
      • SET MESSAGE_TEXT = 'The customer has a related sales record.';
      • END IF//
      • DELIMITER ;

      Now, try to delete a customer that has a related sales record:

      • Delete from customers where customer_id='2';

      As a result you’ll receive the following output:

      Output

      ERROR 1644 (45000): The customer has a related sales record.

      The BEFORE DELETE trigger can prevent accidental deletion of related information in a database.

      However, in some situations, you may want to delete all the records associated with a particular record from the different related tables. In this situation you would use the AFTER DELETE trigger, which you’ll test in the next step.

      Step 7 — Creating an After Delete Trigger

      AFTER DELETE triggers are activated once a record has been deleted successfully. An example of how you can use an AFTER DELETE trigger is a situation in which the discount level a particular customer receives is determined by the number of sales made during a defined period. If some of the customer’s records are deleted from the sales table, the customer discount level would need to be downgraded.

      Another use of the AFTER DELETE trigger is deleting related information from another table once a record from a base table is deleted. For instance, you’ll set a trigger that deletes the customer record if the sales records with the related customer_id are deleted from the sales table. Run the following command to create your trigger:

      • DELIMITER //
      • CREATE TRIGGER delete_related_info
      • AFTER DELETE
      • ON sales
      • FOR EACH ROW
      • Delete from customers where customer_id=OLD.customer_id;//
      • DELIMITER ;

      Next, run the following to delete all sales records associated with a customer_id of 2:

      • Delete from sales where customer_id='2';

      Output

      Query OK, 1 row affected (0.00 sec)

      Now check if there are records for the customer from the sales table:

      • Select * from customers where customer_id='2';

      You will receive an Empty Set output since the customer record associated with the customer_id of 2 was deleted by the trigger:

      Output

      Empty set (0.00 sec)

      You’ve now used each of the different forms of triggers to perform specific functions. Next you will see how you can remove a trigger from the database if you no longer need it.

      Step 8 — Deleting Triggers

      Similarly to any other database object, you can delete triggers using the DROP command. The following is the syntax for deleting a trigger:

      Drop trigger [TRIGGER NAME];
      

      For instance, to delete the last AFTER DELETE trigger that you created, run the following command:

      • Drop trigger delete_related_info;

      Output

      Query OK, 0 rows affected (0.00 sec)

      The need to delete triggers arises when you want to recreate its structure. In such a case, you can drop the trigger and redefine a new one with the different trigger commands.

      Conclusion

      In this tutorial you’ve created, used, and deleted the different kinds of triggers from a MySQL database. Using an example customer-related database you’ve implemented triggers for different use cases such as data validation, business-logic application, audit logging, and enforcing referential integrity.

      For further information on using your MySQL database, check out the following:



      Source link

      Cómo instalar Linux, Nginx, MySQL, PHP (pila LEMP) en Ubuntu 18.04


      Introducción

      La pila de software LEMP es un grupo de elementos de software que puede utilizarse para ofrecer páginas web y aplicaciones web dinámicas. El acrónimo describe un sistema operativo Linux, con un servidor web Nginx (que se pronuncia ​como “Engine-X”). Los datos backend se almacenan en la base de datos de MySQL y el procesamiento dinámico se gestiona a través de PHP.

      En guía se muestra la forma de instalar una pila LEMP en un servidor de Ubuntu 18.04. El sistema operativo Ubuntu se ocupa de los primeros requisitos. Describiremos la manera de hacer funcionar el resto de los componentes.

      Requisitos previos

      Antes de completar este tutorial, deberá tener una cuenta de usuario no root en su servidor con privilegios sudo. Configure esta cuenta completando nuestra guía de configuración inicial para servidores de Ubuntu 18.04.

      Una vez que tenga su usuario disponible, estará listo para comenzar con los pasos descritos en esta guía.

      Paso 2: Instalar el servidor web Nginx

      Para mostrar páginas web a los visitantes de nuestro sitio, emplearemos Nginx, un servidor web moderno y eficaz.

      Todos los programas de software utilizados en este procedimiento provendrán de los repositorios de paquetes predeterminados de Ubuntu. Esto significa que podemos utilizar el conjunto de programas de administración de paquetes apt para completar las instalaciones necesarias.

      Ya que esta es la primera vez que usamos apt para esta sesión, comience actualizando el índice de paquetes de su servidor. A continuación, instale el servidor:

      • sudo apt update
      • sudo apt install nginx

      En Ubuntu 18.04, Nginx se configura para que ejecutarse después de la instalación.

      Si tiene activo el firewall ufw, como se indica en la guía de configuración inicial, deberá permitir las conexiones a Nginx. Nginx se registra de forma automática con ufw tras la instalación, de modo que el procedimiento es bastante sencillo.

      Se recomienda que habilite el perfil más restrictivo que aún permitirá el tráfico que usted desea. Debido a que no configuró SSL para su servidor a través de esta guía, solo deberá permitir el tráfico en el puerto 80.

      Puede habilitarlo escribiendo lo siguiente:

      • sudo ufw allow 'Nginx HTTP'

      Puede verificar el cambio ejecutando lo siguiente:

      El resultado de este comando mostrará que el tráfico de HTTP está permitido:

      Output

      Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx HTTP ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx HTTP (v6) ALLOW Anywhere (v6)

      Una vez agregada la nueva regla del firewall, podrá probar si el servidor se encuentra en ejecución accediendo al nombre de dominio o a la dirección IP pública de su servidor en su navegador web.

      Si no tiene un nombre de dominio para su servidor y no conoce la dirección IP pública de este, puede encontrarla ejecutando siguiente comando:

      • ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's//.*$//'

      Con esto se mostrarán algunas direcciones IP. Puede probar cada una de estas en su navegador web.

      Como alternativa, podrá verificar la dirección IP accesible, como se ve desde otras ubicaciones de Internet:

      Escriba la dirección que reciba en su navegador web. Esta lo llevará a la página de destino predeterminada de Nginx:

      http://server_domain_or_IP
      

      Página predeterminada de Nginx

      Si ve la página de arriba, significa que instaló Nginx de forma correcta.

      Paso 2: Instalar MySQL para administrar datos de sitios

      Ahora que dispone de un servidor web, debe instalar MySQL (sistema de administración de bases de datos) para almacenar y administrar los datos de su sitio.

      Instale MySQL escribiendo lo siguiente:

      • sudo apt install mysql-server

      El software de base de datos MySQL quedará instalado, pero su configuración aún no estará completa.

      Para proteger la instalación, MySQL viene con un script que preguntará si deseamos modificar algunos valores predeterminados no seguros. Inicie el script escribiendo lo siguiente:

      • sudo mysql_secure_installation

      Este script le preguntará si desea configurar el VALIDATE PASSWORD PLUGIN.

      Advertencia: La habilitación de esta función queda a discreción del usuario. Si se habilita, MySQL rechazará con un mensaje de error las contraseñas que no coincidan con los criterios especificados. Esto provocará problemas si utiliza una contraseña débil junto con software que configure automáticamente las credenciales de usuario de MySQL, como los paquetes de Ubuntu para phpMyAdmin. Dejar la validación desactivada será una opción segura, pero siempre deberá utilizar contraseñas seguras y únicas para credenciales de bases de datos.

      Elija Y para indicar que sí, o cualquier otra cosa para continuar sin la habilitación.

      VALIDATE PASSWORD PLUGIN can be used to test passwords
      and improve security. It checks the strength of password
      and allows the users to set only those passwords which are
      secure enough. Would you like to setup VALIDATE PASSWORD plugin?
      
      Press y|Y for Yes, any other key for No:
      

      Si habilitó la validación, el script también le solicitará seleccionar un nivel de validación de contraseña. Tenga en cuenta que si ingresa 2, para marcar el nivel más seguro, recibirá mensajes de error al intentar configurar cualquier contraseña que no contenga números, letras en mayúscula y minúscula, y caracteres especiales, o que se base en palabras comunes del diccionario.

      There are three levels of password validation policy:
      
      LOW    Length >= 8
      MEDIUM Length >= 8, numeric, mixed case, and special characters
      STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file
      
      Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 1
      

      A continuación, se le solicitará enviar y confirmar una contraseña root:

      Please set the password for root here.
      
      New password:
      
      Re-enter new password:
      

      Para el resto de las preguntas, debe elegir Y y presionar la tecla ENTER en cada mensaje. Con esto, se eliminarán algunos usuarios anónimos y la base de datos de prueba, se deshabilitarán las credenciales de inicio de sesión remoto de root y se cargarán estas nuevas reglas para que MySQL respete de inmediato los cambios que realizamos.

      Tenga en cuenta que en los sistemas Ubuntu con MySQL 5.7 (y versiones posteriores), el usuario root de MySQL se configura para la autenticación utilizando el complemento auth_socket de manera predeterminada en lugar de una contraseña. Esto en muchos casos proporciona mayor seguridad y utilidad, pero también puede generar complicaciones cuando deba permitir que un programa externo (como phpMyAdmin) acceda al usuario.

      Si utiliza el complemento auth_socket para acceder a los ajustes de MySQL con su flujo de trabajo, puede continuar con el paso 3. Sin embargo, si prefiere utilizar una contraseña al conectarse con MySQL como root, deberá cambiar su método de autenticación de auth_socket a mysql_native_password. Para hacer esto, abra la línea de comandos de MySQL desde su terminal:

      A continuación, compruebe con el siguiente comando el método de autenticación utilizado por una de sus cuentas de usuario de MySQL:

      • SELECT user,authentication_string,plugin,host FROM mysql.user;

      Output

      +------------------+-------------------------------------------+-----------------------+-----------+ | user | authentication_string | plugin | host | +------------------+-------------------------------------------+-----------------------+-----------+ | root | | auth_socket | localhost | | mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost | | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost | | debian-sys-maint | *CC744277A401A7D25BE1CA89AFF17BF607F876FF | mysql_native_password | localhost | +------------------+-------------------------------------------+-----------------------+-----------+ 4 rows in set (0.00 sec)

      En este ejemplo, puede ver que, en efecto, el usuario root se autentica utilizando el complemento de auth_socket. Para configurar la cuenta de root de modo que la autenticación se realice con una contraseña, ejecute el siguiente comando ALTER USER. Asegúrese de cambiar password por una contraseña segura que elija:

      • ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

      A continuación, ejecute FLUSH PRIVILEGES para indicar al servidor que vuelva a cargar la tabla de permisos y aplique sus nuevos cambios:

      Compruebe de nuevo los métodos de autenticación empleados por cada uno de sus usuarios para confirmar que *root *deje de realizarla con el complemento de auth_socket:

      • SELECT user,authentication_string,plugin,host FROM mysql.user;

      Output

      +------------------+-------------------------------------------+-----------------------+-----------+ | user | authentication_string | plugin | host | +------------------+-------------------------------------------+-----------------------+-----------+ | root | *3636DACC8616D997782ADD0839F92C1571D6D78F | mysql_native_password | localhost | | mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost | | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost | | debian-sys-maint | *CC744277A401A7D25BE1CA89AFF17BF607F876FF | mysql_native_password | localhost | +------------------+-------------------------------------------+-----------------------+-----------+ 4 rows in set (0.00 sec)

      Puede ver en este resultado de ejemplo que el usuario *root *de MySQL ahora se autentica utilizando una contraseña. Una vez que confirme esto en su propio servidor, podrá cerrar el shell de MySQL:

      Nota: Después de configurar su usuario root de MySQL para la autenticación con una contraseña, ya no podrá acceder a MySQL con el comando sudo msql utilizado anteriormente. En su lugar, deberá ejecutar lo siguiente:

      Una vez que ingrese la contraseña que acaba de configurar, verá el la línea de comandos de MySQL.

      En este punto, su sistema de bases de datos estará configurado y podrá instalar PHP.

      Paso 3: Instalar PHP y configurar Nginx para utilizar el procesador de PHP

      Ya tiene instalados Nginx para sus páginas y MySQL para el almacenamiento y la administración de sus datos. Sin embargo, aún le falta una herramienta que pueda generar contenido dinámico. Aquí es donde se considera PHP .

      Dado que Nginx no contiene procesamiento de PHP nativo como otros servidores web, deberá instalar php-fpm, que significa “administrador de procesos de fastCGI”. Indicaremos a Nginx que transmita solicitudes de PHP a este software para su procesamiento.

      Nota: Según su proveedor de plataforma de nube, es posible que deba agregar el repositorio universe de Ubuntu, en el cual se incluye software gratuito y de código abierto actualizado por la comunidad de Ubuntu, antes de instalar el paquete php-fpm. Puede hacerlo escribiendo lo siguiente:

      • sudo add-apt-repository universe

      Instale el módulo php-fpm junto con un paquete auxiliar adicional, php-mysql, que permitirá a PHP comunicarse con el backend de su base de datos. La instalación extraerá los archivos principales de PHP necesarios. Podrá ejecutarla escribiendo lo siguiente:

      • sudo apt install php-fpm php-mysql

      Con esto, habrá instalado todos los componentes requeridos de la pila LEMP, pero aún deberá realizar algunos cambios en la configuración para indicar a Nginx que utilice el procesador PHP para contenido dinámico.

      Esto se realiza en el nivel de bloque del servidor (los bloques de servidor son similares a los hosts virtuales de Apache). Para hacerlo, abra un nuevo archivo de configuración de bloques de servidor dentro del directorio /etc/nginx/sites-available/. En este ejemplo, el nuevo archivo de configuración de bloques de servidor se llama example.com, pero puede dar al suyo el nombre que desee:

      • sudo nano /etc/nginx/sites-available/example.com

      Con la edición de un nuevo archivo de configuración de bloques de servidor, en lugar de editar el predeterminado podrá restaurar fácilmente la configuración predeterminada si lo necesita.

      Agregue el siguiente contenido, tomado y modificado ligeramente a partir del archivo de configuración predeterminado de bloques de servidor, a su nuevo archivo de configuración de bloques de servidor:

      /etc/nginx/sites-available/example.com

      server {
              listen 80;
              root /var/www/html;
              index index.php index.html index.htm index.nginx-debian.html;
              server_name example.com;
      
              location / {
                      try_files $uri $uri/ =404;
              }
      
              location ~ .php$ {
                      include snippets/fastcgi-php.conf;
                      fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
              }
      
              location ~ /.ht {
                      deny all;
              }
      }
      

      Esto es lo que hacen estas directivas y estos bloques de ubicación:

      • listen: define en qué puerto Nginx escuchará. En este caso, escuchará en el puerto 80, el puerto predeterminado para HTTP.
      • root: define el root de documentos en el que se almacenan los archivos disponibles en el sitio web.
      • index: configura Nginx para dar prioridad a los archivos denominados index.php cuando se solicite un archivo de índice, si están disponibles.
      • server_name: define el bloque de servidor que debe utilizarse para una solicitud determinada enviada a su servidor. Introduzca esta directiva en el nombre de dominio o la dirección IP pública de su servidor.
      • location /: el primer bloque de ubicación incluye una directiva try_files, la cual comprueba la existencia de archivos que coincidan con una solicitud de URI. Si Nginx no puede encontrar el archivo apropiado, se mostrará un error 404.
      • location ~ .php$: este bloque de ubicación administra el procesamiento de PHP real orientando Nginx al archivo de configuración fastcgi-php.conf y al archivo php7.2-fpm.sock, que declara el socket que se asocia con php-fpm.
      • location ~ /.ht: el último bloque de ubicación maneja archivos .htaccess, que Nginx no procesa. Al agregar la directiva deny all, si algunos de los archivos .htaccess ingresa de alguna forma en el root de documentos, estos no se pondrán a disposición de los visitantes.

      Una vez que agregue este contenido, guarde y cierre el archivo. Habilite su nuevo bloque de servidor creando un enlace simbólico entre su nuevo archivo de configuración de bloques de servidor (en el directorio /etc/nginx/sites-available/) y el directorio /etc/nginx/sites-enabled/:

      • sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

      Luego, desvincule el archivo de configuración predeterminado del directorio /sites-enabled/:

      • sudo unlink /etc/nginx/sites-enabled/default

      Nota: Si necesita restablecer la configuración predeterminada, puede hacerlo recreando el ajuste del enlace simbólico como se muestra a continuación.

      • sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/

      Verifique si hay errores de sintaxis en su nuevo archivo de configuración escribiendo lo siguiente:

      Si se notifica algún error, vuelva a verificar su archivo antes de continuar.

      Cuando esté listo, vuelva a cargar Nginx para realizar los cambios necesarios:

      • sudo systemctl reload nginx

      Con esto concluye la instalación y configuración de su pila LEMP. Sin embargo, se recomienda confirmar que todos los componentes puedan comunicarse entre sí.

      Paso 4: Crear un archivo PHP para probar la configuración

      Su pila LEMP ahora debería estar configurada por completo. Puede probarla para validar la ejecución correcta de archivos .php a partir del procesador PHP por parte de Nginx.

      Para hacerlo, utilice su editor de texto para crear un archivo PHP de prueba llamado info.php en su root de documentos:

      • sudo nano /var/www/html/info.php

      Introduzca las líneas que se muestran a continuación en el archivo nuevo. Se incluye código PHP válido que mostrará información sobre su servidor:

      /var/www/html/info.php

      <?php
      phpinfo();
      

      Cuando termine, guarde y cierre el archivo.

      Luego, visite esta página en su navegador web accediendo al nombre de dominio o a la dirección IP pública de su servidor con /info.php al final:

      http://your_server_domain_or_IP/info.php
      

      Debería ver una página web generada por PHP con información sobre su servidor:

      Información de página de PHP

      Si ve una página con este aspecto, significa que habrá configurado el procesamiento de PHP con Nginx de forma satisfactoria.

      Tras verificar que Nginx represente la página de forma correcta, la mejor opción será eliminar el archivo que creó porque puede dar indicios sobre su configuración que podrían ser útiles para que usuarios no autorizados intenten ingresar. Siempre puede regenerar este archivo si lo necesita más adelante.

      Por ahora, elimine el archivo escribiendo lo siguiente:

      • sudo rm /var/www/html/info.php

      Con esto, dispondrá de una pila LEMP completamente segura y funcional en su servidor de Ubuntu 18.04.

      Conclusión

      Una pila LEMP es una plataforma poderosa que le permitirá configurar y presentar casi cualquier sitio web o aplicación de su servidor.

      Existen varios pasos posteriores que podría seguir a partir de este punto. Por ejemplo, debe asegurarse de que las conexiones con su servidor estén protegidas. Para ello, podría proteger su instalación de Nginx con Let’s Encrypt. Siguiendo esta guía, obtendrá un certificado TLS/SSL gratuito para su servidor, lo que permitirá ofrecer contenido mediante HTTPS.



      Source link

      Cómo configurar Laravel, Nginx y MySQL con Docker Compose


      El autor seleccionó a The FreeBSD Foundation para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Durante los últimos años, Docker se ha convertido en una solución de uso frecuente para implementar aplicaciones gracias a la forma en que simplifican el funcionamiento y la implementación de aplicaciones en contenedores efímeros. Cuando se usa una pila de aplicación LEMP, por ejemplo, con PHP, Nginx, MySQL y el framework de Laravel, Docker puede simplificar considerablemente el proceso de configuración.

      Docker Compose ha simplificado aún más el proceso de desarrollo al permitir que los desarrolladores definan su infraestructura, incluidos los servicios de aplicación, las redes y los volúmenes, en un único archivo. Docker Compose ofrece una alternativa eficaz para ejecutar varios comandos docker container create y docker container run.

      A través de este tutorial, creará una aplicación web utilizando el marco Laravel con Nginx como servidor web y MySQL como base de datos; todo ello dentro de contenedores de Docker. Definirá toda la configuración de pila en un archivo docker-compose, junto con los archivos de configuración para PHP, MySQL y Nginx.

      Requisitos previos

      Antes de comenzar, necesitará lo siguiente:

      Paso 1: Descargar Laravel e instalar dependencias

      Como primer paso, obtendremos la versión más reciente de Laravel e instalaremos las dependencias del proyecto. Incluiremos Composer, el administrador de paquetes de nivel de aplicación para PHP. Instalaremos estas dependencias con Docker para evitar la instalación de Composer a nivel global.

      Primero, compruebe que se encuentre en su directorio de inicio, clone la última versión de Laravel y dispóngala en un directorio llamado laravel-app:

      • cd ~
      • git clone https://github.com/laravel/laravel.git laravel-app

      Posiciónese en el directorio laravel-app:“

      A continuación, utilice la imagen de composer de Docker a fin de montar los directorios que necesitará para su proyecto de Laravel y evitar la sobrecarga que implica instalar Composer a nivel global:

      • docker run --rm -v $(pwd):/app composer install

      Mediante los indicadores -v y --rm con docker run se crea un contenedor efímero para el cual se aplica un montaje “bind” a la lista de comandos actual antes de su eliminación. Con esto, se copiará el contenido de su directorio ~/laravel-app al contenedor y también se garantizará que la carpeta vendor creada por Composer dentro del contenedor se copie a su directorio actual.

      Como paso final, establezca permisos en el directorio del proyecto para que sea propiedad de su usuario no root:

      • sudo chown -R $USER:$USER ~/laravel-app

      Esto será importante al escribir el Dockerfile para la imagen de su aplicación en el paso 4, ya que le permitirá trabajar con el código de la aplicación y ejecutar procesos en su contenedor como usuario no root.

      Una vez establecido el código de su aplicación, puede proceder a definir sus servicios con Docker Compose.

      Paso 2: Crear el archivo de Docker Compose

      Desarrollar sus aplicaciones con Docker Compose simplifica el proceso de configuración y control de versiones de su infraestructura. Para configurar nuestra aplicación de Laravel, escribiremos un archivo docker-compose que defina nuestro servidor web, nuestra base de datos y nuestros servicios de aplicación.

      Abra el archivo:

      • nano ~/laravel-app/docker-compose.yml

      En el archivo docker-compose, definirá tres servicios: app, webserver y db. Agregue el siguiente código al archivo, asegúrese de sustituir la contraseña root de MySQL_ROOT_PASSWORD, definida como una variable de entorno bajo el servicio db, por una contraseña segura de su elección:

      ~/laravel-app/docker-compose.yml

      version: '3'
      services:
      
        #PHP Service
        app:
          build:
            context: .
            dockerfile: Dockerfile
          image: digitalocean.com/php
          container_name: app
          restart: unless-stopped
          tty: true
          environment:
            SERVICE_NAME: app
            SERVICE_TAGS: dev
          working_dir: /var/www
          networks:
            - app-network
      
        #Nginx Service
        webserver:
          image: nginx:alpine
          container_name: webserver
          restart: unless-stopped
          tty: true
          ports:
            - "80:80"
            - "443:443"
          networks:
            - app-network
      
        #MySQL Service
        db:
          image: mysql:5.7.22
          container_name: db
          restart: unless-stopped
          tty: true
          ports:
            - "3306:3306"
          environment:
            MYSQL_DATABASE: laravel
            MYSQL_ROOT_PASSWORD: your_mysql_root_password
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          networks:
            - app-network
      
      #Docker Networks
      networks:
        app-network:
          driver: bridge
      

      Los servicios definidos aquí incluyen lo siguiente:

      • app: esta definición de servicio contiene la aplicación de Laravel y ejecuta una imagen personalizada de Docker, digitalocean.com/php, que usted definirá en el paso 4. También fija /var/www para working_dir en el contenedor.
      • webserver: esta definición de servicio obtiene la imagen nginx:alpine de Docker y expone los puertos 80 y 443.
      • db: esta definición de servicio obtiene la imagen mysql:5.7.22 de Docker y define algunas variables de entorno, incluida una base de datos llamada laravel para su aplicación y la contraseña root para la base de datos. Puede nombrar la base de datos como lo desee y debe sustituir your_mysql_root_password por su propia contraseña segura. Esta definición de servicio también asigna el puerto 3306 en el host al puerto 3306 en el contenedor.

      Cada propiedad container_name define un nombre para el contenedor, que corresponde al nombre del servicio. Si no define esta propiedad, Docker asignará un nombre a cada contenedor combinando el nombre de una persona históricamente famosa y una palabra al azar separada por un guión bajo.

      Para facilitar la comunicación entre contenedores, los servicios se conectan a una red de puente llamada app-network. Una red de puente utiliza un puente de software que permite que los contenedores conectados a la misma red de puente se comuniquen entre sí. El controlador de puente instala de forma automática reglas en la máquina host para que los contenedores de diferentes redes de puente no puedan comunicarse directamente entre sí. Esto crea un mayor nivel de seguridad para las aplicaciones y garantiza que solo los servicios relacionados puedan comunicarse entre sí. También implica que usted puede definir diferentes redes y servicios que se conectan a funciones relacionadas: los servicios de aplicaciones clientes pueden utilizar una red frontend, por ejemplo, y los servicios de servidor pueden usar una red backend.

      Veamos la forma de agregar volúmenes y montajes “bind” a sus definiciones de servicio para persistir los datos de su aplicación.

      Paso 3: Persistir datos

      Docker tiene características potentes y convenientes para la persistencia de datos. En nuestra aplicación, usaremos volúmenes y montajes bind para persistir la base de datos y los archivos de aplicación y configuración. Los volúmenes ofrecen flexibilidad para los respaldos y la persistencia más allá del ciclo de vida de un contenedor, mientras que los montajes “bind” facilitan los cambios de código durante el desarrollo y realizan cambios en los archivos host o directorios disponibles de inmediato en sus contenedores. En nuestra configuración usaremos ambas opciones.

      Advertencia: Al usar de montajes “bind”, permite cambiar el sistema de archivos host a través de procesos que se ejecutan en un contenedor. Se incluye la creación, modificación o eliminación de archivos o directorios importantes del sistema. Esta es una poderosa capacidad que tiene consecuencias para la seguridad y podría afectar a los procesos no Docker del sistema host. Use los montajes “bind” con cuidado.

      En el archivo docker-compose, defina un volumen llamado dbdata bajo la definición de servicio db para persistir la base de datos de MySQL:

      ~/laravel-app/docker-compose.yml

      ...
      #MySQL Service
      db:
        ...
          volumes:
            - dbdata:/var/lib/mysql
          networks:
            - app-network
        ...
      

      El volumen llamado dbdata persiste el contenido de la carpeta /var/lib/mysql situada dentro del contenedor. Esto le permite detener y reiniciar el servicio db sin perder datos.

      En la parte inferior del archivo, agregue la definición para el volumen dbdata:

      ~/laravel-app/docker-compose.yml

      ...
      #Volumes
      volumes:
        dbdata:
          driver: local
      

      Una vez implementada esta definición, podrá utilizar este volumen en todos los servicios.

      A continuación, agregue un montaje “bind” al servicio db para los archivos de configuración de MySQL que creará en el paso 7:

      ~/laravel-app/docker-compose.yml

      ...
      #MySQL Service
      db:
        ...
          volumes:
            - dbdata:/var/lib/mysql
            - ./mysql/my.cnf:/etc/mysql/my.cnf
        ...
      

      Este montaje “bind” vincula ~/laravel-app/mysql/my.cnf a /etc/mysql/my.cnf en el contenedor.

      A continuación, agregue montajes “bind” al servicio webserver. Habrá dos: uno para el código de su aplicación y otro para la definición de configuración de Nginx que creará en el paso 6:

      ~/laravel-app/docker-compose.yml

      #Nginx Service
      webserver:
        ...
        volumes:
            - ./:/var/www
            - ./nginx/conf.d/:/etc/nginx/conf.d/
        networks:
            - app-network
      

      El primer montaje “bind” vincula el código de la aplicación situado en el directorio ~/laravel-app al directorio /var/www dentro del contenedor. El archivo de configuración que agregará a ~/laravel-app/nginx/conf.d/ también se montará a /etc/nginx/conf.d/ en el contenedor, lo que le permitirá agregar o modificar el contenido del directorio de configuración cuando sea necesario.

      Por último, agregue los siguientes montajes “bind” al servicio app para el código de la aplicación y los archivos de configuración:

      ~/laravel-app/docker-compose.yml

      #PHP Service
      app:
        ...
        volumes:
             - ./:/var/www
             - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
        networks:
            - app-network
      

      El servicio app vincula mediante montaje “bind” la carpeta ~/laravel-app, que contiene el código de la aplicación, a la carpeta /var/www en el contenedor. Esto acelerará el proceso de desarrollo, ya que los cambios realizados en el directorio de su aplicación local se reflejarán de inmediato dentro del contenedor. También vinculará su archivo de configuración PHP, ~/laravel-app/php/local.ini, a /usr/local/etc/php/conf.d/local.ini, dentro del contenedor. Creará el archivo de configuración de PHP local en el paso 5.

      Ahora, su archivo docker-compose tendrá el siguiente aspecto:

      ~/laravel-app/docker-compose.yml

      version: '3'
      services:
      
        #PHP Service
        app:
          build:
            context: .
            dockerfile: Dockerfile
          image: digitalocean.com/php
          container_name: app
          restart: unless-stopped
          tty: true
          environment:
            SERVICE_NAME: app
            SERVICE_TAGS: dev
          working_dir: /var/www
          volumes:
            - ./:/var/www
            - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
          networks:
            - app-network
      
        #Nginx Service
        webserver:
          image: nginx:alpine
          container_name: webserver
          restart: unless-stopped
          tty: true
          ports:
            - "80:80"
            - "443:443"
          volumes:
            - ./:/var/www
            - ./nginx/conf.d/:/etc/nginx/conf.d/
          networks:
            - app-network
      
        #MySQL Service
        db:
          image: mysql:5.7.22
          container_name: db
          restart: unless-stopped
          tty: true
          ports:
            - "3306:3306"
          environment:
            MYSQL_DATABASE: laravel
            MYSQL_ROOT_PASSWORD: your_mysql_root_password
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - dbdata:/var/lib/mysql/
            - ./mysql/my.cnf:/etc/mysql/my.cnf
          networks:
            - app-network
      
      #Docker Networks
      networks:
        app-network:
          driver: bridge
      #Volumes
      volumes:
        dbdata:
          driver: local
      

      Guarde el archivo y cierre su editor cuando termine de realizar cambios.

      Ahora que su archivo docker-compose está escrito, podrá crear la imagen personalizada para su aplicación.

      Paso 4: Crear el Dockerfile

      Docker le permite especificar el entorno dentro de contenedores individuales con un Dockerfile. Un Dockerfile le permite crear imágenes personalizadas que puede emplear para instalar el software requerido por su aplicación y configurar los ajustes según sus requisitos. Puede introducir en Docker Hub o en cualquier registro privado las imágenes personalizadas que cree.

      Nuestro Dockerfile se ubicará en nuestro directorio ~/laravel-app. Cree el archivo:

      • nano ~/laravel-app/Dockerfile

      Este Dockerfile establecerá la imagen de base y especificará los comandos y las instrucciones que se necesitan para crear la imagen de aplicación de Laravel. Agregue el siguiente código al archivo:

      ~/laravel-app/php/Dockerfile

      FROM php:7.2-fpm
      
      # Copy composer.lock and composer.json
      COPY composer.lock composer.json /var/www/
      
      # Set working directory
      WORKDIR /var/www
      
      # Install dependencies
      RUN apt-get update && apt-get install -y 
          build-essential 
          mysql-client 
          libpng-dev 
          libjpeg62-turbo-dev 
          libfreetype6-dev 
          locales 
          zip 
          jpegoptim optipng pngquant gifsicle 
          vim 
          unzip 
          git 
          curl
      
      # Clear cache
      RUN apt-get clean && rm -rf /var/lib/apt/lists/*
      
      # Install extensions
      RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
      RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
      RUN docker-php-ext-install gd
      
      # Install composer
      RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
      
      # Add user for laravel application
      RUN groupadd -g 1000 www
      RUN useradd -u 1000 -ms /bin/bash -g www www
      
      # Copy existing application directory contents
      COPY . /var/www
      
      # Copy existing application directory permissions
      COPY --chown=www:www . /var/www
      
      # Change current user to www
      USER www
      
      # Expose port 9000 and start php-fpm server
      EXPOSE 9000
      CMD ["php-fpm"]
      

      Primero, el Dockerfile crea una imagen en la parte superior de la imagen de php:7.2-fpm Docker. Esta es una imagen basada en Debian que tiene instalada la implementación PHP-FPM de PHP FastCGI. El archivo también instala con composer los paquetes previos para Laravel: mcrypt, pdo_mysql, mbstring e imagick.

      La directiva RUN especifica los comandos para actualizar, instalar y configurar los ajustes dentro del contenedor. Esto incluye la creación de un usuario dedicado y un grupo llamado www. La instrucción WORKDIR especifica el directorio /var/www como directorio de trabajo para la aplicación.

      Crear un usuario dedicado y un grupo con permisos restringidos mitiga la vulnerabilidad inherente al ejecutar contenedores de Docker, que se funcionan por defecto como root. En lugar de ejecutar este contenedor como root, creamos el usuario** www**, que tiene acceso de lectura y escritura a la carpeta /var/www gracias a la instrucción COPY que usaremos con el indicador --chown para copiar los permisos de la carpeta de la aplicación.

      Por último, el comando EXPOSE expone un puerto del contenedor, el 9000, para el servidor php-fpm. CMD especifica el comando que debe ejecutarse una vez que se cree el contenedor. Aquí, el CMD especifica “php-fpm”, que iniciará el servidor.

      Guarde el archivo y cierre su editor cuando termine de realizar cambios.

      Ahora podrá definir su configuración de PHP.

      Paso 5: Configurar PHP

      Ahora que definió su infraestructura en el archivo docker-compose, puede configurar el servicio PHP para que funciones como procesador PHP para solicitudes entrantes de Nginx.

      Para configurar PHP, creará el archivo local.ini dentro de la carpeta php. Este es el archivo que vinculó mediante montaje “bind” a /usr/local/etc/php/conf.d/local.ini dentro del contenedor en el paso 2. Crear este archivo le permitirá anular el archivo php.ini predeterminado que PHP lee al iniciarse.

      Cree el directorio php:

      A continuación, abra el archivo local.ini:

      • nano ~/laravel-app/php/local.ini

      Con el propósito de demostrar cómo configurar PHP, agregaremos el siguiente código para establecer limitaciones de tamaño para archivos cargados:

      ~/laravel-app/php/local.ini

      upload_max_filesize=40M
      post_max_size=40M
      

      Las directivas upload_max_filesize y post_max_size establecen el tamaño máximo permitido para los archivos cargados y demuestran la forma en que puede configurar parámetros php.ini desde su archivo local.ini. Puede disponer cualquier configuración específica de PHP que desee anular en el archivo local.ini.

      Guarde el archivo y cierre el editor.

      Una vez preparado su archivo PHP local.ini, podrá configurar Nginx.

      Paso 6: Configurar Nginx

      Una vez configurado el servicio PHP, podrá modificar el servicio Nginx para usar PHP-FPM como servidor de FastCGI para proporcionar contenido dinámico. El servidor FastCGI se basa en un protocolo binario para interconectar programas interactivos con un servidor web. Para obtener más información, consulte este artículo sobre Comprensión e implementación de proxy de FastCGI en Nginx.

      Para configurar Nginx, creará un archivo app.conf con la configuración del servicio en la carpeta ~/laravel-app/nginx/conf.d/.

      Primero, cree el directorio nginx/conf.d/:

      • mkdir -p ~/laravel-app/nginx/conf.d

      Luego, cree el archivo de configuración app.conf:

      • nano ~/laravel-app/nginx/conf.d/app.conf

      Agregue el siguiente código al archivo para especificar su configuración de Nginx:

      ~/laravel-app/nginx/conf.d/app.conf

      server {
          listen 80;
          index index.php index.html;
          error_log  /var/log/nginx/error.log;
          access_log /var/log/nginx/access.log;
          root /var/www/public;
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass app:9000;
              fastcgi_index index.php;
              include fastcgi_params;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              fastcgi_param PATH_INFO $fastcgi_path_info;
          }
          location / {
              try_files $uri $uri/ /index.php?$query_string;
              gzip_static on;
          }
      }
      

      El bloque de servidor define la configuración para el servidor web de Nginx con las siguientes directivas:

      • listen: esta directiva define el puerto en el cual el servidor escuchará las solicitudes entrantes.
      • error_log y access_log: estas directivas definen los archivos para escribir registros.
      • root: esta directiva establece la ruta de la carpeta root y forma la ruta para cualquier archivo solicitado en el sistema de archivos local.

      En el bloque de ubicación php, la directiva fastcgi_pass especifica que el servicio de app escuchando en un socket TCP del puerto 9000. Esto hace que el servidor PHP-FPM escuche a través de la red en lugar de hacerlo en un socket de Unix. Aunque un socket de Unix tiene una ligera ventaja de velocidad con respecto a un socket de TCP, no cuenta con un protocolo de red y, por lo tanto, omite la pila de red. Para los casos en los cuales los hosts están ubicados en una máquina, puede tener sentido la presencia de un socket de Unix. Sin embargo, en los casos en los que tenga servicios ejecutándose en diferentes hosts, un socket de TCP le ofrece la ventaja de permitirle conectarse a servicios distribuidos. Debido a que nuestro contenedor app se ejecuta en un host diferente del de nuestro contenedor webserver, un socket de TCP es la opción que más sentido tiene para nuestro tipo de configuración.

      Guarde el archivo y cierre su editor cuando termine de realizar cambios.

      Gracias al montaje “bind” mount que creó en el paso 2, cualquier cambio que realice dentro de la carpeta nginx/conf.d/ se reflejará directamente dentro del contenedor webserver.

      A continuación, observaremos nuestras configuraciones de MySQL.

      Paso 7: Configurar MySQL

      Una vez configurados PHP y Nginx, podrá habilitar MySQL para que actúe como base de datos para su aplicación.

      Para configurar MySQL, creará el archivo my.cnf en la carpeta mysql. Este es el archivo que vinculó mediante montaje “bind” a /etc/mysql/my.cnf dentro del contenedor en el paso 2. Este montaje “bind” le permite anular los ajustes de my.cnf según sea necesario.

      Para demostrar cómo funciona esto, agregaremos al archivo my.cnf ajustes que habiliten el registro general de consulta y especifiquen el archivo de registro.

      Primero, cree el directorio mysql:

      • mkdir ~/laravel-app/mysql

      A continuación, cree el archivo my.cnf:

      • nano ~/laravel-app/mysql/my.cnf

      En el archivo, agregue el siguiente código para habilitar el registro de consulta y establecer la ubicación del archivo de registro:

      ~/laravel-app/mysql/my.cnf

      [mysqld]
      general_log = 1
      general_log_file = /var/lib/mysql/general.log
      

      Este archivo my.cnf habilita los registros y define la configuración de general_log con el valor 1 para permitir registros generales. La configuración general_log_file especifica dónde se almacenarán los registros.

      Guarde el archivo y cierre el editor.

      Nuestro siguiente paso será iniciar los contenedores.

      Paso 8: Ejecutar los contenedores y modificar las preferencias de entorno

      Ahora que definió todos sus servicios en su archivo docker-compose y creó los archivos de configuración para estos servicios, puede iniciar los contenedores. Sin embargo, como paso final, crearemos una copia del archivo .env.example que Laravel incluye por defecto y daremos a la copia el nombre .env, que corresponde al archivo que Laravel prevé que definirá su entorno:

      Configuraremos los detalles específicos de nuestros ajustes en este archivo una vez que iniciemos los contenedores.

      Una vez definidos todos sus servicios en su archivo docker-compose, solo deberá emitir un comando para iniciar todos los contenedores, crear los volúmenes y configurar y conectar las redes:

      Cuando ejecute docker-compose por primera vez, descargará todas las imágenes de Docker necesarias, lo cual podría tardar un tiempo. Una vez que las imágenes se descarguen y se almacenen en su máquina local, Compose creará sus contenedores. El indicador -d agrega un demonio al proceso y ejecuta sus contenedores en segundo plano.

      Una vez que el proceso esté completo, use el siguiente comando para enumerar todos los contenedores en ejecución:

      Verá el siguiente resultado con detalles sobre sus contenedores app, webserver y db:

      Output

      CONTAINER ID NAMES IMAGE STATUS PORTS c31b7b3251e0 db mysql:5.7.22 Up 2 seconds 0.0.0.0:3306->3306/tcp ed5a69704580 app digitalocean.com/php Up 2 seconds 9000/tcp 5ce4ee31d7c0 webserver nginx:alpine Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp

      CONTAINER ID en este resultado es un identificador único para cada contenedor, mientras que NAMES enumera el nombre de servicio asociado con cada una. Puede usar ambos identificadores para acceder a los contenedores. IMAGE define el nombre de imagen para cada contenedor, mientras que STATUS proporciona información sobre el su estado: en ejecución, en proceso de reinicio o detenido.

      Ahora puede modificar el archivo .env en el contenedor app para incluir detalles específicos sobre su configuración.

      Abra el archivo usando docker-compose exec, que permite ejecutar comandos específicos en contenedores. En este caso, abrirá el archivo para editar lo siguiente:

      • docker-compose exec app nano .env

      Busque el bloque que especifica DB_CONNECTION y actualícelo para reflejar los detalles de su configuración. Cambiará los siguientes campos:

      • DB_HOST será su contenedor de base de datos db.
      • `DB_DATABASE será la base de datos laravel.
      • `DB_USERNAME será el nombre de usuario que usará para su base de datos. En este caso, usaremos laraveluser.
      • DB_PASSWORD será la contraseña segura que desee utilizar para esta cuenta de usuario.

      /var/www/.env

      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=laravel
      DB_USERNAME=laraveluser
      DB_PASSWORD=your_laravel_db_password
      

      Guarde sus cambios y cierre el editor.

      A continuación, establezca la clave de aplicación para la aplicación de Laravel con el comando php artisan key:generate. Este comando generará una clave, dispondrá una copia de esta en su archivo .env y se asegurará de que las sesiones y los datos cifrados de sus usuarios permanezcan seguros:

      • docker-compose exec app php artisan key:generate

      Con esto, dispondrá de los ajustes de entorno necesarios para ejecutar su aplicación. Para almacenar en caché estos ajustes en un archivo, lo cual aumentará la velocidad de carga de su aplicación, ejecute lo siguiente:

      • docker-compose exec app php artisan config:cache

      Sus ajustes de configuración se cargarán en /var/www/bootstrap/cache/config.php en el contenedor.

      Como paso final, visite http://your_server_ip en el navegador. Verá la siguiente página de inicio para su aplicación Laravel:

      Página de inicio de Laravel

      Con sus contenedores en ejecución y la información de su configuración lista, podrá configurar la información de usuario para la base de datos laravel en el contenedor db.

      Paso 9: Crear un usuario para MySQL

      La instalación predeterminada de MySQL solo crea la cuenta administrativa root, que tiene privilegios ilimitados en el servidor de base de datos. Por lo general, es mejor evitar el uso de la cuenta administrativa root al interactuar con la base de datos. En su lugar, crearemos un usuario de base de datos dedicado para la base de datos de nuestra aplicación de Laravel.

      Para crear un nuevo usuario, ejecute un shell bash interactivo en el contenedor db con docker-compose exec:

      • docker-compose exec db bash

      Dentro del contenedor, inicie sesión en la cuenta administrativa root de MySQL:

      Se le solicitará la contraseña que estableció para la cuenta root de MySQL durante la instalación en su archivo docker-compose.

      Comience revisando la base de datos llamada laravel, que definió en su archivo docker-compose. Ejecute el comando show databases para verificar las bases de datos existentes:”“”

      Verá la base de datos laravel en el resultado:“

      Output

      +--------------------+ | Database | +--------------------+ | information_schema | | laravel | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec)

      A continuación, cree la cuenta de usuario que tendrá permisos de acceso a esta base de datos. Nuestro nombre de usuario será laraveluser, aunque puede cambiarlo por otro que prefiera. Asegúrese de que su nombre de usuario y contraseña aquí coincidan con la información que estableció en su archivo .env en el paso anterior:”“

      • GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password';

      Elimine los privilegios para notificar los cambios al servidor MySQL:

      Cierre MySQL:

      Por último, cierre el contenedor:

      Con esto, habrá configurado la cuenta de usuario para la base de datos de su aplicación de Laravel y estará listo para migrar sus datos y trabajar con la consola Tinker.

      Paso 10: Migrar datos y trabajar con la consola Tinker

      Con su aplicación en ejecución, podrá migrar sus datos y experimentar con el comando tinker, que iniciará una consola PsySH con Laravel precargada. PsySH es una consola para desarrolladores de tiempo de ejecución y un depurador interactivo para PHP, y Tinker es un REPL específico para Laravel. Usar el comando tinker le permitirá interactuar con su aplicación de Laravel desde la línea de comandos en un shell interactivo.

      Primero, pruebe la conexión con MySQL ejecutando el comando Laravel artisan migrate, que crea una tabla migrations en la base de datos dentro del contenedor:

      • docker-compose exec app php artisan migrate

      Con este comando se migrarán las tablas predeterminadas de Laravel. El resultado que confirme la migración tendrá este aspecto:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table

      Una vez que la migración esté completa, podrá ejecutar una consulta para verificar si su conexión a la base de datos es correcta usando el comando tinker:

      • docker-compose exec app php artisan tinker

      Pruebe la conexión de MySQL obteniendo los datos que acaba de migrar:

      • DB::table('migrations')->get();

      Verá un resultado similar a este:

      Output

      => IlluminateSupportCollection {#2856 all: [ {#2862 +"id": 1, +"migration": "2014_10_12_000000_create_users_table", +"batch": 1, }, {#2865 +"id": 2, +"migration": "2014_10_12_100000_create_password_resets_table", +"batch": 1, }, ], }

      Puede usar tinker para interactuar con sus bases de datos y experimentar con servicios y modelos.

      Una vez implementada su aplicación de Laravel, estará listo para seguir adelante con el desarrollo y la experimentación.

      Conclusión

      Con esto, dispondrá de una aplicación de pila LEMP en ejecución en su servidor, que probó accediendo a la página de bienvenida de Laravel y creando migraciones de base de datos de MySQL.

      La clave de la simplicidad en esta instalación es Docker Compose, que le permite crear un grupo de contenedores de Docker definidos en un solo archivo mediante un comando. Si desea obtener más información sobre cómo realizar una integración continua con Docker Compose, consulte Cómo configurar un entorno de prueba de integración continua con Docker y Docker Compose en Ubuntu 16.04. Si desea simplificar su proceso de implementación de la aplicación de Laravel, resultará pertinente el recurso Cómo implementar de forma automática aplicaciones de Laravel con Deployer en Ubuntu 16.04.



      Source link