Ручная установка и настройка серверов баз данных может отнять много времени, особенно если речь идет о множественных экземплярах с разными версиями. Автоматизация этого процесса значительно упростит жизнь системному администратору и сэкономит его рабочие часы. В этой статье рассматривается, как развернуть сервера MySQL и MariaDB в контейнерах Docker, используя автоматический скрипт. Этот скрипт также интегрирует базы данных в панель HestiaCP и phpMyAdmin, делая их доступными для управления и взаимодействия с веб-интерфейсом.
Скрипт, предложенный ниже, автоматизирует следующие задачи:
- Проверка и установка Docker и Docker Compose (если они не установлены).
- Создание контейнеров баз данных с выбранной версией MySQL или MariaDB: MySQL (5.7 и 8.0) MariaDB (10.8, 10.9 и 10.11).
- Настройка контейнеров для интеграции с HestiaCP и phpMyAdmin.
- Удаление контейнеров и связанных с ними данных и конфигураций при необходимости.
Предупреждение:
Этот скрипт предназначен для автоматизации развертывания серверов баз данных в контейнерах Docker и предназначен для опытных пользователей. Все действия выполняются с учетом особенностей и стандартных конфигураций, однако, перед его применением рекомендуется внимательно ознакомиться с логикой скрипта и протестировать его на тестовой среде.
Пожалуйста, убедитесь, что все данные и конфигурации, затронутые скриптом, сохранены или зарезервированы. Использование этого скрипта предполагает ответственность пользователя за его применение, и любые действия, связанные с внесением изменений в существующие конфигурации, выполняются на собственный страх и риск.
#!/bin/bash
# Log file location
LOG_FILE="/home/db_installation.log"
# Logging function
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
sed -i 's/^#precedence ::ffff:0:0\/96 10/precedence ::ffff:0:0\/96 100/' /etc/gai.conf
# Function to generate a random password
generate_password() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 16
}
# Function to check for an existing container
check_existing_container() {
local db_version=$1
if [ "$(docker ps -a --filter "name=${db_version}" --filter "label=zomro_add_db" --format '{{.Names}}')" ]; then
log "Container named ${db_version} with the zomro_add_db flag is already running. Removing existing container..."
docker rm -f ${db_version}
fi
}
# Function to remove a container by version
remove_container() {
local db_version=$1
if [ "$(docker ps -a --filter "name=${db_version}" --filter "label=zomro_add_db" --format '{{.Names}}')" ]; then
log "Removing container named ${db_version} with the zomro_add_db flag..."
docker rm -f ${db_version}
rm -rf /var/lib/${db_version}
rm -rf /root/docker_${db_version}
remove_phpmyadmin_config $db_version
remove_hestia_mysql_config $db_version
log "Container ${db_version} and related data removed."
else
log "No container named ${db_version} with the zomro_add_db flag found."
fi
}
# Function to remove the corresponding HestiaCP MySQL configuration entry from mysql.conf using sed
remove_hestia_mysql_config() {
local db_version=$1
local hestia_config_file="/usr/local/hestia/conf/mysql.conf"
if [ -f "$hestia_config_file" ]; then
cp "$hestia_config_file" "${hestia_config_file}.bak"
log "Backup of HestiaCP MySQL configuration created: ${hestia_config_file}.bak"
# Exact deletion of a line with the HOST identifier
sed -i "/HOST='${db_version}'/d" "$hestia_config_file"
log "Removed HestiaCP MySQL configuration entry for ${db_version}."
else
log "HestiaCP MySQL configuration file not found."
fi
}
# Function to remove the corresponding phpMyAdmin configuration entry
remove_phpmyadmin_config() {
local db_version=$1
local config_file="/etc/phpmyadmin/conf.d/01-${db_version}.php"
if [ -f "$config_file" ]; then
rm -f "$config_file"
log "Removed phpMyAdmin configuration for ${db_version} located at ${config_file}."
else
log "No phpMyAdmin configuration found for ${db_version}."
fi
}
# Function to check if Docker is installed
check_docker_installed() {
if ! command -v docker &> /dev/null; then
log "Docker is not installed. Installing Docker..."
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
systemctl start docker
systemctl enable docker
else
log "Docker is already installed."
fi
}
# Function to check if Docker Compose is installed
check_docker_compose_installed() {
if ! command -v docker-compose &> /dev/null; then
log "Docker Compose is not installed. Installing Docker Compose..."
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
ARCH="x86_64"
elif [ "$ARCH" = "aarch64" ]; then
ARCH="aarch64"
else
log "Unsupported architecture: $ARCH"
exit 1
fi
# Link to the desired version of Docker Compose
VERSION="v2.25.0"
DOCKER_COMPOSE_URL="https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-${OS}-${ARCH}"
# Download and install Docker Compose
curl -L "$DOCKER_COMPOSE_URL" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# Checking the installation
if command -v docker-compose &> /dev/null; then
log "Docker Compose installed successfully."
else
log "Failed to install Docker Compose."
exit 1
fi
else
log "Docker Compose is already installed."
fi
}
# Function to add phpMyAdmin configuration for a specific database version
add_phpmyadmin_config() {
local db_version=$1
local port=$2
local config_file="/etc/phpmyadmin/conf.d/01-${db_version}.php"
log "Creating phpMyAdmin configuration for ${db_version} on port ${port}..."
cat << EOF > "$config_file"
<?php
\$cfg['Servers'][\$i]['host'] = '${db_version}';
\$cfg['Servers'][\$i]['port'] = '${port}';
\$cfg['Servers'][\$i]['auth_type'] = 'cookie';
\$cfg['Servers'][\$i]['verbose'] = '${db_version}';
// Session termination settings
\$cfg['LoginCookieValidity'] = 1440;
\$cfg['LoginCookieStore'] = 0;
\$cfg['ShowPhpInfo'] = true;
// Interface additional settings
\$cfg['ShowChgPassword'] = true;
\$cfg['ShowDbStructureCharset'] = true;
\$cfg['ShowDbStructureCreation'] = true;
\$cfg['ShowDbStructureLastUpdate'] = true;
\$cfg['ShowDbStructureLastCheck'] = true;
// Memory and runtime settings
\$cfg['MemoryLimit'] = '512M';
\$cfg['ExecTimeLimit'] = 300;
\$cfg['UploadDir'] = '';
\$cfg['SaveDir'] = '';
EOF
# root:www-data for config_file
chmod 640 "$config_file"
chown root:www-data "$config_file"
log "phpMyAdmin configuration for ${db_version} added at ${config_file}."
}
# Checking if Docker is installed
check_docker_installed
# Checking if Docker Compose is installed
check_docker_compose_installed
# Generate passwords
MYSQL_ROOT_PASSWORD=$(generate_password)
# Prompting the user to select an action
echo "Select an action:"
echo "1) Install a MySQL/MariaDB server"
echo "2) Remove an existing MySQL/MariaDB server"
read -p "Enter the number corresponding to your choice: " action_choice
if [ "$action_choice" -eq 1 ]; then
log "Prompting the user to select a database version to install..."
echo "Select the database version to install:"
echo "1) MySQL 5.7"
echo "2) MySQL 8.0"
echo "3) MariaDB 10.8"
echo "4) MariaDB 10.9"
echo "5) MariaDB 10.11"
read -p "Enter the number corresponding to your choice: " db_choice
case $db_choice in
1)
DB_IMAGE="mysql:5.7.44-oraclelinux7"
DB_VERSION="mysql-5.7"
DB_TYPE="mysql"
;;
2)
DB_IMAGE="mysql:8.0"
DB_VERSION="mysql-8.0"
DB_TYPE="mysql"
;;
3)
DB_IMAGE="mariadb:10.8"
DB_VERSION="mariadb-10.8"
DB_TYPE="mariadb"
;;
4)
DB_IMAGE="mariadb:10.9"
DB_VERSION="mariadb-10.9"
DB_TYPE="mariadb"
;;
5)
DB_IMAGE="mariadb:10.11"
DB_VERSION="mariadb-10.11"
DB_TYPE="mariadb"
;;
*)
log "Invalid choice. Installation aborted."
exit 1
;;
esac
check_existing_container $DB_VERSION
if ! grep -q "${DB_VERSION}" /etc/hosts; then
echo "127.0.0.1 ${DB_VERSION}" >> /etc/hosts
log "Added hostname ${DB_VERSION} to /etc/hosts"
fi
log "Creating Docker Compose configuration..."
AVAILABLE_PORT=3306
while ss -tuln | grep -q ":$AVAILABLE_PORT"; do
AVAILABLE_PORT=$((AVAILABLE_PORT + 1))
done
mkdir -p /root/docker_${DB_VERSION}
if [ "$DB_TYPE" = "mysql" ] && [ "$DB_VERSION" = "mysql-8.0" ]; then
cat << EOF > /root/docker_${DB_VERSION}/init.sql
ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';
CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EOF
cat << EOF > /root/docker_${DB_VERSION}/docker-compose.yml
services:
${DB_VERSION}:
image: $DB_IMAGE
container_name: ${DB_VERSION}
ports:
- "${AVAILABLE_PORT}:3306"
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
command: --default-authentication-plugin=mysql_native_password --bind-address=0.0.0.0
volumes:
- /var/lib/${DB_VERSION}:/var/lib/mysql
- /root/docker_${DB_VERSION}/init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
labels:
zomro_add_db: "true"
EOF
else
if [ "$DB_TYPE" = "mysql" ]; then
cat << EOF > /root/docker_${DB_VERSION}/init.sql
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_ROOT_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EOF
elif [ "$DB_TYPE" = "mariadb" ]; then
cat << EOF > /root/docker_${DB_VERSION}/init.sql
CREATE OR REPLACE USER 'root'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EOF
fi
cat << EOF > /root/docker_${DB_VERSION}/docker-compose.yml
services:
${DB_VERSION}:
image: $DB_IMAGE
container_name: ${DB_VERSION}
ports:
- "${AVAILABLE_PORT}:3306"
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
MYSQL_ROOT_HOST: '%'
command: --bind-address=0.0.0.0
volumes:
- /var/lib/${DB_VERSION}:/var/lib/mysql
- /root/docker_${DB_VERSION}/init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
labels:
zomro_add_db: "true"
EOF
fi
if [ -d "/var/lib/${DB_VERSION}" ]; then
BACKUP_DIR="/var/lib/${DB_VERSION}_backup_$(date +%Y%m%d%H%M%S)"
mv /var/lib/${DB_VERSION} $BACKUP_DIR
log "Backup created: ${BACKUP_DIR}"
else
log "Data directory not found. Skipping backup creation."
fi
rm -rf /var/lib/${DB_VERSION}
log "Starting Docker Compose for ${DB_VERSION}..."
docker-compose -f /root/docker_${DB_VERSION}/docker-compose.yml up -d
log "Waiting for the database to be ready..."
RETRIES=30
for i in $(seq 1 $RETRIES); do
if docker exec ${DB_VERSION} mysql -u root -p$MYSQL_ROOT_PASSWORD -e "SELECT VERSION();" >/dev/null 2>&1; then
log "Database is ready."
break
else
log "Database is not ready yet. Retrying in 5 seconds..."
sleep 10
fi
if [ "$i" -eq "$RETRIES" ]; then
log "Failed to connect to the database after $RETRIES attempts."
exit 1
fi
done
log "Adding database access to HestiaCP..."
v-add-database-host mysql ${DB_VERSION} root $MYSQL_ROOT_PASSWORD '' '' '' $AVAILABLE_PORT
add_phpmyadmin_config "${DB_VERSION}" "${AVAILABLE_PORT}"
RED='\033[0;31m'
NC='\033[0m'
log "Installation of ${DB_VERSION} server completed successfully."
echo -e "${RED}"
echo "==========================================="
echo " ACCESS DETAILS"
echo "-------------------------------------------"
echo "Host: ${DB_VERSION}"
echo "Port: $AVAILABLE_PORT"
echo "User: root"
echo "Password: $MYSQL_ROOT_PASSWORD"
echo "==========================================="
echo -e "${NC}"
elif [ "$action_choice" -eq 2 ]; then
log "Prompting the user to select a database version to remove..."
echo "Select the database version to remove:"
echo "1) MySQL 5.7"
echo "2) MySQL 8.0"
echo "3) MariaDB 10.8"
echo "4) MariaDB 10.9"
echo "5) MariaDB 10.11"
read -p "Enter the number corresponding to your choice: " db_remove_choice
case $db_remove_choice in
1)
DB_VERSION="mysql-5.7"
;;
2)
DB_VERSION="mysql-8.0"
;;
3)
DB_VERSION="mariadb-10.8"
;;
4)
DB_VERSION="mariadb-10.9"
;;
5)
DB_VERSION="mariadb-10.11"
;;
*)
log "Invalid choice. Removal aborted."
exit 1
;;
esac
remove_container $DB_VERSION
else
log "Invalid action. Exiting."
exit 1
fi
exit 0
Подготовка к автоматизации
Для начала работы необходимо убедиться, что ваш сервер поддерживает Docker и Docker Compose. Скрипт автоматически проверяет наличие этих компонентов и, при необходимости, выполняет их установку. Docker обеспечивает изоляцию процессов, позволяя каждому экземпляру базы данных работать в своем собственном контейнере, а Docker Compose облегчает управление конфигурациями многоконтейнерных приложений.
Порядок выполнения скрипта
Установка Docker и Docker Compose
- Сначала скрипт проверяет, установлены ли Docker и Docker Compose. Если нет — производит их загрузку и установку, активирует службу Docker и настраивает автоматический запуск.
- Эта проверка исключает необходимость вручную отслеживать наличие нужных утилит на сервере, что особенно полезно для администраторов, работающих с множественными системами или версиями ОС.
Генерация и удаление контейнеров для MySQL и MariaDB
- Скрипт предоставляет интерфейс для выбора версии сервера баз данных: MySQL (5.7 и 8.0) или MariaDB (10.8, 10.9 и 10.11).
- После выбора версии происходит генерация Docker Compose конфигурации, с которой и запускается контейнер.
- Если контейнер с данным именем уже существует, скрипт удаляет его, что помогает избежать конфликтов версий и ошибок при развертывании.
- Для каждой версии создается отдельный файл и уникальный порт для подключения, а также резервная копия папки данных в случае существования предыдущих данных.
Создание и настройка конфигурации phpMyAdmin
- После успешного создания контейнера скрипт добавляет конфигурацию для phpMyAdmin, чтобы база данных была доступна для администрирования через веб-интерфейс.
- Конфигурация включает параметры доступа: хост, порт и метод аутентификации.
- Устанавливаются дополнительные настройки, такие как лимиты времени выполнения запросов и использование cookie для аутентификации, что добавляет гибкость в работе с phpMyAdmin.
Добавление конфигурации в HestiaCP
- HestiaCP, будучи популярной панелью управления, требует интеграции с базами данных для более простого управления ими. Скрипт добавляет хост базы данных в конфигурационный файл HestiaCP, делая его доступным для приложений и пользователей панели.
- Для этого скрипт использует команду v-add-database-host, которая добавляет запись в HestiaCP и назначает ей порт, выбранный при создании контейнера. Таким образом, вам не придется добавлять базы данных вручную — все конфигурации добавляются автоматически.
Интерфейс выбора действий (установка или удаление)
- После выполнения всех проверок и установок скрипт предлагает интерфейс выбора: установить новый сервер базы данных или удалить уже существующий.
- При выборе удаления скрипт удаляет контейнер и связанные с ним конфигурационные файлы, а также очищает данные в HestiaCP и phpMyAdmin. Удаление происходит аккуратно: сначала проверяются существующие записи, затем они безопасно удаляются.
Вывод учетных данных
По завершении установки скрипт выводит доступ к базе данных:
- IP-адрес,
- порт,
- имя пользователя,
- пароль.
Эта информация позволяет быстро приступить к работе, не тратя времени на поиск учетных данных в системе.
Заключение
Используя данный скрипт, вы можете автоматизировать процесс установки баз данных в Docker, не отвлекаясь на ручные операции. Это решение подходит для различных сценариев, начиная от тестовых окружений до развертывания баз данных в производственных средах. Скрипт также может быть расширен для работы с другими версиями или типами баз данных, что делает его удобным и универсальным инструментом для системного администратора.