Установка MySQL в Alpine используя Docker
Приветствую! Решил сделать небольшое описание установки MySQL client/server в Alpine (используя Docker), чтобы, с какой-то вероятностью, предвосхитить и предотвратить Вашу головную боль. Я вообще за то, чтобы вопросы любой сложности можно было решать через docker-compose up, и поэтому, сразу дам ссылку на репозиторий: https://github.com/webdevdiary/docker-mysql-alpine.
Дальнейший текст, который уже никому не нужен
Все мы знаем, что можно взять готовый Docker-образ с MySQL, запустить его, и обращаться к нему откуда угодно, но иногда нужно иметь базу прямо на борту контейнера с приложением, например, если мы хотим запустить тесты на этапе CI/CD (в которых участвует база данных), в каком-нибудь GitLab CI, и нам было бы очень удобно иметь все в одном контейнере, который бы мы выкинули на помойку после прохождения тестов.
И выглядит такой Dockerfile так:
FROM alpine:3.16.3 AS with-mysql
USER root
RUN apk add --update --no-cache mysql mysql-client
COPY --chmod=644 conf/mysql_startup.sh /mysql_startup.sh
COPY --chmod=644 conf/my.cnf /etc/mysql/my.cnf
COPY --chmod=644 conf/mariadb-server.cnf /etc/my.cnf.d/mariadb-server.cnf
CMD sh /mysql_startup.sh
FROM with-mysql AS testing
COPY --chmod=644 conf/mysql_connection_test.sh /mysql_connection_test.sh
COPY --chmod=644 conf/mysql_query_test.sh /mysql_query_test.sh
CMD sh /mysql_startup.sh && \
until sh /mysql_connection_test.sh; do \
sleep 10; \
done; \
sh /mysql_query_test.sh
А docker-compose.yml выглядит так:
version: '3.9'
services:
testing:
build:
context: .
dockerfile: Dockerfile
target: testing
image: mysql-testing
container_name: mysql-testing
И файлы, которые должны лежать рядом с Dockerfile:
conf/my.cnf
[mysqld]
user = root
datadir = /app/mysql
socket = /run/mysqld/mysqld.sock
log-bin = /app/mysql/mysql-bin
conf/mariadb-server.cnf
#
# These groups are read by MariaDB server.
# Use it for options that only the server (but not clients) should see
# this is read by the standalone daemon and embedded servers
[server]
# this is only for the mysqld standalone daemon
[mysqld]
#skip-networking
socket = /run/mysqld/mysqld.sock
# Galera-related settings
[galera]
# Mandatory settings
#wsrep_on=ON
#wsrep_provider=
#wsrep_cluster_address=
#binlog_format=row
#default_storage_engine=InnoDB
#innodb_autoinc_lock_mode=2
#
# Allow server to accept connections on all interfaces.
#
#bind-address=0.0.0.0
#
# Optional setting
#wsrep_slave_threads=1
#innodb_flush_log_at_trx_commit=0
# this is only for embedded server
[embedded]
# This group is only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]
# This group is only read by MariaDB-10.5 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mariadb-10.5]
conf/mysql_startup.sh
#!/bin/sh
if [ ! -d "/run/mysqld" ]; then
mkdir -p /run/mysqld
fi
if [ -d /app/mysql ]; then
echo "[i] MySQL directory already present, skipping creation"
/usr/bin/mysqld &
else
echo "[i] MySQL data directory not found, creating initial DBs"
mysql_install_db --user=root > /dev/null
MYSQL_DATABASE=${MYSQL_DATABASE:-"mysql_test"}
MYSQL_USER=${MYSQL_USER:-"mysql_test"}
MYSQL_PASSWORD=${MYSQL_PASSWORD:-"mysql_test"}
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-"mysql_test"}
tfile=`mktemp`
if [ ! -f "$tfile" ]; then
return 1
fi
cat << EOF > $tfile
USE mysql;
FLUSH PRIVILEGES;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY "$MYSQL_ROOT_PASSWORD" WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
ALTER USER 'root'@'localhost' IDENTIFIED BY '';
EOF
if [ "$MYSQL_DATABASE" != "" ]; then
echo "[i] Creating database: $MYSQL_DATABASE"
echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` CHARACTER SET utf8 COLLATE utf8_general_ci;" >> $tfile
if [ "$MYSQL_USER" != "" ]; then
echo "[i] Creating user: $MYSQL_USER with password $MYSQL_PASSWORD"
echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* to '$MYSQL_USER'@'localhost' IDENTIFIED BY '$MYSQL_PASSWORD';" >> $tfile
fi
fi
/usr/bin/mysqld --verbose --init-file=$tfile &
fi
conf/mysql_connection_test.sh
#!/bin/sh
mysql -u mysql_test -pmysql_test mysql_test
conf/mysql_query_test.sh
#!/bin/sh
mysql -u mysql_test -pmysql_test mysql_test -e '
CREATE TABLE mysql_test (
test_field text
);
INSERT INTO mysql_test (test_field) VALUES ("MySQL is working!!!");
SELECT * FROM mysql_test;
'
Результат выполнения
Результатом выполнения будет что-то вроде этого:
Attaching to mysql-testing
mysql-testing | [i] MySQL data directory not found, creating initial DBs
mysql-testing | 2022-11-20 0:43:20 1 [Warning] Failed to load slave replication state from table mysql.gtid_slave_pos: 1017: Can't find file: './mysql/' (errno: 2 "No such file or di
rectory")
mysql-testing | [i] Creating database: mysql_test
mysql-testing | [i] Creating user: mysql_test with password mysql_test
mysql-testing | ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)
mysql-testing | 2022-11-20 0:43:22 0 [Note] /usr/bin/mysqld (server 10.6.10-MariaDB-log) starting as process 67 ...
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Compressed tables use zlib 1.2.12
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Number of pools: 1
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions
mysql-testing | 2022-11-20 0:43:22 0 [Note] mysqld: O_TMPFILE is not supported on /var/tmp (disabling future attempts)
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Using Linux native AIO
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Initializing buffer pool, total size = 134217728, chunk size = 134217728
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Completed initialization of buffer pool
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: 128 rollback segments are active.
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Creating shared tablespace for temporary tables
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: 10.6.10 started; log sequence number 42266; transaction id 14
mysql-testing | 2022-11-20 0:43:22 0 [Note] Plugin 'FEEDBACK' is disabled.
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Loading buffer pool(s) from /app/mysql/ib_buffer_pool
mysql-testing | 2022-11-20 0:43:22 0 [Note] InnoDB: Buffer pool(s) load completed at 221120 0:43:22
mysql-testing | 2022-11-20 0:43:22 0 [Note] Server socket created on IP: '0.0.0.0'.
mysql-testing | 2022-11-20 0:43:22 0 [Note] Server socket created on IP: '::'.
mysql-testing | 2022-11-20 0:43:22 0 [Note] /usr/bin/mysqld: ready for connections.
mysql-testing | Version: '10.6.10-MariaDB-log' socket: '/run/mysqld/mysqld.sock' port: 3306 MariaDB Server
mysql-testing | test_field
mysql-testing | MySQL is working!!!
mysql-testing exited with code 0
Заключение
Как Вы могли заметить, тут как бы MySQL, да не совсем чтобы до мозга костей. И правильно, ведь это MariaDB server. В подавляющем большинстве случаев, это полная замена MySQL, и причина её использования заключается в том, что MariaDB — Open Source, которую можно без проблем использовать в Alpine, в отличие от каких-то правовых проблем с MySQL.
Пока!