# mkdir web-server
# cd web-server/
Создаем директории для проекта.
Под каждый контейнер своя директория для конфигов, и плюс директория data - для файлов и datadb для файлов базы данных.
# mkdir nginx
# mkdir php-fpm
# mkdir mariadb
# mkdir data
# mkdir datadb
Скачиваем образ nginx и php-fpm
# docker pull nginx
# docker pull bitnami/php-fpm
# docker pull mariadb
В директорию data кладем тестовые файлы index.html (любая страничка) и info.php (с функцией phpinfo();)
Пример файла index.html
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Заголовок</title>
<link rel="stylesheet" href="./styles/style.css">
</head>
<body>
<header>
<h1>Сайт-тест HTTP NGINX-1</h1>
<p>Просто какая-то информация</p>
</header>
<main>
12345 АБВГДЕ, Основной блок информации
</main>
<footer>
<p>footer (подвал), нижняя часть сайта</p>
</footer>
<!--подключение скриптов <script src="app.js"></script> -->
</body>
</html>
Содержимое файла info.php
<?php
phpinfo();
?>
Нам необходимо выстроить конструкцию контейнеров, показанную на рисунке ниже
В директорию nginx кладем типовой файл nginx.conf конфига nginx.
Главное, что нужно указать, это параметры директивы fastcgi_pass в блоке location ~ \.php$:
fastcgi_pass php-fpm:9000;
Директива fastcgi_pass задаёт адрес FastCGI-сервера, которому сервер nginx будет передавать php файлы для обработки. Тут указывается доменное имя и порт. 9000 – это стандартный порт, на котором работает сервер php-fpm. А доменное имя «php-fpm» - это доменное имя сервера php-fpm. В системе doker при старте контейнеров в каждом контейнере автоматически пропишутся все имена запущенных сервисов. И если будет запущен контейнер сервиса «php-fpm», то nginx будет знать его внутренний адрес по имени «php-fpm».
Второй важный момент – это директива
fastcgi_param SCRIPT_FILENAME /app$fastcgi_script_name;
Тут необходимо указать правильный путь до местонахождения файлов php. В контейнере, созданном на основе образа bitnami/php-fpm, это будет папка /app. Поэтому переменная SCRIPT_FILENAME должна начинаться с «/app».
В конфигурационном файле важные изменяемые значения выделены красным.
worker_processes 1;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location / {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location / {
index index.php index.html index.htm;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
}
Директива «error_log /var/log/nginx/error.log;» определяет, куда сервер nginx будет складывать логи ошибок. Контейнер bitnami/php-fpm по умолчанию настроен так, что логи для записи передает для записи web-серверу, в данном случае nginx. И искать логи ошибок php нужно тоже в этом же файле /var/log/nginx/error.log.
Создаем файл docker-compose.yml, который описывает контейнеры nginx и php-fpm.
# touch web-server/docker-compose.yml
version: '3'
services:
nginx:
image: nginx
container_name: nginx1
ports:
- 8080:80
volumes:
- ./data:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx/
depends_on:
- php-fpm
networks:
- internal
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
}
Директива «error_log /var/log/nginx/error.log;» определяет, куда сервер nginx будет складывать логи ошибок. Контейнер bitnami/php-fpm по умолчанию настроен так, что логи для записи передает для записи web-серверу, в данном случае nginx. И искать логи ошибок php нужно тоже в этом же файле /var/log/nginx/error.log.
Создаем файл docker-compose.yml, который описывает контейнеры nginx и php-fpm.
# touch web-server/docker-compose.yml
version: '3'
services:
nginx:
image: nginx
container_name: nginx1
ports:
- 8080:80
volumes:
- ./data:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx/
depends_on:
- php-fpm
networks:
- internal
php-fpm:
image: bitnami/php-fpm
container_name: php1
volumes:
- ./data:/app
networks:
- internal
image: bitnami/php-fpm
container_name: php1
volumes:
- ./data:/app
networks:
- internal
networks:
internal:
driver: bridge
Из директории web-server запускаем контейнеры
# docker compose up --build
Параметр --build означает, что перед запуском контейнеров произойдет их сборка.
Теперь можно обратиться к web-серверу и прочитать тестовые файлы:
http://<IPадрес>:8080/
http://<IPадрес>:8080/
Останавливаем контейнеры, нажав CTRL+C в командной строке, где запускали контейнеры (docker compose up --build)
Теперь запускаем контейнеры вместе с контейнером Mariadb. Для этого в docker-compose.yml добавляем новый сервис, работающий в новом контейнере:
mariadb:
image: mariadb
container_name: mariadb1
environment:
MYSQL_ROOT_PASSWORD: rootpasswd
MYSQL_DATABASE: mydb
MYSQL_USER: user1
MYSQL_PASSWORD: secret1
command: mariadbd --log_error="/var/log/mysql/error.log"
ports:
- 3309:3306
volumes:
- ./datadb:/var/lib/mysql
- ./mariadb/error.log:/var/log/mysql/error.log
networks:
- internal
Директива MYSQL_ROOT_PASSWORD: rootpasswd определить пароль для root пользователя базы данных SQL. Директивы MYSQL_DATABASE: mydb создаст базу данных mydb. Создание базы выполняется командой CREATE DATABASE IF NOT EXIST, поэтому если база mydb уже есть, она не будет создана снова.
Директивы MYSQL_USER: user1 и MYSQL_PASSWORD: secret1 создадут пользователя user1 с паролем secrtet1 и сделают его администратором базы, заданной в MYSQL_DATABASE.
Регистрация ошибок контейнера mariadb осуществляется по умолчанию через системный journal. Для того, что бы запись ошибок велась в отдельный файл, нужно в контейнере
в файле /etc/mysql/mariadb.conf.d/50-server.cnf раскомментировать строку:
log_error = /var/log/mysql/error.log. Но при пересборке контейнера это изменение потеряется. Поэтому пойдем другим путем. Создадим в основной системе файл для логов и разрешим писать туда пользователю из docker контейнера:
# touch mariadb/error.log
# chmod 777 mariadb/error.log
В секции command: пропишем команду, которая заставит демон mariadb включить запись лого в файл: mariadbd --log_error="/var/log/mysql/error.log"
И затем в секции volumes примонтируем внутренний файл контейнера «/var/log/mysql/error.log» к файлу основной операционной системы «mariadb/error.log»
Теперь логи mariadb будут записываться в файл в основной операционной системе.
После редактирования файла docker-compose.yml запускаем контейнеры:
# docker compose up --build
Из другой консоли пытаемся подключиться к базе:
# /usr/bin/mariadb -h127.0.0.1 --port=3309 -uroot –p
Вводим пароль из директивы MYSQL_ROOT_PASSWORD и мы в консоли mariadb под рутом.
Можно так же подключиться под именем user1 и паролем secret1
# /usr/bin/mariadb -h127.0.0.1 --port=3309 -u user1 -psecret1
Проверяем, создалась ли база mydb?
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
+--------------------+
2 rows in set (0.001 sec)
Все в порядке, база есть.
Создадим простую таблицу и внесем туда одну строку для теста
> USE mydb;
> CREATE TABLE table_test (a int, b varchar(10));
> INSERT table_test VALUES(1,'mytext');
Эта информация останется в базе даже после перезагрузки контейнеров, так как файлы базы подключаются при старте контейнера из основной системы
Создадим файл dbtest.php в папке data, который будет подключаться к базе данных и выводить данные из таблицу table_test
<?php
$mysqli = new mysqli("mariadb", "user1", "secret1", "mydb");
if (mysqli_connect_errno()) {
echo "Ошибка: ", mysqli_connect_error();
exit;
} else {
echo "Соединение установлено<br>";
}
$query="SELECT a, b FROM table_test ";
$result = $mysqli->query($query) or die("Ошибка запроса");
echo "Данные из базы:<br>";
while($z=$result->fetch_row()) {
echo "a: ".$z[0].", b: ".$z[1];
}
?>
В качестве имени сервера, к которому нужно обращаться в php указываем имя сервиса из описания контейнера в файле docker-compose.yml.
$mysqli = new mysqli("mariadb", "user1", "secret1", "mydb");
Теперь обратившись по URL мы увидим информацию из базы данных:
http://10.10.49.166:8080/dbtest.php
# docker compose up
Запуск в режиме демона:
# docker compose up –d
Остановка контейнеров:
# docker stop mariadb1
Запуск контейнера:
# docker start mariadb1
Остановка всех контейнеров:
# docker compose down
Просмотр состояния контейнеров
# docker compose ps
Вход в контейнеры:
# docker exec -it nginx1 /bin/bash
# docker exec -it php1 /bin/bash
# docker exec -it mariadb1 /bin/bash
Просмотр логов контейнеров:
# docker compose logs -f nginx
# docker compose logs -f mariadb
# docker compose logs -f php-fpm
Привет, благодарю за статью!
ОтветитьУдалитьИменно та сборка, которую Я искал.
Только Я еще php.ini вынес из php-fpm в volumes
php-fpm:
image: bitnami/php-fpm
container_name: php1
volumes:
- ./html:/app
- ./php-fpm/php.ini:/opt/bitnami/php/etc/php.ini # <<<<<
networks:
- internal
для установки "opcache.enable = Off", для отключения кеширования страниц, чтобы при изменении *.php - файлов изменения сразу отображались в web-browsere.