Развертывание приложения PHP с помощью Docker-compose

Приложения PHP обычно состоят из веб-сервера, системы реляционных баз данных и самого интерпретатора языка. В этом уроке мы будем использовать полный стек приложений PHP с помощью Docker. Это подробное руководство, в котором мы собираемся создавать и организовывать контейнеры для Nginx (веб-сервер), MySQL (система баз данных) и PHP.

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

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

Настройка нашей рабочей среды

Реальное основанное на докере приложение обычно состоит из нескольких контейнеров. Управление ими вручную может легко стать довольно грязным и громоздким. Вот где в игру вступает docker-compose. Это поможет вам управлять несколькими контейнерами через простой yamlфайл конфигурации.

Установите docker-compose.

curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Создайте папку для хранения всех необходимых файлов этого примера, а затем cdв нее. Отныне это наш рабочий каталог, и каждая команда будет выполняться внутри этой папки, и каждый путь будет ссылаться относительно него. На эту папку можно ссылаться позже как WORKING_DIR.

mkdir ~/docker
cd ~/docker

Теперь создайте еще три папки.

mkdir php nginx app

В phpпапке, где мы будем создавать наш собственный образ PHP, в nginxпапке будут храниться необходимые файлы для нашего пользовательского образа nginx, а в appпапке - исходный код и конфигурация нашего примера приложения.

Конфигурирование контейнера PHP

В этом примере мы будем использовать php-fpmдля подключения к веб-серверу Nginx. Мы будем использовать официальный базовый образ PHP. Однако нам также необходимо установить и включить некоторые расширения, чтобы мы могли получить доступ к базе данных. Внутри phpпапки создайте файл с именем Dockerfileи поместите в него следующее содержимое.

FROM php:7.1-fpm-alpine3.4
RUN apk update --no-cache \
    && apk add --no-cache $PHPIZE_DEPS \
    && apk add --no-cache mysql-dev \
    && docker-php-ext-install pdo pdo_mysql

Обратите внимание, что мы используем альпийскую версию официального изображения PHP. Alpine - очень крошечный дистрибутив, ориентированный на контейнеры, предоставляющий гораздо меньшие размеры Также обратите внимание на использование этой команды docker-php-ext-install, официальный образ PHP предоставляет эту команду, чтобы упростить процесс установки и настройки расширений PHP.

Теперь давайте создадим этот образ Docker, выполнив следующее (внутри нашего WORKING_DIR):

docker build -t vultr-php php/

docker-compose.ymlфайл

Как уже упоминалось, docker-composeпозволяет управлять несколькими контейнерами через простой файл конфигурации. Этот файл конфигурации обычно называется docker-compose.yml. Создайте этот файл внутри appпапки.

touch app/docker-compose.yml

Теперь поместите следующее содержимое в этот файл.

version: '2'
services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app

Мы объясним этот синтаксис. Сначала обратите внимание на первую строку.

version: '2'

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

services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app

Обратите внимание, что у каждого сервиса есть определенный ключ внутри servicesблока. Указанное здесь имя будет использоваться для ссылки на этот конкретный контейнер позже. Также обратите внимание, что внутри phpконфигурации мы определяем изображение, используемое для запуска контейнера (это изображение, которое мы создали ранее). Мы также определяем отображение объема.

volumes:
  - ./:/app

Это говорит docker-composeо необходимости сопоставления текущего каталога ( ./) с /appкаталогом внутри контейнера. Последняя строка устанавливает /appпапку внутри контейнера как рабочий каталог, что означает, что это папка, из которой по умолчанию выполняются все будущие команды внутри контейнера.

Теперь мы можем организовать наши контейнеры.

cd ~/docker/app
docker-compose up -d

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

docker ps

Как выполнять команды внутри контейнеров

Находясь внутри appпапки, мы можем выполнить любую команду внутри определенного сервисного контейнера с помощью этой docker-composeкоманды.

docker-compose exec [service] [command]

[service]Заполнитель относится к служебному ключу. В нашем случае это было php. Давайте запустим команду внутри контейнера, чтобы проверить нашу версию PHP.

docker-compose exec php php -v

Вы увидите следующий вывод.

PHP 7.1.14 (cli) (built: Feb  7 2018 00:40:45) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

Конфигурирование контейнера Nginx

Как и в случае с контейнером PHP, нам нужно создать собственное изображение для веб-сервера. Но в этом случае нам просто нужно предоставить конфигурацию для нашего virtual host. Убедитесь, что вы внутри нашей WORKING_DIRи создайте Dockerfileвнутри nginxпапки:

cd ~/docker
touch nginx/Dockerfile

Теперь поместите следующее содержимое в это Dockerfile:

FROM nginx:1.13.8-alpine
COPY ./default.conf /etc/nginx/conf.d/default.conf

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

touch nginx/default.conf

Теперь заполните это этим содержанием.

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /app;
    index index.php;

    #server_name server_domain_or_IP;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Обратите внимание, что в fastcgi_pass php:9000строке мы ссылаемся на контейнер PHP по его имени внутри serviceблока docker-compose.ymlфайла конфигурации. Внутренне docker-composeсоздает сеть и назначает имя службы в качестве имени хоста для каждой из определенных служб. Теперь мы можем построить образ Nginx.

docker build -t vultr-nginx nginx/

обновление docker-compose.yml

Теперь обновите app/docker-compose.ymlфайл.

version: '2'
services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app
  web:
    image: vultr-nginx
    volumes:
      - ./:/app
    depends_on:
      - php
    ports:
      - 80:80

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

depends_on:
  - php
ports:
  - 80:80

Как только контейнеру Nginx потребуется полная инициализация службы PHP, мы включаем это требование в depends_onопцию. portsКлюч конфигурации карты хост - порт для контейнерного порта, здесь мы преобразуем порт 80в хост к порту 80в контейнере.

Теперь создайте файл с именем index.phpвнутри appпапки и поместите в него следующее.

<?php phpinfo();

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

cd ~/docker/app
docker-compose up -d

Еще раз, дважды проверьте, что сервис работает.

docker ps

Откройте браузер и получите доступ [vultr-instance-ip]. Вы можете узнать свой IP-адрес экземпляра Vultr, выполнив следующее.

hostname -I

Вы увидите страницу информации PHP.

Настройка контейнера MySQL

Официальный образ MySQL позволяет настроить контейнер с помощью простых переменных среды. Это можно сделать с помощью environmentпараметра внутри определения сервисного блока. Обновите ~/docker/app/docker-compose.ymlфайл до следующего.

version: '2'
services:
  php:
    image: vultr-php
    volumes:
      - ./:/app
    working_dir: /app
  web:
    image: vultr-nginx
    volumes:
      - ./:/app
    depends_on:
      - php
    ports:
      - 80:80
  mysql:
    image: mysql:5.7.21
    volumes:
      - ./:/app
      - dbdata:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=world
      - MYSQL_ROOT_PASSWORD=root
    working_dir: /app
volumes:
  dbdata:

Теперь мы определили новый сервис для базы данных. Обратите внимание на линию dbdata:/var/lib/mysql. Это монтирует путь в контейнере /var/lib/mysqlк постоянному тому, управляемому Docker, таким образом, данные базы данных сохраняются после удаления контейнера. Этот том должен быть определен в блоке верхнего уровня, как вы можете видеть в конце файла.

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

curl -L http://downloads.mysql.com/docs/world.sql.gz -o world.sql.gz
gunzip world.sql.gz

Теперь давайте организуем наши контейнеры.

docker-compose up -d

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

Еще раз проверьте, что контейнер MySQL был запущен.

docker ps

Теперь заполните мировую базу данных.

docker-compose exec -T mysql mysql -uroot -proot world < world.sql

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

docker-compose exec mysql mysql -uroot -proot world

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

select * from city limit 10;

Вы увидите список городов. Теперь выйдите из командной строки MySQL.

mysql> exit

Создание нашего приложения

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

<?php

$pdo = new PDO('mysql:host=mysql;dbname=world;charset=utf8', 'root', 'root');

$stmt = $pdo->prepare("
    select city.Name, city.District, country.Name as Country, city.Population
    from city
    left join country on city.CountryCode = country.Code
    order by Population desc
    limit 10
");
$stmt->execute();
$cities = $stmt->fetchAll(PDO::FETCH_ASSOC);

?>

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Vultr Rocks!</title>
</head>
<body>
    <h2>Most Populous Cities In The World</h2>
    <table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Country</th>
            <th>District</th>
            <th>Population</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach($cities as $city): ?>
            <tr>
                <td><?=$city['Name']?></td>
                <td><?=$city['Country']?></td>
                <td><?=$city['District']?></td>
                <td><?=number_format($city['Population'], 0)?></td>
            </tr>
        <?php endforeach ?>
    </tbody>
    </table>
</body>
</html>

Если вы заходите [vultr-instance-ip]в веб-браузер, вы увидите список самых густонаселенных городов мира. Поздравляем, вы развернули полностью работающее PHP-приложение с помощью Docker.

Вывод

В этом уроке я шаг за шагом продемонстрировал, как настроить полностью работающее PHP-приложение. Мы создали собственные изображения для PHP и Nginx и настроили docker-compose для организации наших контейнеров. Несмотря на простоту и простоту, эта установка отражает реальный сценарий.

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

Для более подробного использования docker-compose, вы должны обратиться к официальной документации .

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



Leave a Comment

Изучение 26 методов анализа больших данных: часть 1

Изучение 26 методов анализа больших данных: часть 1

Изучение 26 методов анализа больших данных: часть 1

6 невероятных фактов о Nintendo Switch

6 невероятных фактов о Nintendo Switch

Многие из вас знают Switch, который выйдет в марте 2017 года, и его новые функции. Для тех, кто не знает, мы подготовили список функций, которые делают «Switch» обязательным гаджетом.

Технические обещания, которые все еще не выполнены

Технические обещания, которые все еще не выполнены

Вы ждете, когда технологические гиганты выполнят свои обещания? проверить, что осталось недоставленным.

Функциональные возможности уровней эталонной архитектуры больших данных

Функциональные возможности уровней эталонной архитектуры больших данных

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

Как ИИ может вывести автоматизацию процессов на новый уровень?

Как ИИ может вывести автоматизацию процессов на новый уровень?

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

CAPTCHA: как долго она может оставаться жизнеспособным методом различения между человеком и ИИ?

CAPTCHA: как долго она может оставаться жизнеспособным методом различения между человеком и ИИ?

CAPTCHA стало довольно сложно решать пользователям за последние несколько лет. Сможет ли он оставаться эффективным в обнаружении спама и ботов в ближайшем будущем?

Технологическая сингулярность: далекое будущее человеческой цивилизации?

Технологическая сингулярность: далекое будущее человеческой цивилизации?

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

Телемедицина и удаленное здравоохранение: будущее уже здесь

Телемедицина и удаленное здравоохранение: будущее уже здесь

Что такое телемедицина, дистанционное здравоохранение и их влияние на будущее поколение? Это хорошее место или нет в ситуации пандемии? Прочтите блог, чтобы узнать мнение!

Вы когда-нибудь задумывались, как хакеры зарабатывают деньги?

Вы когда-нибудь задумывались, как хакеры зарабатывают деньги?

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

Обновление дополнения к macOS Catalina 10.15.4 вызывает больше проблем, чем решает

Обновление дополнения к macOS Catalina 10.15.4 вызывает больше проблем, чем решает

Недавно Apple выпустила macOS Catalina 10.15.4, дополнительное обновление для исправления проблем, но похоже, что это обновление вызывает больше проблем, приводящих к поломке компьютеров Mac. Прочтите эту статью, чтобы узнать больше