Установка MySQL в Alpine используя Docker

Установка 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.

Пока!

Теги: , , ,

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *