Показаны сообщения с ярлыком Docker. Показать все сообщения
Показаны сообщения с ярлыком Docker. Показать все сообщения

среда, 24 апреля 2024 г.

Docker compose. Запуск контейнеров при старте операционной системы

Воспользуемся systemd для запуска контейнеров при старте системы.

Для этого создадим юнит systemd:
# nano /etc/systemd/system/docker-compose-app.service

Содержимое файла:
[Unit]
Description=Docker Compose Application Service
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/docker compose -f /home/korolev/app-dev/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /home/korolev/app-dev/docker-compose.yml down
TimeoutStartSec=0
Restart=on-failure

[Install]
WantedBy=multi-user.target


В конфигурации предполагается, что разработка идет в директории
/home/korolev/app-dev/

Рестартуем демон systemd:

# systemctl daemon-reload

И запускаем docker compose как службу:
# systemctl start docker-compose-app
# systemctl enable docker-compose-app


понедельник, 1 апреля 2024 г.

Установка web-сервера nginx с отдельными модулями php и mariadb с помощью docker

Создаем главную директорию проекта, где будут сложены все необходимые файлы и базы
# 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();
?>


Нам необходимо выстроить конструкцию контейнеров, показанную на рисунке ниже

Основная папка с файлами проекта – это папка data, куда будем складывать файлы html и php.

В директорию 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 / {
             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
    
    php-fpm:
        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://10.10.49.166:8080/info.php

Останавливаем контейнеры, нажав 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