Налаштування нашого робочого середовища
Налаштування контейнера 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, щоб переглянути основні вимоги кожного розширення.