====== Docker: MariaDB ====== This Guide will briefly show how to setup MariaDB on Docker in rootless- mode as written here [[.:docker|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|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 ===== Create Socket in tmpfs ===== 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 - - ===== Yaml and .env, configuration of mariadb and phpMyAdmin ===== 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'' ===== Backup ===== 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.' ===== Optimizing Tables ===== 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