One place for hosting & domains

      настройка

      Установка и настройка Zabbix для безопасного мониторинга удаленных серверов в Ubuntu 20.04


      Автор выбрал Computer History Museum для получения пожертвования в рамках программы Write for DOnations.

      Введение

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

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

      Сервер Zabbix хранит свои данные в реляционной базе данных, работающей на базе MySQL или PostgreSQL. Также вы можете хранить исторические данные в таких базах данных, как Elasticsearch и TimescaleDB. Zabbix предоставляет веб-интерфейс для возможности просмотра данных и настройки системы.

      В этом обучающем модуле мы настроим Zabbix на двух компьютерах Ubuntu 20.04. Один из них будет настроен в качестве сервера Zabbix, а второй — в качестве клиента, который будет отслеживаться. Сервер Zabbix будет использовать базу данных MySQL для записи данных мониторинга и использовать Nginx для обслуживания веб-интерфейса.

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

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

      • Два сервера Ubuntu 20.04, настроенных в соответствии с указаниями обучающего модуля Начальная настройка сервера для Ubuntu 20.04, включая пользователя без привилегий root с привилегиями sudo и настроенный брандмауэр ufw. На одном сервере вы установите Zabbix. В этом обучающем модуле он будет называться сервер Zabbix. Он будет отслеживать ваш второй сервер, этот второй сервер будет называться второй сервер Ubuntu.

      • Для сервера, на базе которого будет работать сервер Zabbix, требуется установка Nginx, MySQL и PHP. Следуйте шагам 1–3 нашего обучающего руководства по набору LEMP Ubuntu 20.04 для их настройки на вашем сервере Zabbix.

      • Зарегистрированное доменное имя. В этом обучающем руководстве мы будем использовать your_domain. Вы можете купить доменное имя на Namecheap, получить его бесплатно на Freenom или воспользоваться услугами любого предпочитаемого регистратора доменных имен.

      • На вашем сервере Zabbix должны быть настроены обе нижеследующие записи DNS. Если вы используете DigitalOcean, ознакомьтесь с нашей документацией по DNS для получения подробной информации по их добавлению.

        • Запись A, где your_domain указывает на публичный IP-адрес вашего сервера Zabbix.
        • Запись A, где www.your_domain указывает на публичный IP-адрес вашего сервера Zabbix.

      Кроме того, поскольку сервер Zabbix используется для доступа к ценной информации о вашей инфраструктуре, которую вам нужно защищать от несанкционированного доступа, очень важно обеспечить защиту сервера сертификатом TLS/SSL. Это необязательно, но настоятельно рекомендуется. Если вы хотите защитить ваш сервер, следуйте указаниям руководства Let’s Encrypt в Ubuntu 20.04 после шага 3 этого обучающего модуля.

      Шаг 1 — Установка сервера Zabbix

      Во-первых, нужно установить Zabbix на сервере, на котором вы установили MySQL, Nginx и PHP. Выполните вход на эту машину в качестве пользователя без прав root:

      • ssh sammy@zabbix_server_ip_address

      Zabbix доступен в диспетчере пакетов Ubuntu, но он уже устарел, поэтому используйте официальный репозиторий Zabbix для установки последней стабильной версии. Загрузите и установите пакет конфигурации репозитория:

      • wget https://repo.zabbix.com/zabbix/5.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.0-1+focal_all.deb
      • sudo dpkg -i zabbix-release_5.0-1+focal_all.deb

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

      Output

      Selecting previously unselected package zabbix-release. (Reading database ... 64058 files and directories currently installed.) Preparing to unpack zabbix-release_5.0-1+focal_all.deb ... Unpacking zabbix-release (1:5.0-1+focal) ... Setting up zabbix-release (1:5.0-1+focal) ...

      Обновите индекс пакета, чтобы новый репозиторий включал:

      Затем установите сервер Zabbix и пользовательский веб-интерфейс с поддержкой базы данных MySQL:

      • sudo apt install zabbix-server-mysql zabbix-frontend-php

      Также установите агент Zabbix, который позволит вам собирать данные непосредственно о статусе сервера Zabbix.

      • sudo apt install zabbix-agent

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

      Шаг 2 — Настройка базы данных MySQL для Zabbix

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

      Войдите в MySQL в качестве пользователя root:

      Создайте базу данных Zabbix с поддержкой символов UTF-8:

      • create database zabbix character set utf8 collate utf8_bin;

      Затем создайте пользователя, которого будет использовать сервер Zabbix, предоставьте ему доступ к новой базе данных и установите пароль для пользователя:

      • create user zabbix@localhost identified by 'your_zabbix_mysql_password';
      • grant all privileges on zabbix.* to zabbix@localhost;

      Он защитит пользователя и базу данных. Выйдите из консоли базы данных.

      Далее вам потребуется импортировать начальную схему и данные. При установке Zabbix вам был предоставлен файл, который сделает это.

      Запустите следующую команду для настройки схемы и импорта данных в базу данных zabbix. Используйте zcat, так как данные в файле сжаты:

      • zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix

      Введите пароль пользователя MySQL zabbix, который вы настроил при получении соответствующей инструкции.

      Выполнение этой команды может занять одну или две минуты. Если вы видите ошибку ERROR 1045 (28000): Access denied for userzabbix@'localhost' (using password: YES), убедитесь, что используете правильный пароль для пользователя zabbix.

      Чтобы сервер Zabbix использовал эту базу данных, вам нужно задать пароль базы данных в файле конфигурации сервера Zabbix. Откройте файл конфигурации в предпочитаемом текстовом редакторе. В этом обучающем руководстве мы будем использовать nano:

      • sudo nano /etc/zabbix/zabbix_server.conf

      Найдите следующую часть файла:

      /etc/zabbix/zabbix_server.conf

      ...
      ### Option: DBPassword                           
      #       Database password. Ignored for SQLite.   
      #       Comment this line if no password is used.
      #                                                
      # Mandatory: no                                  
      # Default:                                       
      # DBPassword=
      ...
      

      Эти комментарии в файле объясняют, как подключаться к базе данных. Вам необходимо задать значение DBPassword в файле для пароля для вашего пользователя базы данных. Добавьте эту строку после этих комментариев для настройки базы данных:

      /etc/zabbix/zabbix_server.conf

      ...
      DBPassword=your_zabbix_mysql_password
      ...
      

      Сохраните и закройте zabbix_server.conf​​​, нажав CTRL+X, а затем Y и ENTER, если вы используете nano.

      Теперь вы настроили сервер Zabbix для подключения к базе данных. Затем вы настроите веб-сервер Nginx для обслуживания пользовательского интерфейса Zabbix.

      Шаг 3 — Настройка Nginx для Zabbix

      Для автоматической настройки Nginx установите пакет автоматической настройки:

      • sudo apt install zabbix-nginx-conf

      В результате вы получите файл конфигурации /etc/zabbix/nginx.conf, а также ссылку на него в каталоге конфигурации Nginx /etc/zabbix/nginx.conf.

      Затем вам нужно внести изменения в этот файл. Откройте файл конфигурации:

      • sudo nano /etc/zabbix/nginx.conf

      Файл содержит автоматически сгенерированную конфигурацию серверного блока Nginx. Он содержит две строки, определяющие имя сервера и порт, который он прослушивает:

      /etc/zabbix/nginx.conf

      server {
      #        listen          80;
      #        server_name     example.com;
      ...
      

      Раскомментируйте две строки и замените example.com на свое доменное имя. Ваши настройки будут выглядеть следующим образом:

      /etc/zabbix/nginx.conf

      server {
              listen          80;
              server_name     your_domain;
      ...
      

      Сохраните и закройте файл. Проведите тестирования, чтобы убедиться в отсутствии ошибок синтаксиса в файлах Nginx, и повторно загрузите конфигурацию:

      • sudo nginx -t
      • sudo nginx -s reload

      Теперь, после настройки Nginx для обслуживания пользовательского интерфейса Zabbix, вы внесете некоторые изменения в настройку PHP, чтобы обеспечить правильность работы пользовательского интерфейса

      Примечание. Как указывалось в разделе предварительных требований, рекомендуется включить на сервере SSL/TLS. Если вы хотите сделать это, перед тем как перейти к шагу 4, выполните действия нашего обучающего модуля о Let’s Encrypt в Ubuntu 20.04 для получения бесплатного сертификата SSL для Nginx. Этот процесс автоматически обнаружит ваш серверный блок Zabbix и выполнит настройку для HTTPS. После получения сертификата SSL/TLS вы можете вернуться и завершить прохождение этого обучающего модуля.

      Шаг 4 — Настройка PHP для Zabbix

      Веб-интерфейс Zabbix написан на языке PHP, и для него требуется ряд специальных настроек сервера PHP. В ходе установки Zabbix был создан файл конфигурации PHP-FPM, который содержит эти настройки. Он расположен в каталоге /etc/zabbix и загружается автоматически PHP-FPM. Вам нужно внести небольшое изменение в этот файл, поэтому откройте его следующим образом:

      • sudo nano /etc/zabbix/php-fpm.conf

      Файл содержит параметры PHP, соответствующие необходимым требованиям для веб-интерфейса Zabbix. Однако настройка часового пояса комментируется по умолчанию. Чтобы Zabbix использовал правильное время, необходимо установить соответствующий часовой пояс:

      /etc/zabbix/php-fpm.conf

      ...
      php_value[max_execution_time] = 300
      php_value[memory_limit] = 128M
      php_value[post_max_size] = 16M
      php_value[upload_max_filesize] = 2M
      php_value[max_input_time] = 300
      php_value[max_input_vars] = 10000
      ; php_value[date.timezone] = Europe/Riga
      

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

      Теперь перезапустите PHP-FPM для применения этих новых настроек:

      • sudo systemctl restart php7.4-fpm.service

      Теперь вы можете запустить сервер Zabbix:

      • sudo systemctl start zabbix-server

      Затем проверьте правильность работы сервера Zabbix:

      • sudo systemctl status zabbix-server

      Вы увидите следующий статус:

      Output

      ● zabbix-server.service - Zabbix Server Loaded: loaded (/lib/systemd/system/zabbix-server.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-12 05:59:32 UTC; 36s ago Process: 27026 ExecStart=/usr/sbin/zabbix_server -c $CONFFILE (code=exited, status=0/SUCCESS) ...

      Наконец, включите запуск сервера в момент загрузки:

      • sudo systemctl enable zabbix-server

      Сервер настроен и подключен к базе данных. Затем настройте веб-интерфейс.

      Шаг — Конфигурация настроек для веб-интерфейса Zabbix

      Веб-интерфейс позволяет видеть отчеты и добавлять хосты, которые вы хотите отслеживать, но для этого требуется определенная начальная настройка. Запустите браузер и перейдите по адресу http://zabbix_server_name или https://zabbix_server_name, если вы установили Let’s Encrypt. На первом экране вы увидите приветственное сообщение. Нажмите Next step (Далее), чтобы продолжить.

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

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

      Рядом со всеми значениями в этой таблице должно стоять ОК, проверьте это. Обязательно прокрутите вниз и просмотрите все предварительные требования. Убедившись, что все готово, нажмите Next step (Далее), чтобы продолжить.

      Следующий экран запросит данные для подключения базы данных.

      Подключение базы занных

      Вы сообщили серверу Zabbix о вашей базе данных, но веб-интерфейсу Zabbix также необходим доступ к базе данных для управления хостами и считывания данных. Поэтому введите учетные данные MySQL, настроенные в шаге 2. Нажмите Next step (Далее), чтобы продолжить.

      На следующем экране вы можете оставить опции по умолчанию.

      Данные сервера Zabbix

      Name (Имя) необязательно; оно используется в веб-интерфейсе, чтобы различать серверы, если у вас несколько отслеживающих серверов. Нажмите Next step (Далее), чтобы продолжить.

      На следующем экране отобразится резюме предварительной установки, чтобы убедиться, что все указано верно.

      Summary

      Нажмите Next step (Далее), чтобы перейти к последнему экрану.

      Теперь установка веб-интерфейса завершена. В ходе этого процесса создается файл конфигурации /usr/share/zabbix/conf/zabbix.conf.php. Можно сделать его резервную копию и использовать в будущем. Нажмите Finish (Готово), чтобы перейти на экран входа. По умолчанию устанавливается пользователь Admin и пароль zabbix.

      Перед входом, установите агент Zabbix на вашем втором сервере Ubuntu.

      Шаг 6 — Установка и настройка агента Zabbix

      Теперь вам нужно настроить ПО агента, которое будет отправлять данные мониторинга на сервер

      Войдите на второй сервер Ubuntu:

      • ssh sammy@second_ubuntu_server_ip_address

      Как и на сервере Zabbix, запустите следующие команды для установки пакета конфигурации репозитория:

      • wget https://repo.zabbix.com/zabbix/5.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.0-1+focal_all.deb
      • sudo dpkg -i zabbix-release_5.0-1+focal_all.deb

      Затем обновите индекс пакета:

      Затем установите агент Zabbix:

      • sudo apt install zabbix-agent

      Хотя Zabbix поддерживает шифрование с помощью сертификата, настройка центра сертификации на входит в этот обучающий модуль. Но вы можете использовать предварительно предоставленные ключи (PSK)​​​ для защиты соединения между сервером и агентом.

      Сначала, сгенерируйте PSK:

      • sudo sh -c "openssl rand -hex 32 > /etc/zabbix/zabbix_agentd.psk"

      Отобразите ключ с помощью cat​​​, чтобы скопировать его:

      • cat /etc/zabbix/zabbix_agentd.psk

      Ключ будет выглядеть примерно так:

      Output

      75ad6cb5e17d244ac8c00c96a1b074d0550b8e7b15d0ab3cde60cd79af280fca

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

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

      • sudo nano /etc/zabbix/zabbix_agentd.conf

      Каждая настройка в этом файле документируется с помощью информационных комментариев по всему файлу, но вам нужно отредактировать только некоторые из них.

      Сначала нужно отредактировать IP-адрес сервера Zabbix. Найдите следующий раздел:

      /etc/zabbix/zabbix_agentd.conf

      ...
      ### Option: Server
      #       List of comma delimited IP addresses, optionally in CIDR notation, or DNS names of Zabbix servers and Zabbix proxies.
      #       Incoming connections will be accepted only from the hosts listed here.
      #       If IPv6 support is enabled then '127.0.0.1', '::127.0.0.1', '::ffff:127.0.0.1' are treated equally
      #       and '::/0' will allow any IPv4 or IPv6 address.
      #       '0.0.0.0/0' can be used to allow any IPv4 address.
      #       Example: Server=127.0.0.1,192.168.1.0/24,::1,2001:db8::/32,zabbix.example.com
      #
      # Mandatory: yes, if StartAgents is not explicitly set to 0
      # Default:
      # Server=
      
      Server=127.0.0.1
      ...
      

      Измените значение по умолчанию на IP-адрес вашего сервера Zabbix:

      /etc/zabbix/zabbix_agentd.conf

      ...
      Server=zabbix_server_ip_address
      ...
      

      По умолчанию сервер Zabbix подключается к агенту. Но для некоторых проверок (например, для мониторинга журналов) требуется обратное подключение. Для правильной работы нужно указать адрес сервера Zabbix и уникальное имя хоста.

      Найдите раздел, который настраивает активные проверки и измените значения по умолчанию:

      /etc/zabbix/zabbix_agentd.conf

      ...
      ##### Active checks related
      
      ### Option: ServerActive
      #       List of comma delimited IP:port (or DNS name:port) pairs of Zabbix servers and Zabbix proxies for active checks.
      #       If port is not specified, default port is used.
      #       IPv6 addresses must be enclosed in square brackets if port for that host is specified.
      #       If port is not specified, square brackets for IPv6 addresses are optional.
      #       If this parameter is not specified, active checks are disabled.
      #       Example: ServerActive=127.0.0.1:20051,zabbix.domain,[::1]:30051,::1,[12fc::1]
      #
      # Mandatory: no
      # Default:
      # ServerActive=
      
      ServerActive=zabbix_server_ip_address
      
      ### Option: Hostname
      #       Unique, case sensitive hostname.
      #       Required for active checks and must match hostname as configured on the server.
      #       Value is acquired from HostnameItem if undefined.
      #
      # Mandatory: no
      # Default:
      # Hostname=
      
      Hostname=Second Ubuntu Server
      ...
      

      Затем найдите раздел, который настраивает надежное подключение к серверу Zabbix и активирует поддержку предварительно предоставленный ключ Найдите раздел TLSConnect, который выглядит следующим образом:

      /etc/zabbix/zabbix_agentd.conf

      ...
      ### Option: TLSConnect
      #       How the agent should connect to server or proxy. Used for active checks.
      #       Only one value can be specified:
      #               unencrypted - connect without encryption
      #               psk         - connect using TLS and a pre-shared key
      #               cert        - connect using TLS and a certificate
      #
      # Mandatory: yes, if TLS certificate or PSK parameters are defined (even for 'unencrypted' connection)
      # Default:
      # TLSConnect=unencrypted
      ...
      

      Затем добавьте эту строку для конфигурации поддержки предварительно предоставленного ключа:

      /etc/zabbix/zabbix_agentd.conf

      ...
      TLSConnect=psk
      ...
      

      Затем найдите раздел TLSAccept, который выглядит следующим образом:

      /etc/zabbix/zabbix_agentd.conf

      ...
      ### Option: TLSAccept
      #       What incoming connections to accept.
      #       Multiple values can be specified, separated by comma:
      #               unencrypted - accept connections without encryption
      #               psk         - accept connections secured with TLS and a pre-shared key
      #               cert        - accept connections secured with TLS and a certificate
      #
      # Mandatory: yes, if TLS certificate or PSK parameters are defined (even for 'unencrypted' connection)
      # Default:
      # TLSAccept=unencrypted
      ...
      

      Настройте входящие соединения для поддержки предварительно предоставленных ключей, добавив эту строку:

      /etc/zabbix/zabbix_agentd.conf

      ...
      TLSAccept=psk
      ...
      

      Затем найдите раздел TLSPSKIdentity, который выглядит следующим образом:

      /etc/zabbix/zabbix_agentd.conf

      ...
      ### Option: TLSPSKIdentity
      #       Unique, case sensitive string used to identify the pre-shared key.
      #
      # Mandatory: no
      # Default:
      # TLSPSKIdentity=
      ...
      

      Выберите уникальное имя для идентификации вашего предварительно предоставленного ключа, добавив эту строку:

      /etc/zabbix/zabbix_agentd.conf

      ...
      TLSPSKIdentity=PSK 001
      ...
      

      Вы будете использовать его в качестве идентификатора PSK при добавлении хоста через веб-интерфейс Zabbix.

      Затем установите опцию, которая указывает на ранее созданный предварительно предоставленный ключ. Найдите опцию TLSPSKfile:

      /etc/zabbix/zabbix_agentd.conf

      ...
      ### Option: TLSPSKFile
      #       Full pathname of a file containing the pre-shared key.
      #
      # Mandatory: no
      # Default:
      # TLSPSKFile=
      ...
      

      Добавьте эту строку, чтобы направить агент Zabbix в созданный вами файл PSK:

      /etc/zabbix/zabbix_agentd.conf

      ...
      TLSPSKFile=/etc/zabbix/zabbix_agentd.psk
      ...
      

      Сохраните и закройте файл. Теперь вы можете перезапустить агент Zabbix и установить его запуск в момент загрузки:

      • sudo systemctl restart zabbix-agent
      • sudo systemctl enable zabbix-agent

      В дополнение к этому проверьте правильность работы агента Zabbix:

      • sudo systemctl status zabbix-agent

      Вы увидите следующий статус, указывающий на то, что агент работает:

      Output

      ● zabbix-agent.service - Zabbix Agent Loaded: loaded (/lib/systemd/system/zabbix-agent.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-12 08:19:54 UTC; 25s ago ...

      Агент будет прослушивать порт 10050 для подключений с сервера. Настройте UFW для разрешения подключений к этому порту:

      Дополнительную информацию о UFW можно получить в статье Настройка брандмауэра с UFW в Ubuntu 20.04.

      Теперь ваш агент готов направлять данные на сервер Zabbix. Но для его использования необходимо подключаться к нему с веб-консоли сервера. В следующем шаге вы завершите настройку.

      Шаг 7 — Добавление нового хоста на сервер Zabbix

      Установка агента на сервер, который вы хотите отслеживать, составляет только половину процесса. Каждый хост, который вы хотите отслеживать, должен быть зарегистрирован на сервере Zabbix, что вы можете сделать через веб-интерфейс.

      Войдите в веб-интерфейс сервера Zabbix, перейдя по адресу http://zabbix_server_name​​​ или https://zabbix_server_name:

      Экран входа в Zabbix

      После того, как вы выполните вход, нажмите Configuration (Настройка), затем Hosts (Хосты) на левой панели управления. Затем нажмите кнопку Create host​​​​​​ (Создать хост) в верхнем правом углу экрана. Откроется страница настройки хоста.

      Создание хоста

      Настройте Имя хоста и IP-адрес, чтобы они отображали имя хоста и IP-адрес вашего второго сервера Ubuntu, а затем добавьте хост в группу. Вы можете выбрать существующую группу, например серверы Linux, или создать собственную группу. Хост может быть в нескольких группах. Для этого введите имя существующей или новой группы в поле Groups (Группы) и выберите желаемое значение из предлагаемого списка.

      Перед тем как добавить группу, нажмите на вкладку Templates​​​.

      Добавление шаблона в хост

      Введите Template OS Linux by Zabbix agent​​​ в поле Search​​​ (Поиск) и затем выберите его из списка, чтобы добавить этот шаблон в хост.

      Затем перейдите на вкладку Encryption (Шифрование). Выберите PSK для Connections to host (Входящие соединения на хост) и Connections from host​​​ (Исходящие соединения от хоста). Затем установите в PSK identity​​​ (Идентификация PSK) настройку PSK 001, которая является значением настройки TLSPSKIdentity агента Zabbix, настроенного ранее. Затем установите значение PSK для ключа, который вы сгенерировали для агента Zabbix. Он хранится в файле /etc/zabbix/zabbix_agentd.psk на компьютере агента.

      Настройка шифрования

      Наконец, нажмите кнопку Add​​​ (Добавить) внизу формы для создания хоста.

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

      Zabbix

      Если у вас есть еще серверы для мониторинга, войдите в каждый хост, установите агент Zabbix, сгенерируйте PSK, настройте агент и добавьте хост в веб-интерфейс, выполнив те же действия, что и при добавлении первого хоста.

      Сервер Zabbix теперь отслеживает ваш второй сервер Ubuntu. Теперь настройте уведомления по электронной почте, чтобы знать о возникновении проблем.

      Шаг 8 — Настройка уведомлений по электронной почте

      Zabbix автоматически поддерживает несколько типов уведомлений: по электронной почте, в OTRS, Slack, Telegram​​​, СМС и т. д. Весь список совместимости можно увидеть на веб-сайте Zabbix.

      В качестве примера в этом обучающем модуле мы настроим уведомления по электронной почте.

      Нажмите Administration (Управление), а затем Media types (Типы связи) на левой панели навигации. Вы увидите список всех типов связи. Для электронной почты предусмотрено две предварительно настроенные опции: обычное текстовое уведомление и уведомления HTML. В этом обучающем модуле будет использоваться простое текстовое уведомление. Нажмите на Email​​​ (электронная почта).

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

      Примечание. Если вы используете двухэтапную аутентификацию для Gmail, необходимо сгенерировать пароль приложения для Zabbix. Пароль приложения вводится только один раз во время установки. Инструкции по генерированию этого пароля можно получить в Справочном центре Google.

      Если вы используете Gmail, введите smtp.gmail.com в поле SMTP server​​​ (Сервер SMTP), 465​​​​​​ в поле SMTP server port​​​ (Порт сервера SMTP), gmail.com в SMTP helo и ваш адрес электронной почты в SMTP email​​​ (Электронная почта SMTP). Затем выберите SSL/TLS для Connection security (Безопасность подключения) и Имя пользователя и пароль для Authentication​​​ (Аутентификация). Введите адрес Gmail в качестве Username (Имя пользователя) и пароль приложения, сгенерированный в учетной записи Google, в качестве Password (Пароль).

      Настройка электронной почты в качестве средства связи

      На вкладке Message templates (Шаблоны сообщений) вы увидите список стандартных сообщений для различных типов уведомлений. Наконец, нажмите кнопку Update​​​ (Обновить) внизу формы для обновления параметров электронной почты.

      Теперь вы можете протестировать отправку уведомлений. Для этого нажмите на подчеркнутую ссылку Test​​ (Тестирование) в соответствующей строке.

      Вы увидите всплывающее окно. Введите свой адрес электронной в поле Send to (Отправить) и нажмите кнопку Test Тестирование. Вы увидите сообщение об успешной отправке и получите тестовое сообщение.

      Тестирование электронной почты

      Закройте всплывающее окно, нажав кнопку Cancel (Отмена).

      Теперь создайте нового пользователя. Нажмите Administration (Управление), а затем Users (Пользователи) на левой панели навигации. Вы увидите список пользователей. Затем нажмите кнопку Create user (Создать пользователя) в верхнем правом углу экрана. Откроется страница настройки пользователя:

      Создание

      Введите новое имя пользователя в поле Alias (Псевдоним) и установите новый пароль. Затем добавьте пользователя в группу администратора. Введите Zabbix administrators в поле Groups (Группы) и выберите его из предложенного списка.

      После добавления группы нажмите на вкладку Media (Средство связи) и нажмите на подчеркнутую ссылку Add (не на кнопку Add (Добавить) под ней). Вы увидите всплывающее окно.

      Добавление электронной почты

      Выберите опцию Email (Электронная почта) из выпадающего списка поля Type (тип). Введите свой адрес электронной почты в поле Send to (Отправить). В остальных опциях можно оставить значения по умолчанию. Нажмите кнопку Add (Добавить) внизу для отправки.

      Теперь перейдите на вкладку Permissions (Разрешения). Выберите Zabbix Super Admin (Суперадминистратор Zabbix) из выпадающего меню поля User type (Тип пользователя).

      Наконец, нажмите кнопку Add​​​ (Добавить) внизу формы для создания пользователя.

      Примечание. Использование пароля по умолчанию небезопасно. Чтобы изменить пароль встроенного пользователя Admin (Администратор), нажмите на псевдоним в списке пользователей. Затем нажмите Change password (Изменить пароль), введите новый пароль и подтвердите изменения, нажав на кнопку Update (Обновить).

      Теперь необходимо включить уведомления. Нажмите на вкладку Configuration (Настройка), а затем Actions (Действия) на левой панели навигации. Вы увидите предварительно настроенное действие, отвечающее за отправку уведомлений всем администраторам Zabbix. Вы можете проверять и менять настройки, нажимая на названия. Для целей данного обучающего модуля используйте параметры по умолчанию. Чтобы активировать действие, нажмите на красную ссылку Disabled​​​ (Отключено) в столбце Status (Статус).

      Теперь вы готовы получать оповещения. В следующем шаге вы сгенерируете одно для тестирования настройки уведомлений.

      Шаг 9 — Создание тестового оповещения

      На этом шаге вы сгенерируете тестовое оповещение, чтобы убедиться, что все подключено. По умолчанию Zabbix отслеживает объем свободного места на диске на вашем сервере. Он автоматически обнаруживает все установки диска и добавляет соответствующие проверки. Это обнаружение выполняется каждый час, поэтому необходимо немного подождать, чтобы сработало уведомление.

      Создайте временный файл, чтобы он был достаточно большим, чтобы сработало оповещение об использовании файловой системы Для этого войдите на второй сервер Ubuntu, если вы еще не подключены:

      • ssh sammy@second_ubuntu_server_ip_address

      Затем определите, сколько есть свободного места на сервере. Чтобы выяснить это, можно использовать команду df​​​:

      Команда df будет сообщать об использовании места на диске в вашей файловой системе, а -h сделает читаемый вывод. Результат будет выглядеть примерно следующим образом:

      Output

      Filesystem Size Used Avail Use% Mounted on /dev/vda1 78G 1.4G 77G 2% /

      В этом случае свободное пространство составляет 77G. Ваше свободное пространство может отличаться.

      Используйте команду fallocate, которая позволяет предварительно распределять или освобождать пространство для файла или создавать файл, который занимает более 80 % имеющегося пространства на диске. Этого будет достаточно, чтобы сработало оповещение:

      • fallocate -l 70G /tmp/temp.img

      Приблизительно через час Zabbix активирует оповещение об объеме свободного пространства на диске и запустит действие, которое вы настроили, чтобы отправить сообщение с уведомлением. Вы можете проверить входящие на наличие сообщения с сервера Zabbix. Сообщение может выглядеть следующим образом:

      Problem started at 09:49:08 on 2020.06.12
      Problem name: /: Disk space is low (used > 80%)
      Host: Second Ubuntu Server
      Severity: Warning
      Operational data: Space used: 71.34 GB of 77.36 GB (92.23 %)
      Original problem ID: 106
      

      Также вы можете перейти на вкладку Monitoring (Мониторинг), а затем на Dashboard​​​ (Панель управления), чтобы увидеть уведомление и детали.

      Главная панель управления

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

      Через одну минуту Zabbix отправит сообщение и оповещение исчезнет с главной панели управления.

      Заключение

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

      Дополнительную информацию о настройке инфраструктуры мониторинга можно найти на нашей тематической странице, посвященной мониторингу.



      Source link

      Установка и настройка Postfix в Ubuntu 20.04


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

      Введение

      Postfix — популярный почтовый агент (MTA) с открытым исходным кодом, который можно использовать для маршрутизации и доставки почты в системе Linux. Согласно оценкам, примерно 25% публичных почтовых серверов в Интернете используют Postfix.

      В этом руководстве мы расскажем, как установить и настроить Postfix на сервере Ubuntu 20.04. Затем мы протестируем способность Postfix правильно выполнять маршрутизацию, выполнив установку s-nail, почтового пользовательского агента (MUA), также называемого клиентом электронной почты.

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

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

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

      • Сервер под управлением Ubuntu 20.04, который будет работать как ваш почтовый сервер Postfix. Этот сервер должен иметь пользователя без прав root с привилегиями sudo, а также брандмауэр, настроенный с помощью UFW. Для выполнения этого требования следуйте указаниям нашего руководства по начальной настройке сервера Ubuntu 20.04.
      • Полное доменное имя, указывающее на ваш сервер Ubuntu 20.04. Помощь по настройке доменного имени в DigitalOcean можно найти в нашей документации по доменам и сетям DNS. Помните, что если вы планируете получать доступ к почте из внешнего источника, вам также потребуется запись MX, указывающая на ваш почтовый сервер.

      Для этого обучающего модуля предполагается, что вы настраиваете хост с доменным именем mail.example.com. При необходимости заменяйте example.com или mail.example.com собственным полным доменным именем.

      Шаг 1 — Установка Postfix

      Postfix включен в репозиторий Ubuntu по умолчанию, так что вы можете установить его с помощью APT.

      Для начала обновите локальный кэш пакетов apt:

      Затем установите пакет postfix с помощью следующей команды. Обратите внимание, что мы передаем переменную среды DEBIAN_PRIORITY=low в эту команду установки. В связи с этим, процедура установки предложит вам настроить некоторые дополнительные опции:

      • sudo DEBIAN_PRIORITY=low apt install postfix

      Процедура установки откроет серию интерактивных диалогов. Для целей данного обучающего модуля введите в диалогах следующие данные:

      • General type of mail configuration?: Для данного параметра выберем пункт Internet Site, соответствующий потребностям нашей инфраструктуры.
      • System mail name: это базовый домен, используемый для построения корректного адреса электронной почты, когда имеется только часть адреса с именем учетной записи. Допустим, имя хоста вашего сервера mail.example.com. Возможно вы захотите задать для системной почты имя example.com. В этом случае для имени пользователя user1 Postfix будет использовать адрес user1@example.com.
      • Root and postmaster mail recipient: это учетная запись Linux, на которую будет перенаправляться почта, адресованная root@ и postmaster@. Используйте для этой цели свою основную учетную запись. В данном примере это имя пользователя sammy.
      • Other destinations to accept mail for: определение получателей почты, которых будет принимать этот экземпляр Postfix. Если вам потребуется добавить любые другие домены, для которых этот сервер будет получать почту, добавьте их здесь. В противном случае значений по умолчанию будет достаточно.
      • Force synchronous updates on mail queue?: поскольку вы вероятно используете журнальную файловую систему, выберите No.
      • Local networks: это перечень локальных сетей, для которых ваш почтовый сервер настроен как реле пересылки сообщений. Значение по умолчанию подойдет для большинства случаев. Если вы пожелаете изменить его, постарайтесь максимально ограничить диапазон сетей.
      • Mailbox size limit: используется для ограничения размера сообщений. Значение «0» отключает любые ограничения размера.
      • Local address extension character: символ, используемый для отделения обычной части адреса от расширения (используется для создания динамических псевдонимов). Для этого обучающего модуля подойдет значение по умолчанию «+».
      • Internet protocols to use: укажите, нужно ли ограничивать версии протокола IP, поддерживаемые Postfix. Для целей данного обучающего модуля выберите вариант «all».

      Приведем настройки, использованные в этом руководстве:

      • General type of mail configuration?: Internet Site
      • System mail name: example.com (не mail.example.com)
      • Root and postmaster mail recipient: имя пользователя основной учетной записи Linux (в наших примерах sammy)
      • Other destinations to accept mail for: $myhostname, example.com, mail.example.com, localhost.example.com, localhost
      • Force synchronous updates on mail queue?: No
      • Local networks: 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
      • Mailbox size limit: 0
      • Local address extension character: +
      • Internet protocols to use: all

      Примечание. Если впоследствии вам потребуется изменить эти настройки, введите команду:

      • sudo dpkg-reconfigure postfix

      Для параметров будут указаны заданные ранее значения.

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

      Шаг 2 — Изменение конфигурации Postfix

      Теперь вы можете изменить дополнительные настройки, которые не предлагались в диалогах процедуры установки. Многие параметры конфигурации Postfix заданы в файле /etc/postfix/main.cf. Вместо того, чтобы редактировать этот файл напрямую, вы можете использовать команду Postfix postconf для запроса или установки параметров конфигурации.

      Для начала задайте расположение почтового ящика пользователя Ubuntu без прав root. В этом обучающем модуле мы используем формат Maildir, в котором соообщения выделяются в отдельные файлы, перемещаемые между каталогами в зависимости от действий пользователя. Также существует возможность хранить все сообщения в одном файле в формате mbox, но мы не рассматриваем ее в этом обучающем модуле.

      Задайте для переменной home_mailbox значение Maildir/. Впоследствии вы создадите структуру каталогов с этим именем в своем домашнем каталоге пользователя. Настройте home_mailbox с помощью следующей команды:

      • sudo postconf -e 'home_mailbox= Maildir/'

      Задайте расположение таблицы virtual_alias_maps, где произвольные учетные записи электронной почты сопоставляются с системными учетными записями Linux. Запустите следующую команду, сопоставляющую расположение таблицы с файлом базы данных хэша под именем /etc/postfix/virtual:

      • sudo postconf -e 'virtual_alias_maps= hash:/etc/postfix/virtual'

      Мы определили расположение файла виртуальной карты в файле main.cf и теперь можем создать сам файл и начать сопоставление учетных записей электронной почты с учетными записями пользователей в системе Linux. Создайте файл в nano или другом предпочитаемом текстовом редакторе:

      • sudo nano /etc/postfix/virtual

      Укажите все адреса, для которых вы хотите получать электронную почту, а затем укажите через пробел имя пользователя Linux, которому должна доставляться эта почта.

      Например, если вы хотите принимать электронную почту на адреса contact@example.com и admin@example.com и доставлять ее пользователю Linux с именем sammy, файл можно настроить следующим образом:

      /etc/postfix/virtual

      contact@example.com sammy
      admin@example.com sammy
      

      После сопоставления всех почтовых адресов с соответствующими учетными записями сервера вы можете сохранить и закрыть файл. Если вы использовали nano, нажмите CTRL + X, Y, а затем ENTER.

      Примените сопоставление:

      • sudo postmap /etc/postfix/virtual

      Перезапустите процесс Postfix, чтобы все изменения были применены:

      • sudo systemctl restart postfix

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

      Вы можете разрешить подключение к службе с помощью следующей команды:

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

      Шаг 3 — Установка почтового клиента и инициализация структуры Maildir

      Этот шаг поможет вам установить пакет s-nail для взаимодействия с доставляемой почтой. Это функциональный вариант почтового клиента BSD xmail, правильно работающий с форматом Maildir.

      Перед установкой клиента желательно проверить настройку переменной среды MAIL. Клиент s-nail использует эту переменную для определения мест поиска почты для вашего пользователя.

      Если требуется гарантированно задать переменную MAIL вне зависимости от способа доступа к учетной записи (через ssh, su, su -, sudo и т. п.), необходимо задать переменную в файле /etc/bash.bashrc и добавить ее в файл /etc/profile.d, чтобы она использовалась всеми пользователями по умолчанию.

      Чтобы добавить переменную в эти файлы, введите:

      • echo 'export MAIL=~/Maildir' | sudo tee -a /etc/bash.bashrc | sudo tee -a /etc/profile.d/mail.sh

      Чтобы прочитать переменную для текущего сеанса, в качестве источника можно использовать файл /etc/profile.d/mail.sh:

      • source /etc/profile.d/mail.sh

      Выполнив этот шаг, установите клиент электронной почты s-nail с помощью APT:

      Перед запуском клиента необходимо изменить несколько настроек. Откройте файл /etc/s-nail.rc в своем редакторе:

      Добавьте в конец файла следующие опции:

      /etc/s-nail.rc

      . . .
      set emptystart
      set folder=Maildir
      set record=+sent
      

      Вот что делают эти строки:

      • set emptystart: позволяет клиенту открываться даже при пустом почтовом ящике
      • set folder=Maildir: задает для каталога Maildir внутреннюю переменную folder
      • set record=+sent создает файл sent в формате mbox для хранения отправленной почты в каталоге, заданном в переменной folder, в данном случае Maildir

      Сохраните файл и закройте его после завершения. Теперь вы готовы инициализировать структуру Maildir в вашей системе.

      Чтобы быстро создать структуру Maildir в домашнем каталоге, отправьте себе электронное письмо с помощью команды s-nail. Поскольку файл sent будет доступен только после создания Maildir, для этого первого письма нужно отключить запись в этот файл. Используйте для этого опцию -Snorecord.

      Для отправки письма добавьте строку в команду s-nail. Измените команду, чтобы сделать получателем вашего пользователя Linux:

      • echo 'init' | s-nail -s 'init' -Snorecord sammy

      Примечание. Вы можете получить следующий ответ:

      Output

      Can't canonicalize "/home/sammy/Maildir"

      Это нормально, и такой ответ может появиться только при отправке первого сообщения.

      Для проверки создания каталога выполните поиск каталога ~/Maildir:

      Вы увидите, что структура каталогов создана, и что новый файл сообщений находится в каталоге ~/Maildir/new:

      Output

      /home/sammy/Maildir/: cur new tmp /home/sammy/Maildir/cur: /home/sammy/Maildir/new: 1463177269.Vfd01I40e4dM691221.mail.example.com /home/sammy/Maildir/tmp:

      Структура каталогов создана, и теперь мы готовы протестировать клиент s-nail. Для этого мы просмотрим отправленное вами сообщение init и отправим сообщение на сторонний адрес электронной почты.

      Шаг 5 — Тестирование клиента

      Чтобы открыть клиент, запустите команду s-nail:

      В консоли вы увидите рудиментарную папку входящих с ожидающим сообщением init:

      Output

      s-nail version v14.9.15. Type `?' for help "/home/sammy/Maildir": 1 message 1 new >N 1 sammy@example.com 2020-05-19 15:40 14/392 init

      Нажмите ENTER, чтобы вывести сообщение:

      Output

      [-- Message 1 -- 14 lines, 369 bytes --]: From sammy@example.com Tue May 19 15:40:48 2020 Date: Tue, 19 May 2020 15:40:48 +0000 To: sammy@example.com Subject: init Message-Id: <20160513220749.A278F228D9@mail.example.com> From: sammy@example.com init

      Вы можете вернуться к списку сообщений, введя h и нажав ENTER:

      Output

      >R 1 sammy@example.com 2020-05-19 15:40 14/392 init

      Теперь сообщение имеет состояние R, означающее, что оно прочитано.

      Поскольку это сообщение не очень полезно, мы можем удалить его, введя d и нажав ENTER:

      Чтобы вернуться к терминалу, введите q и нажмите ENTER:

      В качестве последнего испытания проверим, может ли s-nail правильно отправлять электронные сообщения. Для этого передадим содержимое текстового файла text в процесс s-nail, как мы делали это с сообщением init на предыдущем шаге.

      Для начала напишем тестовое сообщение в текстовом редакторе:

      Введите текст, которы вы хотите отправить:

      ~/test_message

      Hello,
      
      This is a test.  Please confirm receipt!
      

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

      Затем используйте команду cat для передачи сообщения в процесс s-nail. Для этого можно использовать следующий пример, где используются следующие опции:

      • -s: задает строку темы электронного сообщения
      • -r: изменение поля «From» письма. По умолчанию в этом поле указан текущий пользователь Linux. Опция -r позволяет заменить его корректным адресом, в том числе определенным в файле /etc/postfix/virtual. Например, в следующей команде используется адрес contact@example.com

      Также следует заменить user@email.com на корректный адрес электронной почты, к которому у вас имеется доступ:

      • cat ~/test_message | s-nail -s 'Test email subject line' -r contact@example.com user@email.com

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

      Примечание. Если сообщение отсутствует в почтовом ящике, оно может быть доставлено в папку Spam.

      Вы можете просмотреть отправленные сообщения в клиенте s-nail. Запустите интерактивный клиент еще раз:

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

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

      Output

      +[/home/sammy/Maildir/]sent: 1 message 1 new ▸N 1 contact@example.com 2020-05-19 15:47 12/297 Test email subject line

      Вы можете управлять отправленными письмами с помощью тех же команд, которые используются для входящих писем.

      Заключение

      Теперь почтовая система Postfix настроена на вашем сервере Ubuntu 20.04. Управление серверами электронной почты может оказаться непростой задачей для начинающих системных администраторов, но с этой конфигурацией у вас должно быть достаточно функций MTA для работы с электронной почтой, чтобы начать эту работу.



      Source link

      Установка и настройка Laravel с помощью Docker Compose в Ubuntu 20.04


      Введение

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

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

      • Служба app с PHP7.4-FPM;
      • Служба db с MySQL 5.7;
      • Служба nginx, использующая службу app для синтаксического анализа кода PHP перед предоставлением приложения Laravel конечному пользователю.

      Чтобы ускорить разработку и упростить отладку приложения, мы обеспечим синхронизацию файлов приложения с использованием общих томов. Также мы узнаем, как использовать команды docker-compose exec для запуска Composer и Artisan в контейнере app.

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

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

      Для начала работы мы получим демонстрационное приложение Laravel из его репозитория на Github. Нас интересует раздел tutorial-01, содержащий базовое приложение Laravel, которое мы создали в первом обучающем руководстве этой серии.

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

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

      Нам потребуется команда unzip для распаковки кода приложения. Если вы еще не установили этот пакет, сделайте это с помощью следующей команды:

      • sudo apt update
      • sudo apt install unzip

      Теперь распакуйте содержимое приложения и переименуйте распакованную директорию для удобства доступа:

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

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

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

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

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

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

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

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

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

      Текущий файл .env из демонстрационного приложения travellist содержит настройки использования локальной базы данных MySQL с адресом хоста базы данных 127.0.0.1. Нам нужно обновить переменную DB_HOST, чтобы она указывала на службу базы данных, которую мы создадим в нашей среде Docker. В этом обучающем руководстве мы присвоим службе базы данных имя db. Замените указанное значение DB_HOST именем службы базы данных:

      .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
      ...
      

      При желании вы также можете изменить название базы данных, имя пользователя и пароль. Эти переменные будут использоваться на последующем шаге, когда мы настроим файл docker-compose.yml для настройки наших служб.

      Сохраните файл после завершения редактирования. Если вы использовали nano, нажмите Ctrl+x, а затем Y и Enter для подтверждения.

      Шаг 3 — Настройка файла Dockerfile для приложения

      Хотя наши службы MySQL и Nginx будут основаны на образах по умолчанию, полученных из Docker Hub, нам все равно потребуется создать персонализированный образ контейнера приложения. Для этого мы создадим новый файл Dockerfile.

      Наш образ travellist будет основан на php:7.4-fpm, официальном образе PHP из Docker Hub. Поверх базовой среды PHP-FPM мы установим несколько дополнительных модулей PHP и инструмент Composer для управления зависимостями.

      Также мы создадим нового пользователя системы, что необходимо для выполнения команд artisan и composer при разработке приложения. Параметр uid обеспечивает соответствие uid пользователя внутри контейнера и системного пользователя на хосте, где работает Docker. Любые файлы, созданные этими командами, воспроизводятся на хосте с соответствующими разрешениями. Также это означает, что вы можете использовать предпочитаемый редактор кода на хосте для разработки приложения, работающего внутри контейнеров.

      Создайте новый файл Dockerfile:

      Скопируйте следующие строки в файл 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
      
      

      Не забудьте сохранить файл после завершения работы.

      Вначале наш файл Dockerfile определяет базовый образ, который мы используем: php:7.4-fpm.

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

      При этом создается новый пользователь системы и выполняется настройка его параметров с помощью аргументов user и uid в начале файла Dockerfile. Эти значения вставляются Docker Compose во время сборки.

      В заключение мы зададим рабочую директорию по умолчанию /var/www и переключимся на созданного пользователя. Это гарантирует, что вы будете подключаться как обычный пользователь и находиться в правильной директории при выполнении команд composer и artisan в контейнере приложения.

      Шаг 4 — Настройка конфигурации Nginx и файлов дампа базы данных

      При создании сред разработки с помощью Docker Compose часто бывает необходимо использовать общие конфигурации или файлы инициализации со служебными контейнерами для настройки этих служб или их включения в процессе загрузки. Такая практика упрощает изменение файлов конфигурации для отладки среды во время разработки приложения.

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

      Для настройки Nginx мы будем использовать файл travellist.conf, настраивающий обслуживание приложения. Создайте папку docker-compose/nginx с помощью следующей команды:

      • mkdir -p docker-compose/nginx

      Откройте в этой директории новый файл с именем travellist.conf:

      • nano docker-compose/nginx/travellist.conf

      Скопируйте следующую конфигурацию Nginx в этот файл:

      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;
          }
      }
      

      Этот файл настраивает Nginx для прослушивания порта 80 и использования index.php в качестве страницы индекса по умолчанию. Это задаст корневую директорию документа /var/www/public, а затем Nginx будет настроен для использования службы app на порту 9000 для обработки файлов *.php.

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

      Чтобы настроить базу данных MySQL, мы откроем для общего доступа дамп базы данных, который будет импортирован при инициализации контейнера. Эта возможность обеспечивается образом MySQL 5.7, который мы будем использовать в этом контейнере.

      Создайте новую папку для файлов инициализации MySQL в папке docker-compose:

      • mkdir docker-compose/mysql

      Откройте новый файл .sql:

      • nano docker-compose/mysql/init_db.sql

      Следующий дамп MySQL основан на базе данных, которую мы настроили в обучающем руководстве по Laravel на LEMP. Она создаст новую таблицу с именем places. Затем таблица будет заполнена местами на основе образца.

      Добавьте в файл следующий код:

      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);
      

      Таблица places содержит три поля: id, name и visited. Поле visited — это флаг, используемый для отметки мест со статусом to go. Вы можете свободно изменять или добавлять места в образец. Сохраните и закройте файл после завершения.

      Мы завершили настройку файла Dockerfile приложения и файлов конфигурации служб. Далее мы выполним настройку Docker Compose для использования этих файлов при создании наших служб.

      Шаг 5 — Создание мультиконтейнерной среды с Docker Compose

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

      Для настройки наших определений служб мы создадим новый файл с именем docker-compose.yml. Обычно этот файл располагается в корневой папке приложения и определяет контейнеризованную среду, в том числе базовые образы, используемые для построения контейнеров, и взаимодействие между службами.

      Мы определим в файле docker-compose.yml три разные службы: app, db и nginx.

      Служба app построит образ с именем travellist на базе ранее созданного файла Dockerfile. Определяемый этой службой контейнер запустит сервер php-fpm для синтаксической проверки кода PHP и возврата результатов в службу nginx, которая будет работать в отдельном контейнере. Служба mysql определяет контейнер, где запущен сервер MySQL 5.7. Наши службы будут использовать общую соединительную сеть с именем travellist.

      Файлы приложения будут синхронизироваться в службах app и nginx посредством монтирования привязок. Монтирование привязок — это полезный инструмент в средах разработки, позволяющий организовать эффективную двустороннюю синхронизацию между хостом и контейнерами.

      Создайте новый файл docker-compose.yml в корневой папке приложения:

      Обычно файл docker-compose.yml начинается с определения версии, после которого идет узел services, где определяются все службы. Общие сети обычно определяются в конце этого файла.

      Для начала скопируйте этот шаблонный код в файл docker-compose.yml:

      docker-compose.yml

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

      Теперь мы отредактируем узел services и добавим в него службы app, db и nginx.

      Служба app

      Служба app настраивает контейнер с именем travellist-app. Она строит новый образ Docker на базе файла Dockerfile в той же директории, что и файл docker-compose.yml. Новый образ сохраняется на локальном компьютере с именем travellist.

      Хотя корневая директория документов выдается приложением в контейнере nginx, нам нужно, чтобы файлы приложения находились внутри контейнера app, поскольку мы хотим выполнять задачи командной строки с помощью инструмента Laravel Artisan.

      Скопируйте следующее определение службы в узел services в файле 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
      

      Эти параметры имеют следующее назначение:

      • build: данная конфигурация предписывает Docker Compose построить локальный образ службы app с использованием заданного пути (контекста) и указаний из файла Dockerfile. Аргументы user и uid вставляются в файл Dockerfile для настройки команд создания пользователя во время сборки.
      • image: имя, которое будет использоваться для создаваемого образа.
      • container_name: задает имя контейнера для этой службы.
      • restart: всегда выполнять перезапуск, если служба не остановлена.
      • working_dir: задает для этой службы директорию по умолчанию /var/www.
      • volumes: создает общий том, который будет синхронизировать содержимое текущей директории с директорией /var/www внутри контейнера. Следует отметить, что это не корневая директория документов, поскольку она находится в контейнере nginx.
      • networks: настраивает службу для использования сети с именем travellist.

      Служба db

      Служба db использует готовый образ MySQL 5.7 из Docker Hub. Поскольку Docker Compose автоматически загружает файлы переменных .env, находящиеся в той же директории, что и файл docker-compose.yml, мы можем получить параметры базы данных из файла Laravel .env, созданного на предыдущем шаге.

      Добавьте следующее определение служб в узел services сразу же после определения службы 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
      

      Эти параметры имеют следующее назначение:

      • image: определяет образ Docker, который следует использовать для этого контейнера. В данном случае мы используем образ MySQL 5.7 из Docker Hub.
      • container_name: задает имя контейнера для этой службы: travellist-db.
      • restart: всегда перезапускать службу, если она явно не остановлена.
      • environment: определяет переменные среды в новом контейнере. Мы используем полученные из файла Laravel .env значения для настройки нашей службы MySQL, которая автоматически создаст новую базу данных и пользователя на базе заданных переменных среды.
      • volumes: создает том для общего доступа к дампу базы данных .sql, который будет использоваться для инициализации базы данных приложения. Образ MySQL будет автоматически импортировать файлы .sql, расположенные в директории /docker-entrypoint-initdb.d внутри контейнера.
      • networks: предписывает службе использовать сеть с именем travellist.

      Служба nginx

      Служба nginx использует готовый образ Nginx на базе облегченного дистрибутива Linux под названием Alpine. Она создает контейнер с именем travellist-nginx, и он использует определение ports для создания переадресации с порта 8000 системы хоста на порт 80 внутри контейнера.

      Добавьте следующее определение службы в узел services сразу после службы 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
      

      Эти параметры имеют следующее назначение:

      • image: определяет образ Docker, который следует использовать для этого контейнера. В данном случае мы используем образ Alpine Nginx 1.17.
      • container_name: задает имя контейнера для этой службы: travellist-nginx.
      • restart: всегда перезапускать эту службу, если она явно не остановлена.
      • ports: задает переадресацию портов, разрешающую внешний доступ через порт 8000 к веб-серверу на порту 80 внутри контейнера.
      • volumes: создает два общих тома. Первый из них синхронизирует содержимое текущей директории с директорией /var/www внутри контейнера. При внесении локальных изменений в файлы приложения эти изменения быстро отражаются в приложении, обслуживаемом Nginx внутри контейнера. Второй том обеспечивает копирование нашего файла конфигурации Nginx docker-compose/nginx/travellist.conf в папку конфигурации Nginx контейнера.
      • networks: предписывает этой службе использовать сеть с именем travellist.

      Готовый файл docker-compose.yml

      Так выглядит готовый файл docker-compose.yml:

      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
      

      Обязательно сохраните файл после завершения.

      Шаг 6 — Запуск приложения с помощью Docker Compose

      Теперь мы используем команды docker-compose для сборки образа приложения и запуска заданных нами служб.

      Выполните сборку образа app с помощью следующей команды:

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

      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

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

      Output

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

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

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

      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 /docker-entrypoint.sh ngin ... Up 0.0.0.0:8000->80/tcp

      Теперь ваша среда работает, но для завершения настройки приложения нам нужно выполнить еще несколько команд. Вы можете использовать команду docker-compose exec для выполнения команд в контейнерах служб, например ls -l для отображения подробной информации о файлах в директории приложения:

      • docker-compose exec app ls -l

      Output

      total 260 -rw-rw-r-- 1 sammy sammy 737 Jun 9 11:19 Dockerfile -rw-rw-r-- 1 sammy sammy 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy sammy 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy sammy 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy sammy 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy sammy 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy sammy 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy sammy 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy sammy 4096 Jun 9 11:19 docker-compose -rw-rw-r-- 1 sammy sammy 965 Jun 9 11:27 docker-compose.yml -rw-rw-r-- 1 sammy sammy 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy sammy 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy sammy 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy sammy 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy sammy 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy sammy 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy sammy 4096 Jan 7 08:05 tests drwxrwxr-x 41 sammy sammy 4096 Jun 9 11:32 vendor -rw-rw-r-- 1 sammy sammy 538 Jan 7 08:05 webpack.mix.js

      Теперь мы выполним команду composer install для установки зависимостей приложения:

      • 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%) - 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.

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

      • docker-compose exec app php artisan key:generate

      Output

      Application key set successfully.

      Откройте браузер и введите в адресную строку доменное имя вашего сервера или IP-адрес с портом 8000:

      http://server_domain_or_IP:8000
      

      Примечание. Если вы запускаете эту демонстрацию на локальном компьютере, используйте http://localhost:8000 для доступа к приложению через браузер.

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

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

      Вы можете использовать команду logs для проверки журналов, сгенерированных вашими службами:

      • docker-compose logs nginx
      Attaching to travellist-nginx
      …
      travellist-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
      travellist-nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
      travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:34 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
      travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:35 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
      

      Если вы хотите приостановить среду Docker Compose, сохраняя состояние всех служб, используйте команду:

      Output

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

      Вы можете возобновить работу служб с помощью команды:

      Output

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

      Чтобы закрыть среду Docker Compose и удалить все ее контейнеры, сети и тома, используйте команду:

      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

      Обзор всех команд Docker Compose можно найти в справочном материале по командной строке Docker Compose.

      Заключение

      В этом обучающем руководстве мы настроили среду Docker с тремя контейнерами, используя Docker Compose для определения инфраструктуры в файле YAML.

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



      Source link