Разберёмся с помощью примера, что такое docker-compose
Docker Compose - это инструмент в экосистеме Docker, который позволяет определить и управлять многоконтейнерными приложениями. Он предоставляет удобный способ описать конфигурацию приложения в YAML-файле, который содержит информацию о контейнерах, сетях, объемах и других настройках.
С помощью Docker Compose вы можете объединить несколько сервисов и контейнеров в единую систему, описывая их зависимости и конфигурацию. Это особенно полезно, когда ваше приложение состоит из нескольких сервисов, например, веб-сервера, базы данных и кэша, и вы хотите запустить их одним командой или управлять ими с помощью нескольких команд.
Docker Compose легко устанавливается и работает на разных платформах. Он позволяет создавать, запускать и останавливать множество контейнеров из вашего приложения всего лишь одной командой. Это упрощает развертывание и масштабирование приложений, особенно в средах разработки, тестирования и производства.
В этой статье рассмотрим как легко и просто можно поднимать свои web сервера, на примере стека технологий: apache2, c php и postgresql с помощью одной команды, если у вас установлен docker и docker-compose.
Если не установлены, то в Debian подобных дистрибутивах это делается так:
Теперь приступим.
Рассмотрим всё на простом примере. Создаём каталог product с будущим проектом
mkdir product cd product
это будет корень проекта.
создаём каталоги
mkdir php mkdir html mkdir html/apache_logs mkdir pgsql
создаём файлы
touch php/Dockerfile touch html/index.php touch docker-compose.yaml touch mysite.conf
Заходим внутрь каталога php (в нём мы создадим файл именно с таким именем Dockerfile, даже регистр имеет значение, это файлы для создания docker образов, на тот случай если нам нужно что-то добавить в базовый образ который мы берём из dockerhub, в этом примере мы доработаем образ для нашего php сервера)
Затем идём в каталог html
Фактически этот каталог и будет, для файлов нашего сайта, который мы планируем запустить на этом сервере, поэтому в нём сразу создаём файл index.php для тестирования работоспособности наших контейнеров.
Так же в этом же каталоге создаём подкаталог apache_logs
для логов сервера.
Выходим обратно на уровень product и создаём ещё один каталог для второго контейнера баз данных, фактически для хранения на хосте файлов с базой данных и настроек,
pgsql
Теперь основное действие, здесь же на корневом уровне проекта, создаём файл для сборки контейнеров
называется вот так: docker-compose.yaml
в точности копируем, вместе с расширением yaml
Теперь создадим файл настроек apache2 который будет работать в контейнере, mysite.conf это файл конфигурации нашего сайта для сервера apache2 который мы смонтируем внутрь контейнера при его создании. В тот же контейнр мы смонтируем и каталог html
А во второй контейнер, с базой данных мы смонтируем каталог pgsql
Как всё это будет монтироваться, мы наглядно мы увидем в содержимом файла docker-compose.yaml
А пока, сейчас у вас должна быть вот такая структура корня проекта, каталог product:
.
├── docker-compose.yaml
├── html
│ ├── apache_logs
│ ├── index.html
│ └── index.php
├── mysite.conf
├── pgsql
├── php
│ └── Dockerfile
└── README.md
создайте все эти файлы и каталоги, и приступим к их заполнению.
начнём с файла
docker-compose.yaml Обратите внимание все отступы, в этом файле, как и оступы в файлах Dockerfile, строго одного уровня, они имееют синтаксическое значение, почти точно такое же как и в файлах python, поэтому внимательно соблюдайте такие оступы, если желаете, чтобы у вас всё работало без ошибок.
обратите внимение, все строки которые начинаются с # можно просто удалить, они являются комментариями и никак не учитываются при сборке.
☯
Terminal:
⌕
≡
✕
#любой комментарий в таком файле начинается со знака решётки version: '3' services: #первый контейнер для php и сервера apache2 php: build: #обратите внимание как мы сначала указываем, где находится наш Dockerfile для сборки этого образа относительно корня проекта context: ./php dockerfile: Dockerfile #если бы нам не нужно было добавлять никаких пакетов в образ то можно было вместо этих трёх строк выше начиная с build, для Dockerfile просто указать название образа, строка ниже. #image: php:8.0-apache #Но так мы ещё сделаем с образом для контейнеров базы данных ниже. ports: #здесь мы указываем на каких портах будет работать контейнер. т.е. первым идёт порт хоста с которого мы запустим контейнер #вторым через : идёт порт внутри контейнера - '80:80' - '25:25' volumes: #вот это есть деректива монтирования #здесь показы вначале локальные каталоги на вашем хосте, и корня проекта, а затем через знак : каталоги в которых они будут расположены внутри контейнеров - ./html:/var/www/html - ./html:/usr/local/apache2/htdocs - ./html/apache_logs:/var/log/apache2 - ./mysite.conf:/usr/local/apache2/conf/extra/mysite.conf depends_on: # здесь мы указываем зависимость или связь со вторым образом, который мы назовём db и пропишем ниже - db environment: #здесь мы указываем переменную окружения, в данном случае зададим переменной DOMEN, url адрес, обратите внимаение как #эта переменная используется при создании контейнера, на локально хосте если нет домен можно использовать localhost или обращаться к серверу просто по его ip - DOMAIN=ramanzes.freemyip.com networks: # и ещё один важный параметр это внутренняя сеть, наших контейнеров по которым они будут работать друг с другом - myapp_network #второй контейнер для сервера PostgreSQL создаём просто из образа db: image: postgres:latest volumes: - ./pgsql:/var/lib/postgresql/data environment: - POSTGRES_USER=docker - POSTGRES_PASSWORD=dockerpassword - POSTGRES_DB=base_docker networks: - myapp_network #без оступа как и services начинаеся деректива сети.Для простоты я добавлю указание использования сети по умолчанию, называемой bridge. networks: myapp_network: driver: bridge
Теперь файл mysite.conf:
В котором, кстати отступы, уже не имеют синтаксического значения, только для наглядности.
Эта конфигурация будет добавлена внутрь контейнера, после сборки...
☯
Terminal:
⌕
≡
✕
ServerRoot "/usr/local/apache2" Listen 80 DocumentRoot "/var/www/html"Options Indexes FollowSymLinks AllowOverride All Require all granted SetHandler application/x-httpd-php ErrorLog "/var/log/apache2/error.log" LogLevel warn CustomLog "/var/log/apache2/access.log" combined
теперь файл ├── php
│ └── Dockerfile
Dockerfile
☯
Terminal:
⌕
≡
✕
FROM php:8.0-apache ENV PGSQL_DIR /var/lib/postgresql/data RUN apt-get update \ && apt-get install -y libpq-dev postgresql-client \ && docker-php-ext-install pdo pdo_pgsql
теперь файл
├── html
│ └── index.php
Для проверки связи контейнеров, вот пример на PHP, который создает таблицу в базе данных PostgreSQL, заполняет ее случайным текстом и выводит этот текст на экран в браузере:
☯
Terminal:
⌕
≡
✕
<h1>Да php работает</h1> <?php phpinfo(); ?>
<?php
$host = 'db';
$port = '5432';
$user = 'docker';
$password = 'dockerpassword';
$database = 'base_docker';
$dsn = "pgsql:host=$host;port=$port;dbname=$database";
$conn = new PDO($dsn, $user, $password);
// Выполните нужные вам действия с соединением к базе данных PostgreSQL
$dsn = "pgsql:host=$host;port=$port;dbname=$database;user=$user;password=$password";
try {
$conn = new PDO($dsn);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected to the PostgreSQL database successfully<br><br>";
// Создание таблицы
$sql = "CREATE TABLE IF NOT EXISTS random_text (
id serial PRIMARY KEY,
text VARCHAR(255) NOT NULL
)";
$conn->exec($sql);
echo "Table 'random_text' created successfully<br><br>";
// Заполнение таблицы случайным текстом
for ($i = 1; $i <= 10; $i++) {
$randomText = generateRandomText();
$sql = "INSERT INTO random_text (text) VALUES ('$randomText')";
$conn->exec($sql);
echo "Inserted random text: $randomText<br>";
}
// Вывод текста из базы данных на экран
$sql = "SELECT * FROM random_text";
$result = $conn->query($sql);
$rows = $result->fetchAll(PDO::FETCH_ASSOC);
if (count($rows) > 0) {
echo "<br>Random Text:<br>";
foreach ($rows as $row) {
echo $row['text'] . "<br>";
}
} else {
echo "No random text found";
}
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
$conn = null;
// Функция для генерации случайного текста
function generateRandomText($length = 20) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$randomText = '';
for ($i = 0; $i < $length; $i++) {
$randomText .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomText;
}
?>
Приведенный пример создает таблицу 'random_text' с двумя столбцами: 'id' (идентификатор) и 'text' (текстовое поле). Затем он заполняет таблицу случайным текстом, используя функцию generateRandomText(). Наконец, он извлекает текст из базы данных и выводит его на экран в браузере.
Перед использованием этого примера необходимо заменить значения "имя_базы_данных", "имя_пользователя" и "пароль" на соответствующие данные вашей базы данных PostgreSQL, т.е. здесь будут использоваться те данные, что были указаны в docker-compose.yaml при создании второго контейнера. Убедитесь, что у вас есть соединение с базой данных для выполнения примера. Также учтите, что данное решение для базы данных PostgreSQL, и вам понадобится установленный драйвер PHP для работы с PostgreSQL, о чём мы уже тоже позаботились при создании образа из Dockerfile.
После приведения своего рабочего каталога в такой вид, находясь в корне проекта, т.е. в том же каталоге, же где и файл docker-compose.yaml
Выполняем следующие команды по порядку. Загрузим образы на свой компьютер.
Создадим контейнеры из этих образов и запустим их, следующей командой:
Убедимся, что контейнеры запустились успешно:
Ну и понятное дело, что если вы откроете в браузере домен в моём случае это http://ramanzes.freemyip.com, ну или localhost, который вы указали в образе php при создании web сервера, вы увидете свой сервер в работе.