One place for hosting & domains

      Laravel

      Cómo usar migraciones y alimentadores de bases de datos para abstraer la configuración de bases de datos en Laravel


      Las migraciones y los sembradores son poderosas utilidades de bases de datos que se proporcionan a través del marco PHP Laravel para permitir a los desarrolladores iniciar, destruir y volver a crear rápidamente la base de datos de una aplicación. Estas utilidades permiten minimizar los problemas de inconsistencia que pueden surgir en la base de datos cuando varios desarrolladores trabajan en la misma aplicación: los nuevos colaboradores solo deben ejecutar un par de comandos artisan para configurar la base de datos en una nueva instalación.

      A lo largo de esta guía, crearemos migraciones y alimentadores para completar una base de datos de aplicación de demostración de Laravel con datos de ejemplo. Al final, podrá destruir y volver a crear las tablas de su base de datos cuantas veces lo desee, usando solo comandos artisan.

      Requisitos previos

      Para completar los pasos de esta guía, necesitará lo siguiente:

      Nota: En esta guía, para ejecutar la aplicación usaremos un entorno de desarrollo en contenedor administrado por Docker Compose, pero también puede optar por ejecutar la aplicación en un servidor LEMP. Para configurarlo, puede seguir nuestra guía Cómo instalar y configurar Laravel con LEMP en Ubuntu 18.04.

      Paso 1: Obtener la aplicación de demostración

      Para comenzar, obtendremos la aplicación Laravel de demostración de su repositorio de GitHub. Nos interesa la ramificación tutorial-02, en la que se incluye una configuración de Docker Compose para ejecutar la aplicación en contenedores. En este ejemplo, descargaremos la aplicación en nuestra carpeta de inicio, pero puede usar cualquier directorio que elija:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

      Debido a que descargamos el código de la aplicación como un archivo .zip, necesitaremos el comando unzip para desempaquetarlo. Si no lo hizo recientemente, actualice el índice local de paquetes de su computadora:

      A continuación instale el paquete unzip:

      Después de eso, descomprima el contenido de la aplicación:

      Luego para facilitar el acceso cambie el nombre del directorio desempaquetado por travellist-demo:

      • mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

      En el siguiente paso, crearemos un archivo de configuración .env para configurar la aplicación.

      Paso 2: Configurar el archivo .env de la aplicación

      En Laravel, se utiliza un archivo .env para establecer configuraciones dependientes del entorno, como las credenciales y cualquier información que pueda variar entre las implementaciones. Este archivo no está incluido en el control de revisiones.

      Advertencia: En el archivo de configuración del entorno se encuentra información confidencial sobre su servidor, incluidas las credenciales de bases de datos y las claves de seguridad. Por ese motivo, nunca debe compartir públicamente este archivo.

      Los valores incluidos en el archivo .env tendrán prioridad sobre los valores establecidos en los archivos de configuración normales que se encuentran en el directorio config. Para cada instalación en un nuevo entorno se requiere un archivo de entorno personalizado a fin de definir elementos como las configuraciones de conexión de bases de datos, las opciones de depuración y las URL de aplicación, entre otros elementos que pueden variar dependiendo del entorno en el que se ejecute la aplicación.

      Diríjase al directorio travellist-demo:

      Ahora, crearemos un nuevo archivo .env para personalizar las opciones de configuración para el entorno de desarrollo que configuraremos. En Laravel se incluye un archivo .env de ejemplo que podemos copiar para crear el nuestro:

      Abra este archivo utilzando nano o el editor de texto que prefiera:

      Así es como se ve su archivo .env ahora:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password

      En el archivo .env actual de la aplicación de demostración travellist se incluyen las configuraciones para usar el entorno en contenedor que creamos con Docker Compose en la última parte de esta serie. No necesita cambiar ninguno de estos valores, pero puede modificar DB_DATABASE, DB_USERNAME y DB_PASSWORD si lo desea, ya que nuestro archivo docker-compose.yml los obtiene automáticamente para configurar la base de datos de desarrollo. Solo asegúrese de que la variable DB_HOST permanezca sin cambios, ya que esta hace referencia al nombre de nuestro servicio de base de datos dentro del entorno de Docker Compose.

      Si realiza algún cambio en el archivo, asegúrese de guardarlo y cerrarlo presionando CTRL + X, Y y luego INTRO.

      Nota: Si optó por ejecutar la aplicación en un servidor LEMP, deberá cambiar los valores resaltados para reflejar la configuración de su propia base de datos, incluida la variable DB_HOST.

      Paso 3: Instalar las dependencias de la aplicación con Composer

      Ahora usaremos Composer, la herramienta de administración de dependencias de PHP, para instalar las dependencias de la aplicación y garantizar que podamos ejecutar comandos artisan.

      Abra su entorno de Docker Compose con el comando siguiente. Con esto, se creará la imagen travellist para el servicio app y se extraerán las imágenes adicionales de Docker requeridas por los servicios de nginx y db a fin de crear el entorno de la aplicación:

      Output

      Creating network "travellist-demo_travellist" with driver "bridge" Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in 9259bb2ac034 … Creating travellist-app ... done Creating travellist-nginx ... done Creating travellist-db ... done

      Esta operación puede tardar unos minutos en completarse. Una vez terminado el proceso, podemos ejecutar Composer para instalar las dependencias de la aplicación.

      Para ejecutar composer y otros comandos en el contenedor de servicio app, usaremos docker-compose exec. El comando exec nos permite ejecutar cualquier comando que elijamos en los contenedores gestionados por Docker Compose. Se utiliza la siguiente sintaxis: docker-compose exec service_name command.

      Nota: En caso de optar por utilizar un servidor LEMP para ejecutar la aplicación de demostración, debe ignorar la parte de docker-compose exec app de los comandos enumerados a lo largo de esta guía. Por ejemplo, en lugar de ejecutar el siguiente comando como está escrito, simplemente ejecutaría lo siguiente:

      Para ejecutar composer install en el contenedor app, ejecute lo siguiente:

      • docker-compose exec app composer install

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) …

      Cuando Composer termine de instalar las dependencias de la aplicación, podrá ejecutar los comandos artisan. Para verificar que en la aplicación se pueda establecer conexión con la base de datos, ejecute el siguiente comando en el que se eliminará cualquier tabla existente:

      • docker-compose exec app php artisan db:wipe

      Con este comando se eliminará cualquier tabla ya existente de la base de datos configurada. Si se ejecutó con éxito y en la aplicación se pudo establecer conexión con la base de datos, verá un resultado como el siguiente:

      Output

      Dropped all tables successfully.

      Ahora que instaló las dependencias de la aplicación con Composer, puede usar la herramienta artisan para crear migraciones y alimentadores.

      Paso 4: Crear migraciones de bases de datos

      En la herramienta de línea de comandos artisan que se incluye con Laravel hay una serie de comandos auxiliares que pueden utilizarse para administrar la aplicación e iniciar nuevas clases. Para generar una nueva clase de migración, podemos usar el comando make:migration de la siguiente manera:

      • docker-compose exec app php artisan make:migration create_places_table

      Laravel infiere la operación que se ejecutará (create), el nombre de la tabla (places) y si en esta migración se creará una tabla nueva o no, basada en el nombre descriptivo proporcionado al comando make:migration.

      Verá un resultado similar a este:

      Output

      Created Migration: 2020_02_03_143622_create_places_table

      Con esto se generará un nuevo archivo en el directorio database/migrations de la aplicación. Laravel utiliza la marca de tiempo incluida en el archivo generado automáticamente para determinar el orden en que se deben ejecutar las migraciones.

      Utilice su editor de texto preferido para abrir el archivo de migración generado. Recuerde sustituir el valor resaltado por el nombre de su propio archivo de migración:

      • nano database/migrations/2020_02_03_143622_create_places_table.php

      En el archivo de migración generado se incluye una clase llamada CreatePlacesTable:

      database/migrations/2020_02_03_143622_create_places_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreatePlacesTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('places');
          }
      }
      
      

      En esta clase se incluyen dos métodos: up y down. Ambos métodos contienen código de arranque que puede ampliar para personalizar lo que ocurre cuando se ejecuta esa migración y también lo que sucede cuando se revierte.

      Modificaremos el método up para que en la tabla places se refleje la estructura que ya estamos usando en la versión actual de la aplicación:

      • id: campo de clave primaria.
      • name: nombre del lugar.
      • visited: indica si este lugar ya recibió visitas o no.

      En el constructor de esquemas de Laravel se exponen los métodos para crear, actualizar y eliminar tablas de una base de datos. En la clase Blueprint se define la estructura de la tabla y se proporcionan varios métodos para abstraer la definición de cada campo de la tabla.

      En el código generado automáticamente se establece un campo de id primario llamado id. En el método timestamps se crean dos campos datetime que las clases de base de datos subyacentes actualizan de manera automática cuando se insertan o actualizan datos dentro de la tabla. Además de estas, tendremos que incluir un campo name y otro visited.

      Nuestro campo name será del tipo string y nuestro campo visited estará configurado con el tipo boolean. También estableceremos un valor predeterminado 0 para el campo visited, de modo que si no se transmite ningún valor, significa que aún no se visitó el lugar. El método up tendrá ahora el siguiente aspecto:

      database/migrations/2020_02_03_143622_create_places_table.php

      …
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->string('name', 100);
                  $table->boolean('visited')->default(0);
                  $table->timestamps();
              });
          }
      …
      

      Nota: Puede encontrar la lista completa de tipos de columnas disponibles en la documentación de Laravel.

      Después de incluir las dos líneas resaltadas en su propia secuencia de comandos de migración, guarde y cierre el archivo.

      Su migración estará lista para ejecutarse a través de artisan migrate. Sin embargo, eso solo crearía una tabla vacía; también debemos poder insertar datos de ejemplo para desarrollo y pruebas. En el siguiente paso, veremos cómo hacerlo usando alimentadores de bases de datos.

      Paso 5: Crear alimentadores de bases de datos

      Un alimentador es una clase especial que se utiliza para generar e insertar datos de ejemplo (semillas) en una base de datos. Esta es una característica importante en los entornos de desarrollo, ya que le permite volver a crear la aplicación con una base de datos nueva usando valores de ejemplo que de otra manera tendría que insertar manualmente al volver a crear la base de datos.

      Ahora, usaremos el comando artisan a fin de generar una nueva clase de alimentador para nuestra tabla places llamada PlacesTableSeeder:

      • docker-compose exec app php artisan make:seeder PlacesTableSeeder

      Con el comando se creará un nuevo archivo llamado PlacesTableSeeder.php dentro del directorio database/seeds. Abra el archivo usando su editor de texto preferido:

      • nano database/seeds/PlacesTableSeeder.php

      El archivo PlacesTableSeeder.php generado automáticamente tiene el siguiente aspecto:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              //
          }
      }
      
      

      Nuestra nueva clase de alimentador contiene un método vacío llamado run. Este método se invocará cuando se ejecute el comando db:seed de Artisan.

      Debemos editar el método run para que se incluyan las instrucciones de inserción de datos de ejemplo en la base de datos. Usaremos el generador de consultas de Laravel para simplificar este proceso.

      El generador de consultas de Laravel ofrece una interfaz fluida para operaciones de bases de datos como la inseción, actualización, eliminación y recuperación de datos. También cuenta con elementos de protección contra ataques de inyección SQL. Está expuesto por la fachada DB, un proxy estático para las clases de base de datos subyacentes en el contenedor de servicio.

      Para comenzar, crearemos una variable de clase estática para contener todos los lugares de ejemplo que queramos insertar en la base de datos como matriz. Esto nos permitirá usar un bucle foreach para iterar todos los valores, insertando cada uno en la base de datos con el generador de consultas.

      Daremos a esta variable el nombre $places:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];

      A continuación, tendremos que incluir una instrucción use en la parte superior de nuestra clase PlacesTableSeeder para facilitar la referencia a la fachada DB en el código:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      …
      

      Ahora, podemos iterar los valores de la matriz $places usando un bucle foreach e insertar cada uno en nuestra tabla places con el generador de consultas:

      database/seeds/PlacesTableSeeder.php

      …
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      
      

      El bucle foreach itera cada valor de la matriz estática $places. En cada iteración, usamos la fachada DB para insertar una nueva fila en la tabla places. Para el campo name, fijamos el nombre del lugar que acabamos de obtener de la matriz $places y para el campo visited marcamos un valor aleatorio de 0 o 1.

      Así es como se visualizará la clase PlacesTableSeeder completa después de todas las actualizaciones:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];
      
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      }
      

      Guarde y cierre el archivo cuando termine de realizar estos cambios.

      Las clases de alimentadores no se cargan automáticamente en la aplicación. Debemos editar la clase principal DatabaseSeeder para incluir una invocación al alimentador que acabamos de crear.

      Abra el archivo database/seeds/DatabaseSeeder.php con nano o su editor favorito:

      • nano database/seeds/DatabaseSeeder.php

      La clase DatabaseSeeder se parece a cualquier otro sembrador: deriva de la clase Seeder y tiene un método run. Actualizaremos este método para incluir una invocación a PlacesTableSeeder.

      Actualice el método actual run dentro de su clase DatabaseSeeder eliminando la línea marcada con comentarios y reemplazándola por el siguiente código resaltado:

      database/seeds/DatabaseSeeder.php

      …
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      ...
      

      Después de la actualización, la clase DatabaseSeeder completa tendrá el siguiente aspecto:

      database/seeds/DatabaseSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class DatabaseSeeder extends Seeder
      {
          /**
           * Seed the application's database.
           *
           * @return void
           */
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      }
      
      
      

      Guarde y cierre el archivo cuando termine de actualizar su contenido.

      Con esto, terminamos de preparar una migración y un alimentador para nuestra tabla places. En el siguiente paso, veremos la manera de ejecutarlos.

      Paso 6: Ejecutar migraciones y alimentadores de bases de datos

      Antes de continuar, debemos asegurarnos de que su aplicación esté lista y en funcionamiento. Configuraremos la clave de cifrado de la aplicación y luego accederemos a esta última desde un navegador para probar el servidor web.

      Para generar la clave de cifrado requerida por Laravel, puede usar el comando artisan key:generate:

      • docker-compose exec app php artisan key:generate

      Una vez generada la clave, podrá acceder a la aplicación orientando su navegador al nombre de host o a la dirección IP de su servidor en el puerto 8000:

      http://server_host_or_ip:8000
      

      Verá una página como la siguiente:

      Error de MySQL

      Esto significa que en la aplicación se puede establecer conexión con la base de datos, pero no se logró encontrar una tabla llamada places. Ahora crearemos la tabla places usando el siguiente comando migrate de Artisan:

      • docker-compose exec app php artisan migrate

      Verá un resultado similar a este:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)

      Observará que se ejecutaron algunas otras migraciones junto con la migración create_places_table que configuramos. Estas migraciones se generan de forma automática cuando se instala Laravel. Aunque ahora no usaremos estas tablas adicionales, serán necesarias en el futuro cuando ampliemos la aplicación para tener usuarios registrados y tareas programadas. Por ahora, puede dejarlas como están.

      En este momento, nuestra tabla sigue vacía. Debemos ejecutar el comando db:seed para propagar la base de datos con nuestros lugares de ejemplo:

      • docker-compose exec app php artisan db:seed

      Con esto, se ejecutará nuestro alimentador y se insertarán los valores de ejemplo que definimos en nuestra clase PlacesTableSeeder. Verá un resultado similar a este:

      Output

      Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Ahora, vuelva a cargar la página de la aplicación en su navegador. Verá una página similar a la siguiente:

      Aplicación de demostración de Laravel

      Cuando necesite comenzar desde cero, podrá descartar todas sus tablas de la base de datos con lo siguiente:

      • docker-compose exec app php artisan db:wipe

      Output

      Dropped all tables successfully.

      Para ejecutar las migraciones de la aplicación y propagar las tablas con un solo comando, puede usar lo siguiente:

      • docker-compose exec app php artisan migrate --seed

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Si quiere revertir una migración, puede ejecutar lo siguiente:

      • docker-compose exec app php artisan migrate:rollback

      Con esto, se activará el método down para cada clase de migración dentro de la carpeta migrations. Normalmente, se eliminarán todas las tablas que se crearon a través de las clases de migración y se dejarán solo las tablas que se puedan haber creado de forma manual. Verá resultados como este:

      Output

      Rolling back: 2020_02_10_144134_create_places_table Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds) Rolling back: 2019_08_19_000000_create_failed_jobs_table Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)

      El comando rollback es especialmente útil cuando se realizan cambios en los modelos de la aplicación y no se puede usar un comando db:wipe; por ejemplo, si varios sistemas dependen de la misma base de datos.

      Conclusión

      En esta guía, abordamos la forma de usar migraciones y alimentadores de bases de datos para facilitar la creación de bases de datos de desarrollo y la prueba de estas para una aplicación de Laravel 6.

      Como paso siguiente, podría intereserle consultar la documentación de Laravel para obtener más información sobre cómo usar el generador de consultas y modelos de Eloquent para abstraer aún más el esquema de la base de datos de su aplicación.



      Source link

      Использование миграции и пополнения базы данных для настройки абстрактной базы данных в Laravel


      Миграции и пополнения — это мощные утилиты для базы данных, предоставляемые PHP-фреймворком Laravel, которые позволяют разработчикам быстро инициализировать, уничтожать и воссоздавать базу данных приложения. Эти утилиты помогают свести к минимуму проблемы несогласованности базы данных, которые могут возникать, когда несколько разработчиков работают над одним приложением: новым участникам нужно будет запустить всего несколько команд artisan для настройки базы данных при новой установке.

      В этом обучающем руководстве мы выполним миграцию и пополнения для заполнения базы данных демонстрационного приложения Laravel, используя примеры данных. В конце вы сможете уничтожать и воссоздавать таблицы базы данных в любой момент времени, пользуясь только командами artisan.

      Предварительные требования

      Для выполнения этого обучающего руководства вам потребуется следующее:

      Примечание. В этом обучающем руководстве мы будем использовать контейнеризованную среду разработки под управлением Docker Compose для запуска приложения, но вы можете использовать приложение на сервере LEMP. Чтобы воспользоваться этим вариантом, ознакомьтесь с нашим руководством по установке и настройке Laravel с LEMP в Ubuntu 18.04.

      Шаг 1 — Получение демонстрационного приложения

      Вначале мы получим демонстрационное приложение Laravel из репозитория GitHub. Нас интересует раздел tutorial-02, который содержит настройку Docker Compose для запуска приложения в контейнерах. В данном примере мы загрузим приложение в домашнюю папку, но вы можете использовать любую директорию по вашему выбору:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

      Поскольку мы загрузили код приложения в виде файла .zip, нам нужно воспользоваться командой unzip для распаковки архива. Если вы не использовали эту программу в последнее время, обновите локальный индекс пакетов вашего компьютера:

      Затем выполните установку пакета unzip:

      Распакуйте содержимое приложения:

      Далее необходимо переименовать директорию на travellist-demo для удобства доступа:

      • mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

      На следующем шаге мы создадим файл конфигурации .env для настройки приложения.

      Шаг 2 — Настройка файла .env приложения

      В Laravel файл .env используется для настройки зависимых от среды конфигураций, например, учетных данных и любой информации, которая может отличаться для разных развертываний. Этот файл не включен в систему контроля версий.

      Предупреждение. Файл конфигурации среды содержит важную информацию о вашем сервере, включая учетные данные базы данных и ключи безопасности. В связи с этим не следует предоставлять этот файл в открытый доступ.

      Значения в файле .env имеют приоритет по отношению к значениям в обычных файлах конфигурации, расположенных в директории config. Для каждого случая установки в новую среду требуется персонализированный файл среды, где будут определены такие настройки, как параметры подключения к базе данных, параметры отладки, URL приложения и другие параметры, в зависимости от используемой для запуска приложения среды.

      Перейдите в директорию travellist-demo:

      Теперь мы создадим новый файл .env для настройки индивидуальных параметров конфигурации для создаваемой нами среды разработки. В комплектацию Laravel входит образец файла .env, который мы скопируем для создания собственного файла:

      Откройте этот файл с помощью nano или другого текстового редактора на ваш выбор:

      Теперь ваш файл .env выглядит следующим образом:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password

      Текущий файл .env для демонстрационного приложения travellist содержит настройки для работы в контейнеризованной среде, которую мы создали с помощью Docker Compose в последней статье данной серии. Вам не обязательно вносить изменения в эти значения, но вы можете изменить значения DB_DATABASE, DB_USERNAME и DB_PASSWORD, если захотите, так как они автоматически подставляются из нашего файла docker-compose.yml для настройки базы данных разработки. Убедитесь, что переменная DB_HOST остается без изменений, поскольку она указывает имя нашей службы базы данных в среде Docker Compose.

      При внесении любых изменений в файл обязательно сохраните и закройте его, нажав CTRL + X, Y, а затем ENTER.

      Примечание. Если вы хотите запустить приложение на сервере LEMP, вам нужно изменить выделенные значения в соответствии с собственными настройками базы данных, включая значение переменной DB_HOST.

      Шаг 3 — Установка зависимостей приложения с помощью Composer

      Теперь мы воспользуемся Composer, инструментом для управления зависимостями PHP, чтобы установить зависимости приложения и обеспечить возможность выполнения команд artisan.

      Сформируйте вашу среду Docker Compose с помощью следующей команды. В результате будет создан образ travellist для службы app и добавлены дополнительные образы Docker, необходимые службам nginx и db, чтобы создать среду приложения:

      Output

      Creating network "travellist-demo_travellist" with driver "bridge" Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in 9259bb2ac034 … Creating travellist-app ... done Creating travellist-nginx ... done Creating travellist-db ... done

      Выполнение этой операции может занять несколько минут. После завершения процесса мы сможем запустить Composer для установки зависимостей приложения.

      Для выполнения composer и других команд в контейнере службы app мы будем использовать docker-compose exec. Команда exec позволяет нам выполнять любую команду по нашему выбору в контейнерах под управлением Docker Compose. Она имеет следующий синтаксис: docker-compose exec service_name command.

      Примечание. Если вы предпочитаете использовать сервер LEMP для запуска демонстрационного приложения, можно проигнорировать часть docker-compose exec app для команд, представленных в рамках этого руководства. Например, вместо запуска следующей команды, как она написана, вы можете использовать следующую команду:

      Чтобы выполнить установку composer в контейнер приложения, запустите следующую команду:

      • docker-compose exec app composer install

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) …

      Когда Composer выполнит установку зависимостей приложения, вы сможете выполнять команды artisan. Чтобы убедиться, что приложение сможет подключиться к базе данных, выполните следующую команду, которая выполняет очистку всех существующих таблиц:

      • docker-compose exec app php artisan db:wipe

      Эта команда будет удалять все ранее существовавшие таблицы в настроенной базе данных. Если выполнение команды было завершено успешно, а приложению удалось подключиться к базе данных, вы увидите следующий результат:

      Output

      Dropped all tables successfully.

      Теперь, когда вы установили зависимости приложения с помощью Composer, вы можете использовать инструмент artisan для создания миграций и пополнений.

      Шаг 4 — Создание миграций базы данных

      Инструмент командной строки artisan, предоставляемый вместе с Laravel, содержит ряд вспомогательных команд, которые могут использоваться для управления приложением и загрузки новых классов. Чтобы сгенерировать новый класс миграции, мы можем использовать команду make:migration следующим образом:

      • docker-compose exec app php artisan make:migration create_places_table

      Laravel выводит операцию, которую необходимо выполнить (create), имя таблицы (places), а также то, будет ли эта миграция создавать новую таблицу или нет, на основе описательного имени, предоставленного команде make:migration.

      Вывод будет выглядеть следующим образом:

      Output

      Created Migration: 2020_02_03_143622_create_places_table

      В результате будет создан новый файл в директории database/migrations приложения. Отметка времени, которая включается в автоматически генерируемый файл, используется Laravel для определения того, в каком порядке следует выполнять миграции.

      Используйте предпочитаемый вами текстовый редактор для открытия сгенерированного файла миграции. Обязательно замените выделенное значение на имя вашего файла миграции:

      • nano database/migrations/2020_02_03_143622_create_places_table.php

      Сгенерированный файл миграции содержит класс CreatePlacesTable:

      database/migrations/2020_02_03_143622_create_places_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreatePlacesTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('places');
          }
      }
      
      

      Этот класс имеет два метода: up и down. Оба метода содержат код начальной загрузки, который вы можете расширить, чтобы настроить то, что будет происходить, когда эта миграция выполняется, а также что будет происходить в случае отката изменений.

      Мы изменим метод up так, чтобы таблица places имела структуру, которую мы уже использовали в текущей версии приложения:

      • id: поле первичного ключа.
      • name: название места.
      • visited: было ли посещено это место или нет.

      Конструктор схемы Laravel предоставляет методы для создания, обновления и удаления таблиц в базе данных. Класс Blueprint определяет структуру таблицы и предоставляет несколько методов для абстракции определения каждого поля таблицы.

      Автоматически генерируемый код задает поле основного идентификатора id. Метод timestamps создает два поля datetime, которые автоматически обновляются классами соответствующей базы данных, когда данные помещаются в таблицу или обновляются. Помимо этого, нам потребуется добавить поля name и visited.

      Наше поле name будет иметь тип string, а для поля visited будет установлен тип boolean. Также мы зададим значение по умолчанию 0 для поля visited, так что если значение не будет передано, это будет означать, что место пока не посещено. Вот как в настоящий момент выглядит метод up:

      database/migrations/2020_02_03_143622_create_places_table.php

      …
          public function up()
          {
              Schema::create('places', function (Blueprint $table) {
                  $table->bigIncrements('id');
                  $table->string('name', 100);
                  $table->boolean('visited')->default(0);
                  $table->timestamps();
              });
          }
      …
      

      Примечание. Вы можете найти полный список доступных типов столбцов в документации Laravel.

      После добавления двух выделенных строк в вашем скрипте миграции сохраните и закройте файл.

      Теперь ваша миграция готова к исполнению с помощью artisan migrate. Однако в этом случае будет создана пустая таблица, а нам нужна возможность добавления примеров данных для разработки и тестирования. На следующем шаге мы узнаем, как сделать это с помощью пополнений базы данных.

      Шаг 5 — Создание пополнений для базы данных

      seeder — это специальный класс, используемый для генерации и вставки примеров данных в базу данных. Это очень важная функция для среды разработки, поскольку она позволяет воссоздать приложение с новой базой данных, используя примеры значений, которые вам в ином случае пришлось бы вручную вставлять при каждом воссоздании базы данных.

      Теперь мы воспользуемся командой artisan, которая генерирует новый класс seeder для нашей таблицы places с названием PlacesTableSeeder:

      • docker-compose exec app php artisan make:seeder PlacesTableSeeder

      Команда будет создавать новый файл с именем PlacesTableSeeder.php внутри директории database/seeds. Откройте этот файл в текстовом редакторе по выбору:

      • nano database/seeds/PlacesTableSeeder.php

      Вот как выглядит автоматически сгенерированный файл PlacesTableSeeder.php:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              //
          }
      }
      
      

      Наш новый класс seeder содержит пустой метод с именем run. Этот метод будет вызываться при выполнении команды db:seed Artisan.

      Нам нужно изменить метод run, чтобы включить инструкции по вставке примеров данных в базу данных. Мы воспользуемся конструктором запросов Laravel для организации этого процесса.

      Конструктор запросов Laravel предоставляет гибкий интерфейс для операций с базами данных, например, для вставки, обновления и восстановления данных. Также он обеспечивает защиту от внедрения SQL-кода. Конструктор запросов определяется фасадом DB, статическим прокси для классов базы данных в контейнере службы.

      Для начала мы создадим переменную статического класса, хранящую все примеры мест, которые мы хотим вставить в базу данных в форме массива. Это позволит нам использовать цикл foreach для итерации по всем значениям, вставляя все эти значения в базу данных с помощью конструктора запросов.

      Мы назовем эту переменную $places:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];

      Далее нам потребуется включить оператор use сверху класса PlacesTableSeeder, чтобы проще ссылаться на фасад DB в коде:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      …
      

      Теперь мы можем пробежаться по значениям массива $places с помощью цикла foreach и добавить их в нашу таблицу places с помощью конструктора запросов:

      database/seeds/PlacesTableSeeder.php

      …
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      
      

      Цикл foreach проходит по каждому значению статического массива $places. В каждой итерации мы используем фасад DB для добавления новой строки в таблице places. Мы сохраним в поле name название места, которое мы только что получили из массива $places, а для поля visited будет использоваться случайное значение 0 или 1.

      Класс PlacesTableSeeder будет выглядеть следующим образом после всех обновлений:

      database/seeds/PlacesTableSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      use IlluminateSupportFacadesDB;
      
      class PlacesTableSeeder extends Seeder
      {
          static $places = [
              'Berlin',
              'Budapest',
              'Cincinnati',
              'Denver',
              'Helsinki',
              'Lisbon',
              'Moscow',
              'Nairobi',
              'Oslo',
              'Rio',
              'Tokyo'
          ];
      
          /**
           * Run the database seeds.
           *
           * @return void
           */
          public function run()
          {
              foreach (self::$places as $place) {
                  DB::table('places')->insert([
                      'name' => $place,
                      'visited' => rand(0,1) == 1
                  ]);
              }
          }
      }
      

      Сохраните и закройте файл после внесения всех изменений.

      Классы типа seeder не загружаются автоматически в приложение. Нам нужно изменить главный класс DatabaseSeeder, чтобы добавить вызов класса типа seeder, который мы только что создали.

      Откройте файл database/seeds/DatabaseSeeder.php с помощью nano или вашего любимого редактора:

      • nano database/seeds/DatabaseSeeder.php

      Класс DatabaseSeeder выглядит стандартным образом: он наследуется от класса Seeder и имеет метод run. Мы обновим этот метод, чтобы включить PlacesTableSeeder.

      Обновите текущий метод run внутри вашего класса DatabaseSeeder, удалив закомментированную строку и заменив ее на следующий выделенный код:

      database/seeds/DatabaseSeeder.php

      …
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      ...
      

      Так будет выглядеть класс DatabaseSeeder после обновления:

      database/seeds/DatabaseSeeder.php

      <?php
      
      use IlluminateDatabaseSeeder;
      
      class DatabaseSeeder extends Seeder
      {
          /**
           * Seed the application's database.
           *
           * @return void
           */
          public function run()
          {
              $this->call(PlacesTableSeeder::class);
          }
      }
      
      
      

      Сохраните и закройте файл после внесения изменений в его содержимое.

      Мы завершили настройку миграции и наполнения для нашей таблицы places. На следующем шаге мы узнаем, как их запускать.

      Шаг 6 — Запуск миграции и наполнения базы данных

      Перед продолжением нужно убедиться, что ваше приложение готово и запущено. Мы настроим ключ шифрования приложения и получим доступ к приложению из браузера, чтобы протестировать веб-сервер.

      Чтобы сгенерировать ключ шифрования, требуемый Laravel, вы можете использовать команду artisan key:generate:

      • docker-compose exec app php artisan key:generate

      После получения ключа вы сможете получить доступ к приложению, указав в браузере имя хоста сервера или IP-адрес для порта 8000:

      http://server_host_or_ip:8000
      

      Страница будет выглядеть следующим образом:

      Ошибка MySQL

      Это означает, что приложение может подключаться к базе данных, но оно не может найти таблицу с именем places. Теперь мы создадим таблицу places, используя следующую команду migrate artisan:

      • docker-compose exec app php artisan migrate

      Вывод будет выглядеть следующим образом:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)

      Вы увидите, что несколько других миграций было выполнено наряду с настроенной нами миграцией create_places_table. Эти миграции генерируются автоматически, когда установлен Laravel. Хотя мы не будем использовать эти дополнительные таблицы сейчас, они будут необходимы в будущем при расширении приложения для зарегистрированных пользователей и запланированных заданий. Пока что вы можете оставить их как есть.

      На данный момент наша таблица пустая. Нам нужно запустить команду db:seed, чтобы наполнить базу данных нашими выбранными местами:

      • docker-compose exec app php artisan db:seed

      В результате будет запущен наш класс seeder и будут добавлены образцы значений, которые мы определили в нашем классе PlacesTableSeeder. Вывод будет выглядеть следующим образом:

      Output

      Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Теперь перезагрузите страницу приложения в браузере. Вы увидите приблизительно следующую страницу:

      Демонстрационное приложение Laravel

      Каждый раз, когда вы захотите начать с нуля, вы можете удалить все ваши таблицы базы данных, используя следующую команду:

      • docker-compose exec app php artisan db:wipe

      Output

      Dropped all tables successfully.

      Чтобы запустить миграцию приложения и заполнение таблиц с помощью одной команды, вы можете использовать следующий вариант:

      • docker-compose exec app php artisan migrate --seed

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

      Если вы захотите откатить изменения, запустите следующую команду:

      • docker-compose exec app php artisan migrate:rollback

      В результате будет запущен метод down для каждого класса миграции внутри папки migrations. Как правило, он удаляет все таблицы, созданные в классах миграции, оставляя все остальные таблицы, которые могли быть созданы вручную. Вывод будет выглядеть следующим образом:

      Output

      Rolling back: 2020_02_10_144134_create_places_table Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds) Rolling back: 2019_08_19_000000_create_failed_jobs_table Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)

      Команда отката изменений особенно полезна, когда вы вносите изменения в модели приложения, а команда db:wipe не может использоваться, например, если несколько систем используют одну базу данных.

      Заключение

      В этом руководстве мы увидели, как использовать миграции и наполнения для облегчения настройки баз данных для разработки и тестирования приложения Laravel 6.

      В качестве следующего шага вы можете ознакомиться с документацией Laravel для получения более подробной информации о том, как использовать конструктор запросов, и о том, как использовать модели Eloquent для дальнейшей абстракции схемы базы данных вашего приложения.



      Source link

      Conteinerizando um aplicativo Laravel 6 para o desenvolvimento com o Docker Compose no Ubuntu 18.04


      Introdução

      Conteinerizar um aplicativo se refere ao processo de adaptar um aplicativo e seus componentes com a finalidade de conseguir executá-lo em ambientes leves, conhecidos como contêineres. Esses ambientes são isolados e descartáveis e podem ser aproveitados para o desenvolver, testar e implantar aplicativos para a produção.

      Neste guia, usaremos o Docker Compose para conteinerizar um aplicativo Laravel 6 para o desenvolvimento. Quando você tiver terminado, terá um aplicativo de demonstração Laravel funcionando em três contêineres de serviço separados:

      • Um serviço de app executando o PHP7.4-FPM;
      • Um serviço de db executando o MySQL 5.7;
      • Um serviço de nginx que usa o serviço app para analisar o código PHP antes de entregar o aplicativo Laravel para o usuário final.

      Para permitir um processo de desenvolvimento simplificado e facilitar a depuração do aplicativo, manteremos os arquivos do aplicativo em sincronia, usando volumes compartilhados. Também veremos como usar os comandos docker-compose exec para executar o Composer e o Artisan no contêiner do app.

      Pré-requisitos

      Passo 1 — Obtendo o aplicativo Demo

      Para começar, vamos buscar o aplicativo demo do Laravel do seu repositório do Github. Estamos interessados na ramificação do tutorial-01, que contém o aplicativo básico do Laravel que criamos no primeiro guia desta série.

      Para obter o código do aplicativo compatível com este tutorial, baixe a versão tutorial-1.0.1 para seu diretório home com:

      • cd ~
      • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip

      Vamos precisar do comando unzip para descompactar o código do aplicativo. Caso não tenha instalado esse pacote antes, faça isso agora com:

      • sudo apt update
      • sudo apt install unzip

      Agora, descompacte os conteúdos do aplicativo e renomeie o diretório desempacotado para ter um acesso mais fácil:

      • unzip travellist.zip
      • mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo

      Navegue até o diretório travellist-demo:

      No próximo passo, vamos criar um arquivo de configuração .env para configurar o aplicativo.

      Passo 2 — Configurando o arquivo .env do aplicativo

      Os arquivos de configuração do Laravel estão localizados em um diretório chamado config, dentro do diretório raiz do aplicativo. Além disso, um arquivo .env é usado para preparar a configuração dependente do ambiente, como credenciais e quaisquer informações que possam variar entre as implantações. Esse arquivo não está incluído no controle de revisão.

      Aviso: o arquivo de configuração de ambiente contém informações confidenciais sobre o seu servidor, incluindo credenciais para o banco de dados e chaves de segurança. Por esse motivo, nunca compartilhe esse arquivo publicamente.

      Os valores contidos no arquivo .env terão precedência sobre os valores definidos nos arquivos de configuração regulares, localizados no diretório config. Cada instalação em novo ambiente exige um arquivo de ambiente personalizado para definir coisas como as configurações da conexão com o banco de dados, as opções de depuração, a URL do aplicativo, entre outros itens que possam variar, dependendo do ambiente em que o aplicativo esteja funcionando.

      Agora, vamos criar um novo arquivo .env para personalizar as opções de configuração do ambiente de desenvolvimento que estamos preparando. O Laravel vem com um exemplo de arquivo do .env que podemos copiar para criar o nosso:

      Abra este arquivo usando o nano ou outro editor de texto de sua escolha:

      O arquivo .env atual do aplicativo demo travellist contém as configurações para usar um banco de dados local do MySQL, com o 127.0.0.1 como o host do banco de dados. Precisamos atualizar a variável DB_HOST para que ela aponte para o serviço de banco de dados que vamos criar em nosso ambiente do Docker. Neste guia, vamos chamar nosso serviço de banco de dados de db. Vá em frente e substitua o valor listado de DB_HOST pelo nome do serviço de banco de dados:

      .env

      APP_NAME=Travellist
      APP_ENV=dev
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      
      DB_CONNECTION=mysql
      DB_HOST=db
      DB_PORT=3306
      DB_DATABASE=travellist
      DB_USERNAME=travellist_user
      DB_PASSWORD=password
      ...
      

      Caso queira, sinta-se à vontade para alterar o nome do bando de dados, nome de usuário e senha. Essas variáveis serão aproveitadas em um próximo passo, onde iremos definir o arquivo docker-compose.yml para configurar nossos serviços.

      Salve o arquivo quando terminar de editar. Se você usou o nano, você pode fazer isso pressionando Ctrl+x, depois Y e Enter para confirmar.

      Passo 3 — Configurando o Dockerfile do aplicativo

      Embora ambos os nossos serviços do MySQL e do Nginx se baseiem em imagens padronizadas, obtidas a partir do Docker Hub,ainda precisaremos compilar uma imagem personalizada para o contêiner do aplicativo. Criaremos um novo Dockerfile para isso.

      Nossa imagem do travellist irá basear-se na imagem oficial do PHP, php:7.4-fpm​​​ do Docker Hub. Além desse ambiente básico do PHP-FPM, instalaremos alguns módulos adicionais do PHP e a ferramenta de gerenciamento de dependência do Composer.

      Também iremos criar um novo usuário do sistema; isso é necessário para executar comandos do artisan e do composer durante o desenvolvimento do aplicativo. A configuração do uid garante que o usuário dentro do contêiner tenha o mesmo uid que o usuário do sistema no seu computador host, onde você estiver executando o Docker. Dessa forma, quaisquer arquivos criados por esses comandos são replicados no host com as permissões corretas. Isso também significa que você poderá usar o editor de códigos de sua escolha no computador host para desenvolver o aplicativo que está executando dentro dos contêineres.

      Crie um novo Dockerfile com:

      Copie o seguinte conteúdo para o seu Dockerfile:

      Dockerfile

      FROM php:7.4-fpm
      
      # Arguments defined in docker-compose.yml
      ARG user
      ARG uid
      
      # Install system dependencies
      RUN apt-get update && apt-get install -y 
          git 
          curl 
          libpng-dev 
          libonig-dev 
          libxml2-dev 
          zip 
          unzip
      
      # Clear cache
      RUN apt-get clean && rm -rf /var/lib/apt/lists/*
      
      # Install PHP extensions
      RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
      
      # Get latest Composer
      COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
      
      # Create system user to run Composer and Artisan Commands
      RUN useradd -G www-data,root -u $uid -d /home/$user $user
      RUN mkdir -p /home/$user/.composer && 
          chown -R $user:$user /home/$user
      
      # Set working directory
      WORKDIR /var/www
      
      USER $user
      
      

      Não se esqueça de salvar o arquivo quando terminar.

      Nosso Dockerfile começa pela definição da imagem base que estamos usando: php:7.4-fpm.

      Após instalar os pacotes do sistema e as extensões do PHP, instalaremos o Composer, copiando o executáve composer de sua última imagem oficial para nossa imagem do aplicativo.

      Então, um novo usuário do sistema é criado e configurado usando os argumentos user e uid que foram declarados no início do Dockerfile. Esses valores serão injetados pelo Docker Compose no momento da compilação.

      Por fim, definimos o dir padrão em funcionamento como /var/www e trocamos para o usuário recém-criado. Isso garantirá que, ao executar os comandos do composer e do artisan no contêiner do aplicativo, você esteja se conectando como um usuário comum e que esteja no diretório correto.

      Passo 4 — Configurando os arquivos de configuração do Nginx e os arquivos de despejo do banco de dados

      Ao criar ambientes de desenvolvimento com o Docker Compose, com frequência, é necessário compartilhar os arquivos de configuração ou de inicialização com os contêineres de serviço, para assim configurar ou inicializar esses serviços. Essa prática facilita fazer alterações nos arquivos de configuração para ajustar seu ambiente enquanto estiver desenvolvendo o aplicativo.

      Agora, vamos definir uma pasta com os arquivos que serão usados para configurar e inicializar nossos contêineres de serviço.

      Para configurar o Nginx, compartilharemos um arquivo travellist.conf que configurará como o aplicativo será atendido. Crie a pasta docker-compose/nginx com:

      • mkdir -p docker-compose/nginx

      Abra um novo arquivo chamado de travellist.conf dentro desse diretório:

      • nano docker-compose/nginx/travellist.conf

      Copie a seguinte configuração do Nginx para aquele arquivo:

      docker-compose/nginx/travellist.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;
          }
      }
      

      Esse arquivo irá configurar o Nginx para escutar na porta 80 e usar o index.php como a página de índice padrão. Ele definirá o diretório base como /var/www/public e, em seguida, configurará o Nginx para usar o serviço app na porta 9000 para processar os arquivos *.php.

      Salve e feche o arquivo quando terminar de editar.

      Para configurar o banco de dados do MySQL, compartilharemos um banco de dados de despejo que será importado quando o contêiner for inicializado. Esta é uma característica fornecida pela imagem do MySQL 5.7, que usaremos naquele contêiner.

      Crie uma nova pasta para seus arquivos de inicialização do MySQL dentro da pasta docker-compose:

      • mkdir docker-compose/mysql

      Abra um novo arquivo .sql:

      • nano docker-compose/mysql/init_db.sql

      O arquivo de despejo do MySQL se baseia no banco de dados que configuramos em nosso guia do Laravel em LEMP. Ele criará uma nova tabela chamada places. Então, ele preencherá a tabela com um conjunto de exemplos de localidade.

      Adicione o código a seguir ao arquivo:

      docker-compose/mysql/db_init.sql

      DROP TABLE IF EXISTS `places`;
      
      CREATE TABLE `places` (
        `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
        `visited` tinyint(1) NOT NULL DEFAULT '0',
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
      
      INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0);
      

      A tabela places contém três campos: id, name e visited. O campo visited é um sinalizador utilizado para identificar os lugares que ainda não foram visitados. Sinta-se à vontade para modificar os exemplos de localidade ou incluir novos locais. Salve e feche o arquivo quando terminar.

      Terminamos de configurar o Dockerfile do aplicativo e os arquivos de configuração de serviço. Em seguida, configuraremos o Docker Compose para usar esses arquivos ao criar nossos serviços.

      O Docker Compose permite a criação de ambientes multicontêiner para os aplicativos em execução no Docker. Ele usa as definições de serviço para compilar ambientes totalmente personalizáveis com vários contêineres que podem compartilhar redes e volumes de dados. Isso permite uma integração perfeita entre os componentes do aplicativo.

      Para configurar nossas definições de serviço, criaremos um novo arquivo chamado docker-compose.yml. Este arquivo fica normalmente localizado na raiz da pasta do aplicativo. Ele define seu ambiente em contêiner, incluindo as imagens base que você usará para compilar seus contêineres e como seus serviços irão interagir.

      Vamos definir três serviços diferentes em nosso arquivo docker-compose.yml: app, db e nginx.

      O serviço app compilará uma imagem chamada travellist, com base no Dockerfile que criamos anteriormente. O contêiner definido por esse serviço executará um servidor php-fpm para analisar o código PHP e enviará os resultados de volta para o serviço do nginx, o qual estará em execução em um contêiner separado. O serviço mysql define um contêiner que executa um servidor do MySQL 5.7. Nosso serviços irão compartilhar uma conexão de rede de ponte chamada de travellist.

      Os arquivos do aplicativo serão sincronizados nos serviços do app e do nginx através de montagens associadas. As montagens bind são úteis em ambientes de desenvolvimento porque elas levam em conta um desempenho sincronizado bidirecional entre o computador host e os contêineres.

      Crie um novo arquivo docker-compose.yml na raiz da pasta do aplicativo:

      Um arquivo típico do docker-compose.yml começa com uma definição de versão, seguido de um nó de services, sob o qual todos os serviços são definidos. As redes compartilhadas são geralmente definidas no final desse arquivo.

      Para começar, copie este código boilerplate para o seu arquivo docker-compose.yml:

      docker-compose.yml

      version: "3.7"
      services:
      
      
      networks:
        travellist:
          driver: bridge
      

      Agora, vamos editar o nó de services para incluir os serviços app, db e nginx.

      O serviço app

      O serviço app configurará um contêiner chamado travellist-app. Ele compila uma nova imagem do Docker com base em um Dockerfile - localizado no mesmo caminho que o arquivo docker-compose.yml. A nova imagem será salva localmente sob o nome travellist.

      Embora o diretório base que está sendo atendido como o aplicativo esteja localizado no contêiner do nginx, também precisamos dos arquivos do aplicativo em algum lugar dentro do contêiner de app, para que possamos executar tarefas de linha de comando com a ferramenta Laravel Artisan.

      Copie a seguinte definição de serviço sob seu nó de services, dentro do arquivo docker-compose.yml:

      docker-compose.yml

        app:
          build:
            args:
              user: sammy
              uid: 1000
            context: ./
            dockerfile: Dockerfile
          image: travellist
          container_name: travellist-app
          restart: unless-stopped
          working_dir: /var/www/
          volumes:
            - ./:/var/www
          networks:
            - travellist
      

      Essas configurações fazem o seguinte:

      • build: esta configuração diz ao Docker Compose para compilar uma imagem local para o serviço app, usando o caminho especificado (contexto) e o Dockerfile para obter instruções. Os argumentos user e uid são injetados no Dockerfile para personalizar os comandos de criação de usuário no momento da compilação.
      • image: o nome que será usado para a imagem que está sendo criada.
      • container_name: define o nome do contêiner desse serviço.
      • restart: sempre reinicia, a menos que o serviço seja interrompido.
      • working_dir: define o diretório padrão para esse serviço como /var/www.
      • volumes: cria um volume compartilhado que sincronizará o conteúdo do diretório atual para o /var/www, dentro do contêiner. Note que esse não é o seu diretório raiz, uma vez que ele ficará no contêiner nginx.
      • networks: define esse serviço para usar uma rede chamada travellist.

      O serviço db

      O serviço db usa uma imagem de MySQL 5.7 pré-compilada do Docker Hub. Como o Docker Compose carrega automaticamente os arquivos da variável .env, localizados no mesmo diretório que o arquivo docker-compose.yml, podemos obter nossas configurações de banco de dados do arquivo .env do Laravel que criamos em um passo anterior.

      Inclua a seguinte definição de serviço no nó de seus services, logo após o serviço app:

      docker-compose.yml

        db:
          image: mysql:5.7
          container_name: travellist-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_USER: ${DB_USERNAME}
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - ./docker-compose/mysql:/docker-entrypoint-initdb.d
          networks:
            - travellist
      

      Essas configurações fazem o seguinte:

      • image: define a imagem do Docker que deve ser usada para este contêiner. Neste caso, estamos usando uma imagem MySQL 5.7 do Docker Hub.
      • container_name: define o nome do contêiner para este serviço: travellist-db​​​.
      • restart: sempre reinicia este serviço, a menos que ele seja explicitamente interrompido.
      • environment: define as variáveis de ambiente no novo contêiner. Estamos usando valores obtidos a partir do arquivo .env do Laravel para configurar nosso serviço do MySQL, o qual irá criar - automaticamente - um novo banco de dados e um usuário, com base nas variáveis de ambiente fornecidas.
      • volumes: cria um volume para compartilhar um arquivo de despejo de banco de dados .sql que será usado para inicializar o banco de dados do aplicativo. A imagem do MySQL importará automaticamente os arquivos .sql colocados no diretório /docker-entrypoint-initdb.d dentro do contêiner.
      • networks: define esse serviço para usar uma rede chamada travellist.

      O serviço nginx

      O serviço nginx usa uma imagem do Nginx pré-compilada sobre o Alpine, uma distribuição de Linux leve. Ela cria um contêiner chamado travellist-nginx e usa a definição de ports para criar um redirecionamento da porta 8000 - no sistema host - para a porta 80 - dentro do contêiner.

      Inclua a seguinte definição de serviço no nó de seus services, logo após o serviço db:

      docker-compose.yml

        nginx:
          image: nginx:1.17-alpine
          container_name: travellist-nginx
          restart: unless-stopped
          ports:
            - 8000:80
          volumes:
            - ./:/var/www
            - ./docker-compose/nginx:/etc/nginx/conf.d
          networks:
            - travellist
      

      Essas configurações fazem o seguinte:

      • image: define a imagem do Docker que deve ser usada para este contêiner. Neste caso, estamos usando a imagem do Alpine Nginx 1.17.
      • container_name: define o nome do contêiner para este serviço: travellist-nginx​​​.
      • restart: sempre reinicia este serviço, a menos que ele seja explicitamente interrompido.
      • ports: define um redirecionamento de porta que permitirá o acesso externo através da porta 8000 para o servidor Web em execução na porta 80, dentro do contêiner.
      • volumes: cria dois volumes compartilhados. O primeiro sincronizará o conteúdo do diretório atual para o /var/www, dentro do contêiner. Dessa forma, quando fizer alterações locais nos arquivos do aplicativo, elas serão refletidas rapidamente no aplicativo que está sendo atendido pelo Nginx, dentro do contêiner. O segundo volume garantirá que o nosso arquivo de configuração do Nginx, localizado em docker-compose/nginx/travellist.conf, seja copiado para a pasta de configuração do Nginx do contêiner.
      • networks: define esse serviço para usar uma rede chamada travellist.

      Arquivo docker-compose.yml finalizado

      Nosso arquivo docker-compose.yml finalizado ficará com esta aparência:

      docker-compose.yml

      version: "3.7"
      services:
        app:
          build:
            args:
              user: sammy
              uid: 1000
            context: ./
            dockerfile: Dockerfile
          image: travellist
          container_name: travellist-app
          restart: unless-stopped
          working_dir: /var/www/
          volumes:
            - ./:/var/www
          networks:
            - travellist
      
        db:
          image: mysql:5.7
          container_name: travellist-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_USER: ${DB_USERNAME}
            SERVICE_TAGS: dev
            SERVICE_NAME: mysql
          volumes:
            - ./docker-compose/mysql:/docker-entrypoint-initdb.d
          networks:
            - travellist
      
        nginx:
          image: nginx:alpine
          container_name: travellist-nginx
          restart: unless-stopped
          ports:
            - 8000:80
          volumes:
            - ./:/var/www
            - ./docker-compose/nginx:/etc/nginx/conf.d/
          networks:
            - travellist
      
      networks:
        travellist:
          driver: bridge
      

      Certifique-se de salvar o arquivo quando terminar.

      Agora, usaremos os comandos do docker-compose para compilar a imagem do aplicativo e executar os serviços que especificamos em nossa configuração.

      Compile a imagem do app com o seguinte comando:

      Esse comando pode levar alguns minutos para completar. Você verá um resultado similar a este:

      Output

      Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest

      Quando a compilação estiver concluída, você poderá executar o ambiente em segundo plano com:

      Output

      Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done

      Isso executará seus contêineres em segundo plano. Para exibir informações sobre o estado de seus serviços ativos, execute:

      Você verá um resultado como esse:

      Output

      Name Command State Ports ------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp

      Agora, seu ambiente está funcionando! Porém, ainda precisaremos executar alguns comandos para concluir a configuração do aplicativo. Você pode usar o comando docker-compose exec para executar comandos nos contêineres de serviço, como um ls -l para exibir informações detalhadas sobre os arquivos no diretório do aplicativo:

      • docker-compose exec app ls -l

      Output

      total 256 -rw-rw-r-- 1 sammy 1001 738 Jan 15 16:46 Dockerfile -rw-rw-r-- 1 sammy 1001 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy 1001 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy 1001 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy 1001 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy 1001 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy 1001 4096 Jan 15 16:46 docker-compose -rw-rw-r-- 1 sammy 1001 1015 Jan 15 16:45 docker-compose.yml -rw-rw-r-- 1 sammy 1001 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy 1001 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy 1001 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy 1001 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy 1001 4096 Jan 7 08:05 tests -rw-rw-r-- 1 sammy 1001 538 Jan 7 08:05 webpack.mix.js

      Agora, vamos executar o composer install para instalar as dependências do aplicativo:

      • docker-compose exec app composer install

      Você verá um resultado como esse:

      Output

      Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > IlluminateFoundationComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully.

      A última coisa que precisamos fazer - antes de testar o aplicativo - é gerar uma chave única para o aplicativo com a artisan, a ferramenta de linha de comando do Laravel. Esta chave é usada para criptografar sessões de usuário e outros dados confidenciais:

      • docker-compose exec app php artisan key:generate

      Output

      Application key set successfully.

      Agora, vá até seu navegador e acesse o nome de domínio ou endereço IP do seu servidor na porta 8000:

      http://server_domain_or_IP:8000
      

      Você verá uma página como esta:

      Demo do aplicativo Laravel

      Você pode usar o comando logs para verificar os registros gerados por seus serviços:

      • docker-compose logs nginx
      Attaching to travellist-nginx
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:25 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:26 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:42 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      …
      

      Se quiser pausar seu ambiente do Docker Compose ao mesmo tempo que mantém o estado de todos seus serviços, execute:

      Output

      Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done

      Em seguida, você poderá retomar os seus serviços com:

      Output

      Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done

      Para fechar seu ambiente do Docker Compose e remover todos os seus contêineres, redes e volumes, execute:

      Output

      Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist

      Para obter um panorama de todos os comandos do Docker Compose, verifique a Referência da linha de comando do Docker Compose.

      Conclusão

      Neste guia, configuramos um ambiente do Docker com três contêineres, usando o Docker Compose para definir nossa infraestrutura em um arquivo YAML.

      A partir deste ponto, você poderá trabalhar no seu aplicativo do Laravel sem a necessidade de instalar e configurar um servidor Web local para desenvolvimentos e testes. Além disso, você estará trabalhando com um ambiente descartável e que pode ser facilmente replicado e distribuído, o que pode ser útil ao desenvolver seu aplicativo e ao passar para um ambiente de produção.



      Source link