Налаштування нашого робочого середовища
											
										
																			
											
												Налаштування контейнера PHP
											
										
																			
											
												Налаштування контейнера Nginx
											
										
																			
											
												Налаштування контейнера MySQL
											
										
																			
											
												Створення нашого додатка
											
										
																			
											
												Висновок
											
										
																	
												
Додатки PHP зазвичай складаються з веб-сервера, системи реляційної бази даних і самого інтерпретатора мови. У цьому підручнику ми будемо використовувати повний стек програм PHP за допомогою docker. Це детальний посібник, у якому ми збираємося створювати та організувати контейнери для Nginx (веб-сервер), MySQL (система баз даних) і PHP.
Заради цього підручника ми напишемо просту програму, яка зчитує список міст з бази даних і відображає його на веб-сторінці, таким чином ми продемонструємо базову, але працюючу програму PHP.
Цей посібник передбачає, що у вас уже встановлено Docker-CE і принаймні мінімальні знання докера. З цього приводу ви можете переглянути наступні посібники:
Налаштування нашого робочого середовища
Реальна програма на основі докерів зазвичай складається з кількох контейнерів. Керування ними вручну може легко стати досить брудним і громіздким. Ось тут і вступає в гру 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
Once the Nginx container needs the PHP service to be fully initialized, we force this requirement in the depends_on option.
The ports configuration key maps a host port to a container port, here we map the port 80 in the host to the port 80 in
the container.
Now create a file called index.php inside the app folder and put the following in it.
<?php phpinfo();
Make sure the port 80 is accessible through your firewall and execute the following.
cd ~/docker/app
docker-compose up -d
Once again, double check that the service is up.
docker ps
Open a browser and access [vultr-instance-ip]. You may find out your Vultr instance IP address by running the following.
hostname -I
You will see the PHP info page.
Configuring the MySQL container
Офіційний образ 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-compose, вам слід звернутися до офіційної документації .
Залежно від вимог вашої програми та PHP-фреймворку, який ви використовуєте, ви можете додати більше розширень. Це можна легко зробити, змінивши Dockerfileвикористовуване для створення нашого користувацького образу PHP. Однак деякі розширення потребують додаткових залежностей для встановлення в контейнері. Ви повинні звернутися до списку розширень в 
 офіційній документації PHP, щоб переглянути основні вимоги кожного розширення.