Diese Version (2024/08/03 23:42) wurde bestätigt durch Daniel.Die zuvor bestätigte Version (2024/08/03 23:10) ist verfügbar.Diff

Docker: MariaDB

This Guide will briefly show how to setup MariaDB on Docker in rootless- mode as written here https://obel1x.de/dokuwiki/doku.php?id=content:serverbasics:docker|

Note that this will NOT work out of the Box right now, see this bug here: https://github.com/phpmyadmin/docker/issues/187#issuecomment-1872177089 Currently you need to change the file docker-entrypoint.sh manually after downloading the images.

Using Postgres for some time, i switched to mysql and than to mariadb as i like it most, as you can do good performence- measurements with the ability to slowlog.

Remarks to my setup:

  • Tuned mariadb for Nextcloud
  • Using Sockets, not TCP/IP on the host
  • Added some tweaks from the net

On the Host, the directory /run/mysqld/mysqld.sock will be used instead of tcp/ip. This directory needs to be created as tmpfs by systemd at boot.

Create the File /etc/tmpfiles.d/docker-mariadb.conf with content

#Type Path            Mode UID      GID    Age Argument
d     /run/mysqld     0755 docker   docker -   -

First, create the directory /srv/docker-compose/mariadb and put the following files and content in it:

File .env

COMPOSE_HTTP_TIMEOUT=180

MARIADB_TAG=11.2.2

File docker-compose.yml

version: '3.8'
#
# Nach einigem hin und her, hat sich mariadb als zuverlässigste datenbank herausgestellt
# Achtung: NICHT mysql, sondern mariadb !
#
services:
mariadb:
   image: mariadb:${MARIADB_TAG}
   platform: linux/amd64
   cap_add:
     - SYS_NICE
   restart: always
   command: --default-storage-engine innodb --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
   environment:
#Attention: won't work !
#      - MARIADB_ROOT_PASSWORD="XXX"
#use this and check the password at the logs of the first start:
     - MARIADB_RANDOM_ROOT_PASSWORD=1
     - MARIADB_AUTO_UPGRADE=1
# 0 = Null = False, but false does not work here
     - MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=0
#Could be set when opening port 3306 to the hosts network and disallow root when connecting from other hosts
#is only set the first time for user creation - after that its fixed and may only be changed after login or internally in the container
#wenn leer, dann wird als host % genommen (also alle)if not set, % = allow all is taken
#      - MARIADB_ROOT_HOST='%'
   security_opt: # see https://github.com/MariaDB/mariadb-docker/issues/434#issuecomment-1136151239
     - seccomp:unconfined
     - apparmor:unconfined
#can be set to prevent some limitations. as long as the service is fine, don't change!
#    ulimits:
#      nproc: "262144"
#      nofile:
#        soft: "262144"
#        hard: "262144"
#      memlock: "262144"
   healthcheck:
     test: healthcheck.sh --connect --innodb_initialized
     interval: 20s
     start_period: 10s
     timeout: 10s
     retries: 3
#This opens the IP- Port of MariaDB - i won't do this as the socket /run/mysqld/mysqld.sock is more efficient
#    ports:
#      - 3306:3306
   volumes:
     - mariadb_data:/var/lib/mysql
     - mariadb_log:/var/log/mysql
     - ./my.cnf:/etc/mysql/conf.d/my.cnf
     - /run/mysqld:/run/mysqld
#This won't work as mariadb does not get lock to that file when managed by docker (don't now why exactly)
#      - /run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
   tmpfs:
     - /tmp
   networks:
     - mariadb

 phpmyadmin:
   image: phpmyadmin:latest
   platform: linux/amd64
   restart: always
   ports:
     - 8081:80
   environment:
     - PMA_ARBITRARY=1
     - PMA_ABSOLUTE_URI=http://pcserver2023:8081/
     - PMA_HOSTS=localhost
#      - PMA_PORTS=/run/mysqld/mysqld.sock
     - PMA_PMADB=phpmyadmin
   volumes:
     # Own Config in local config.user.inc.php
     - ./config.user.inc.php:/etc/phpmyadmin/config.user.inc.php:ro
     - /run/mysqld:/run/mysqld
   healthcheck:
     test: "curl localhost:80"
     interval: "60s"
     timeout: "3s"
     start_period: "5s"
     retries: 3
   depends_on:
     - mariadb
   networks:
     - mariadb

volumes:
mariadb_data:
   driver_opts:
     device: ""
     type: ""
     o: "umask=0007"

 mariadb_log:
   driver: local
   driver_opts:
     device: ""
     type: ""
     o: "umask=0007"

networks:
   mariadb:

File my.cnf

[server]
max_connections = 12
#
skip_name_resolve = 1
#und Statistiken ausschalten
innodb_stats_on_metadata = 0
#
max_allowed_packet = 16M
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

#tmp-tables werden zum beispiel für update-select verwendet. wenn die hier nicht rein passen, werden sie auf der Platte
#erzeugt.
#Achtung: Warnungen, dass 0_TMPFILE nicht angelegt werden können, sind normal(!), hindern nicht an der Ausführung, solange mysql startet
#Diese soll gleich sein mit max_heap_table_size
tmp_table_size = 1024M
max_heap_table_size = 1024M

#Timeouts hochsetzen
# 3600 ist wohl zu viel, sagt mysqltuner
wait_timeout = 300
# damit wird dann nach 6 minuten inaktivität doch mal getrennt
interactive_timeout = 360

#[Warning] 'innodb-buffer-pool-instances' was removed. It does nothing now and exists only for compatibility with old my.cnf files.
#innodb_buffer_pool_instances = 1
# Standard 128 - wir haben 16GB Hauptspeicher und das soll eine große DB werden. Also diese auch etwas nutzen.
#innodb_buffer_pool_size = 128M
innodb_buffer_pool_size = 1024M
#log_file_size sollen 25% des buffer-pools sein
#sollen aber nicht mehr als 256M sein sagt der ratgeber... mal sehen
innodb_log_file_size = 256M
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = fsync
innodb_max_dirty_pages_pct = 90
query_cache_type = 1
query_cache_limit = 56M
query_cache_min_res_unit = 2k
query_cache_size = 64M
low-priority-updates=on
join_buffer_size = 256M
sort_buffer_size = 4M
read_rnd_buffer_size = 2M

#Nur fuer MyISAM-Tabellen: war 128M und fast nicht benutzt. soll man runterschalten, zur Performancesteigerung
key_buffer_size=64M

#Bin-Log: sehr wichtig!
log_bin=mysql-bin
binlog_format = ROW
expire_logs_days=3

#Slow Logs - Todos: Wie kann man das in Docker gut machen - also persistent, aber OHNE zuviel Datenmüll?
#solange ich die rotation nicht an habe, würde das zuviel schreiben
slow_query_log_file = /var/log/mysql/slow.log
log-slow-verbosity=explain
#slow_query_log = 0
#
#Möglichkeit 1: herausfinden vieler disk-zugriffe
#slow-query-log = 1
## Alder - default=sp - aber keiner weiss, wofür sp steht! Also raus!
#log-slow-disabled_statements=admin
#Deprecated mit MariaDB11 - "use log_slow_filter without admin"
#log-slow-admin-statements=off
#long-query-time=0
#log-slow-filter=filesort_on_disk,tmp_table_on_disk
#Möglichkeit 2: Lange Queries wegen fehlender Indizes
slow-query-log = 1
long-query-time=1
#log-slow-filter=not_using_index

[client]
default-character-set = utf8mb4
socket = /run/mysqld/mysqld.sock

[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
transaction_isolation = READ-COMMITTED
innodb_file_per_table=1
#[Warning] 'innodb-large-prefix' was removed. It does nothing now and exists only for compatibility with old my.cnf files.
#innodb_large_prefix=on
#[Warning] 'innodb-defragment' was removed. It does nothing now and exists only for compatibility with old my.cnf files.
#innodb-defragment=1

File config.user.inc.php

<?php

declare(strict_types=1);

# Settings for phpMyAdmin

# $cfg['ShowPhpInfo'] = true; // Adds a link to phpinfo() on the home page
$cfg['AllowArbitraryServer'] = false;

// Array starts at 1 ...
$i = 1;
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['socket'] = '/run/mysqld/mysqld.sock';
#$cfg['Servers'][$i]['auth_type'] = 'http';

Backing up MariaDB works like this:

#!/bin/bash
# This would be Postgres - i don't like postgres, so see beneath for mariadb:
# rm /backup/nextcloud_pgdumpall.zstd
# docker exec -t postgresql-pgsql_db-1 pg_dumpall -c -U postgres  | zstd -19 -o /backup/nextcloud_pgdumpall.zstd --no-progress
# For mariadb use mariadb-dump and root
# For mysql use mysqldump and admin
BACKUPFILE=/backup/nextcloud_mariadbdump.zstd
MARIADB_PASS='verysecretpassword'
echo "Backup of mariadb to ${BACKUPFILE}"
rm ${BACKUPFILE}
docker exec -t mariadb-mariadb-1 mariadb-dump --all-databases --single-transaction --quick --lock-tables=false -u root -p${MARIADB_PASS}  | zstd -19 -o ${BACKUPFILE} --no-progress
echo 'Backup done.'

Doing this will remove defragmentation and repair some stuff, so maybe you want to do this once a month or so mariadb_optimize.sh:

#!/bin/bash
#Optimize Database
# 28.11.2023: Docker-Version
# 13.12.2023: Replaced mysql by mariadb
#
echo "Check and optimize DB Mysql"

RUN_SQL=/srv/backupscripts/backupfiles/check_all_tables.sql
RUN_LOG=/srv/backupscripts/backupfiles/check_all_tables.log

#SQL="SELECT CONCAT('ANALYZE LOCAL TABLE \`',table_schema,'\`.\`',table_name,'\`;')"
SQL="SELECT CONCAT('CHECK TABLE \`',table_schema,'\`.\`',table_name,'\` EXTENDED;')"
SQL="${SQL} FROM information_schema.tables WHERE table_schema NOT IN"
SQL="${SQL} ('information_schema','performance_schema','mysql','sys','innodb')"
SQL="${SQL} AND engine IS NOT NULL"

MARIADB_USER='root'
MARIADB_PASS='verysecretpassword'
CONTAINERNAME='mariadb_mariadb_1'

RUN_CMD="docker exec -i ${CONTAINERNAME} mariadb -u${MARIADB_USER} -p${MARIADB_PASS}"

# Create SQL Commands to run
${RUN_CMD} -ANe"${SQL}" --raw --silent | grep TABLE> ${RUN_SQL}
# Execute CHECK TABLE Commands
${RUN_CMD} --raw --silent --table <${RUN_SQL}> ${RUN_LOG} 2>&1

#cat "${RUN_LOG}" | grep check
#RUN_ERROR=(`cat "${RUN_LOG}" | grep check`)
RUN_ERROR=(`cat "${RUN_LOG}" | grep error`)
if [[ ! -z "${RUN_ERROR}" |]]; then
  echo "***********************************************"
  echo ""
  echo "!!!! ERROR- STOP OPTIMIZE: Some MySQL Databases are corrupt, please check output in ${RUN_LOG}:"
  cat "${RUN_LOG}"
  echo ""
  echo "***********************************************"
  exit 1
fi
echo "Check MysqlDB was sucessful, no errors found"

exit 0

#For me, i choose to run this only every 6th of the month
ifStart=`date '+%d'`
if [ $ifStart == 06 ]
then
  echo "Optimize DB Mysql"
  RUN_SQL=/srv/backupscripts/backupfiles/optimize_all_tables.sql
  RUN_LOG=/srv/backupscripts/backupfiles/optimize_all_tables.log

  SQL="SELECT CONCAT('OPTIMIZE TABLE \`',table_schema,'\`.\`',table_name,'\`;')"
  SQL="${SQL} FROM information_schema.tables WHERE table_schema NOT IN"
  SQL="${SQL} ('information_schema','performance_schema','mysql','sys','innodb')"
  SQL="${SQL} AND engine IS NOT NULL"

  # Create SQL Commands to run
  ${RUN_CMD} -ANe"${SQL}" --raw --silent | grep TABLE> ${RUN_SQL}

  # Execute Commands
  ${RUN_CMD} --raw --silent --table <"${RUN_SQL}"> ${RUN_LOG} 2>&1
  cat "${RUN_LOG}"
  RUN_ERROR=(`cat "${RUN_LOG}" | grep error`)
  if [[ ! -z "${RUN_ERROR}" |]]; then
    echo "***********************************************"
    echo ""
    echo "!!!! ERROR- STOP OPTIMIZE: Some MySQL Databases are corrupt, please check output in ${RUN_LOG}:"
    echo ""
    echo "***********************************************"
    exit 1
  fi
  # Useless for Docker...
  #  /sbin/btrfs filesystem defragment /srv/faststorage/mysql -r
fi
echo "Optimize finished sucessfully"
exit 0

#Diese Version geht leider nicht, weil die KOmmandos im Docker nicht vorhanden sind...
#docker exec -t mysql-mysqldb-1 mysqlcheck -u admin -p'Ps.xz!)6JLn/YoGL' --check --auto-repair --all-databases 1>/dev/null
#docker exec -t mysql-mysqldb-1 mysqlcheck -u admin -p'Ps.xz!)6JLn/YoGL' --check --auto-repair --all-databases
Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
  • content/serverbasics/docker-mariadb.txt
  • Zuletzt geändert: 2024/08/03 23:41
  • von Daniel