Compare commits

..

21 Commits

Author SHA1 Message Date
8b7ac89601
updated supported releases 2024-06-14 15:26:37 +02:00
7a5317012d
updated mariadb version
All checks were successful
continuous-integration/drone/tag Build is passing
2023-06-06 14:35:06 +02:00
f3c1f54efc
updated mariadb versions
All checks were successful
continuous-integration/drone/tag Build is passing
2023-06-06 11:59:06 +02:00
ca4adfc189
fix jsonnet
All checks were successful
continuous-integration/drone/tag Build is passing
2022-03-01 19:11:04 +01:00
a2957e48b4
fix building
Some checks failed
continuous-integration/drone/tag Build is failing
2022-03-01 19:06:01 +01:00
325d580b03
updated drone with jsonnet
All checks were successful
continuous-integration/drone/tag Build is passing
2022-01-13 14:42:54 +01:00
8de0c8b2b7
typo 2022-01-13 14:27:49 +01:00
2b3d588dba
added mariadb 10.1 2022-01-13 11:58:53 +01:00
eca9c4083b
matrix build is now jsonnet 2022-01-13 11:54:20 +01:00
453130871b
some mariadb upgrades
All checks were successful
continuous-integration/drone/tag Build is passing
2022-01-13 09:17:56 +01:00
56ad6595a3
updated readme
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-19 14:43:50 +01:00
1ea25ff238
updated drone
All checks were successful
continuous-integration/drone/tag Build is passing
2021-03-19 14:15:15 +01:00
c76c4c4469
removed maria 10.1
All checks were successful
continuous-integration/drone/tag Build is passing
2021-03-19 13:46:16 +01:00
1e272b391f
added mariadb 10.5
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
2021-03-19 12:51:10 +01:00
e064feafff
added mariadb 10.4
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2019-11-26 13:26:00 +01:00
c70c7597be
new way for cron
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2019-11-26 12:57:46 +01:00
c9aa84320a
some docs
All checks were successful
continuous-integration/drone/push Build is passing
2019-11-25 22:20:43 +01:00
f94daa8467
support for mariadb includes
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2019-11-25 20:21:59 +01:00
989f283b6f
fix mysql custom parameters
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2019-11-25 18:54:15 +01:00
fc7b026b0a
fix docker build args
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2019-11-25 15:22:37 +01:00
385161bbe0
fix docker build args
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2019-11-25 15:19:38 +01:00
10 changed files with 353 additions and 438 deletions

45
.drone.jsonnet Normal file
View File

@ -0,0 +1,45 @@
local Pipeline(mariadb_version) = {
kind: "pipeline",
type: "docker",
name: "maria-" + mariadb_version,
steps: [
{
name: "build_and_publish_" + mariadb_version,
image: "plugins/docker:linux-amd64",
pull: "always",
settings: {
dockerfile: "Dockerfile",
build_args: [
"MARIA_VERSION=" + mariadb_version,
],
registry: "docker.asperti.com",
repo: "docker.asperti.com/paspo/mariadb-backup-slave",
username: {
from_secret: "docker_username",
},
password: {
from_secret: "docker_password",
},
tags: [ "latest-" + mariadb_version, "maria-" + mariadb_version ],
auto_tag: false,
force_tag: true,
daemon_off: false,
}
}
],
trigger: {
event: ['tag'],
}
};
[
Pipeline("11.4"),
Pipeline("11.3"),
Pipeline("11.2"),
Pipeline("11.1"),
Pipeline("11.0"),
Pipeline("10.11"),
Pipeline("10.6"),
Pipeline("10.5"),
Pipeline("10.4"),
]

View File

@ -1,83 +0,0 @@
kind: pipeline
name: default
steps:
- name: build
image: plugins/docker:linux-amd64
pull: always
settings:
dockerfile: Dockerfile
daemon_off: false
dry_run: true
repo: docker.asperti.com/paspo/mariadb-backup-slave
when:
event:
exclude:
- tag
- name: build_and_publish_10_1
image: plugins/docker:linux-amd64
pull: always
environment:
MARIA_VERSION: 10.1
settings:
dockerfile: Dockerfile
auto_tag: false
force_tag: true
daemon_off: false
password:
from_secret: docker_password
registry: docker.asperti.com
repo: docker.asperti.com/paspo/mariadb-backup-slave
tags:
- maria-10.1
username:
from_secret: docker_username
when:
event:
- tag
- name: build_and_publish_10_2
image: plugins/docker:linux-amd64
pull: always
environment:
MARIA_VERSION: 10.2
settings:
dockerfile: Dockerfile
auto_tag: false
force_tag: true
daemon_off: false
password:
from_secret: docker_password
registry: docker.asperti.com
repo: docker.asperti.com/paspo/mariadb-backup-slave
tags:
- maria-10.2
username:
from_secret: docker_username
when:
event:
- tag
- name: build_and_publish_10_3
image: plugins/docker:linux-amd64
pull: always
environment:
MARIA_VERSION: 10.3
settings:
dockerfile: Dockerfile
auto_tag: true
force_tag: true
daemon_off: false
password:
from_secret: docker_password
registry: docker.asperti.com
repo: docker.asperti.com/paspo/mariadb-backup-slave
tags:
- latest
- maria-10.3
username:
from_secret: docker_username
when:
event:
- tag

View File

@ -1,14 +1,22 @@
ARG MARIA_VERSION=10.3
ARG MARIA_VERSION
FROM mariadb:${MARIA_VERSION}
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -q -y cron sudo automysqlbackup
COPY mysql.cnf /etc/mysql/mariadb.conf.d/settings.cnf
RUN chown mysql:mysql /etc/mysql/mariadb.conf.d/settings.cnf
COPY docker-entrypoint.sh /usr/local/bin/
COPY maria-include.cnf /etc/mysql/conf.d/maria-include.cnf
COPY custom.cnf /etc/mysql/mariadb.conf.d/custom.cnf
RUN chown mysql:mysql /etc/mysql/mariadb.conf.d/custom.cnf
COPY docker-entrypoint-new.sh /usr/local/bin/
COPY healthcheck.sh /usr/local/bin/
COPY automysqlbackup /etc/default
COPY sudoers /etc/sudoers.d/mysudoers
HEALTHCHECK CMD /usr/local/bin/healthcheck.sh
HEALTHCHECK --interval=30s --start-period=30s --timeout=3s \
CMD /usr/local/bin/healthcheck.sh
VOLUME /var/lib/automysqlbackup
ENTRYPOINT ["/usr/local/bin/docker-entrypoint-new.sh"]
CMD ["mariadbd"]

250
README.md
View File

@ -1,24 +1,262 @@
[![Build Status](https://drone.asperti.com/api/badges/paspo/docker-mariadb-backup-slave/status.svg)](https://drone.asperti.com/paspo/docker-mariadb-backup-slave)
# docker-mariadb-backup-slave
[![Build Status](https://drone.asperti.com/api/badges/paspo/docker-mariadb-backup-slave/status.svg)](https://drone.asperti.com/paspo/docker-mariadb-backup-slave)
Setup a mariadb slave server with automysqlbackup
## Parameters
### SERVER_ID
This is used to customize slave server ID. The default value is 33. You should use an unique ID for each server.
### READONLY
When set to **1**, the slave server is set as readonly. This is the default. If you set this variable to something different, the database will be read/write.
### REPLICATE_DO_DB
This is used to specify a single database to backup. It is generally advised to set this variable to the database name you want to backup.
## How to setup a mysql slave for backup
### Configure the master node
Examine all mariadb config files, they're usually located in **/etc/mysql/**. You must have these instructions:
```ini
[mysqld]
server_id = 1
log_bin
log-bin = binlog
max-binlog-size = 500M
binlog-do-db = my-db-name
bind-address = 0.0.0.0
```
$ docker exec some-mariadb sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /some/path/on/your/host/all-databases.sql
You must have an unique server_id and binlog enabled (the max-binlog-size is purely an example). The bind-address is here to make sure your server is reachable from the backup node. Maybe you can consider a firewall rule if your db shouldn't be reached from outside. The binlog-do-db is used to specify which database you want to be used with binlog; you can have multiple binlog-do-db lines if you need to replicate more than one db.
After these modifications, restart mariadb.
2019-11-24 10:57:24 0 [Warning] Neither --relay-log nor --relay-log-index were used; so replication may break when this MySQL server acts as a slave and has his hostname changed!! Please use '--log-basename=#' or '--relay-log=mysqld-relay-bin' to avoid this problem.
### Create a replication user
Execute this statement on the master node:
```sql
grant replication slave on *.* to repluser@backupslave.host identified by 'aRandomPassword'; flush privileges;
```
Replace **repluser**, **backupslave.host**, **aRandomPassword** with something more meaningful. Please take note that **in replication you cannot use a password longer than 32 characters**.
### Start the slave server
We use docker-compose here, but you can do the same with plain docker. Here's a sample **docker-compose.yaml** file:
```yaml
version: "3"
services:
backup-slave:
image: docker.asperti.com/paspo/mariadb-backup-slave
restart: always
volumes:
- "./mysql/:/var/lib/mysql"
- "./backup/:/var/lib/automysqlbackup"
environment:
- MYSQL_ROOT_PASSWORD=aSecurePassword
- SERVER_ID=3
- READONLY=0
- REPLICATE_DO_DB=aWordpressDatabase
- MARIADB_AUTO_UPGRADE=1
```
Start the container:
```bash
docker-compose up -d
```
Create the database:
```bash
docker exec my-container sh -c 'echo "create database aWordpressDatabase;" | exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"'
```
### Freeze the master
To obtain a consistant slave, you first have to freeze the master, and then transfer the data.
Execute this on the master:
```sql
FLUSH TABLES WITH READ LOCK;
show master status;
```
***Keep this session running!!!*** If you close it, it will release the lock.
Take note of file and position, we'll need these informations later.
### Import initial data
We have two ways to copy the data from the master to the slave: we'll call these "live" and "classic".
The classic way is the usual mysqldump + file transfer + import.
The live way is dump + import at the same time, without an intermediate file.
The live way is preferred when you have small databases (less than 5Gb) and a good bandwidth (100+ Mbit) available between the master and the slave.
The classic way is preferred when you have a big database because it locks the database for less time.
### Import initial data (live version)
Now, we need to import the backup from the master, so as we started the slave as readwrite, we can now do this on the slave:
```bash
docker exec my-container sh -c 'mysqldump -C --lock-tables=false --quick -u repluser -h master.host --password="aRandomPassword" aWordpressDatabase | mysql -u root -p"$MYSQL_ROOT_PASSWORD" aWordpressDatabase'
```
Replace **my-container**, **repluser**, **master.host**, **aRandomPassword**, **aWordpressDatabase** with the correct values.
Now that the slave has got some data, we can release the lock in the master:
```bash
UNLOCK TABLES;
```
### Import initial data (classic version)
In the master we run mysqldump in a shell:
```bash
mysqldump -u root -p aWordpressDatabase | gzip > thedump.sql.gz
```
When the export is finished, we can let the master resume his work, by issuing this command in the previous mysql session:
```bash
UNLOCK TABLES;
```
We can proceed to transfer the dump file to the slave; use the method you prefer.
On the slave, copy the dump file in the running container, like this:
```bash
docker cp thedump.sql.gz my-container:/thedump.sql.gz
```
Then we import it:
```bash
docker exec my-container sh -c 'zcat /thedump.sql.gz | mysql -u root -p"$MYSQL_ROOT_PASSWORD" aWordpressDatabase'
docker exec my-container sh -c 'rm /thedump.sql.gz'
```
Replace **my-container**, **aWordpressDatabase** with the correct values.
### Start the slave
Open a mysql console in the slave:
```bash
docker exec -ti my-container sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" aWordpressDatabase'
```
And configure the replication:
```sql
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO
MASTER_HOST='master.host',
MASTER_USER='repluser',
MASTER_PASSWORD='aRandomPassword',
MASTER_PORT=3306,
MASTER_LOG_FILE='binlog.000007',
MASTER_LOG_POS=1234567,
MASTER_HEARTBEAT_PERIOD=60,
MASTER_CONNECT_RETRY=10;
START SLAVE;
```
### Check replication status
```bash
docker exec -ti my-container sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" aWordpressDatabase -e "SHOW SLAVE STATUS\G;"'
```
Example output:
```sql
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master.host
Master_User: repluser
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: binlog.000008
Read_Master_Log_Pos: 12392188
Relay_Log_File: backup-slave-relay-bin.000002
Relay_Log_Pos: 51478388
Relay_Master_Log_File: binlog.000007
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: aWordpressDatabase
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 252550180
Relay_Log_Space: 116716314
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 31939
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
1 row in set (0.00 sec)
```
In a normal condition, **Slave_IO_Running** and **Slave_SQL_Running** should be **Yes**: this means that the communication between master and slave is ok and no sync error has occourred. **Seconds_Behind_Master** is usually 0, except wen the communication has just been established and the slave has to catch up with the master. This situation usually resolves in some time.
### Make the slave read-only
For a safety measure, we're enabling read-only mode for the slave: we don't have to run any query on this host, we're just using it for scheduled backups.
Reopen **docker-compose.yaml**, change **READONLY=0** to **READONLY=1** and restart the container:
```bash
docker-compose up -d
```
## How to use different mariadb version
The default is mariadb 10.5.
If you want, you can use mariadb 10.4, 10.3, or 10.2 by changing this line in **docker-compose.yaml**:
```yaml
image: docker.asperti.com/paspo/mariadb-backup-slave:maria-10.1
```
## Build the image locally
```sh
docker build -t mariadb-backup-slave:maria-10.3 --build-arg "MARIA_VERSION=10.3" .
```

4
custom.cnf Normal file
View File

@ -0,0 +1,4 @@
[mysqld]
server_id=33
replicate-do-db=
read-only

36
docker-entrypoint-new.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
set -eo pipefail
shopt -s nullglob
source /usr/local/bin/docker-entrypoint.sh
write_custom_config() {
SERVER_ID=${SERVER_ID:-33}
READONLY=${READONLY:-1}
cat >/etc/mysql/mariadb.conf.d/custom.cnf <<EOF
[mysqld]
server_id=${SERVER_ID}
replicate-do-db=${REPLICATE_DO_DB}
EOF
if [ "$READONLY" = "1" ] ; then
echo "read-only" >> /etc/mysql/mariadb.conf.d/custom.cnf
fi
}
start_cron() {
sudo cron -f &
}
chown_datadir() {
sudo chown -R mysql /var/lib/mysql
}
if ! _is_sourced; then
write_custom_config
chown_datadir
start_cron
_main "$@"
fi

View File

@ -1,344 +0,0 @@
#!/bin/bash
set -eo pipefail
shopt -s nullglob
# logging functions
mysql_log() {
local type="$1"; shift
printf '%s [%s] [Entrypoint]: %s\n' "$(date --rfc-3339=seconds)" "$type" "$*"
}
mysql_note() {
mysql_log Note "$@"
}
mysql_warn() {
mysql_log Warn "$@" >&2
}
mysql_error() {
mysql_log ERROR "$@" >&2
exit 1
}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
mysql_error "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
# check to see if this file is being run or sourced from another script
_is_sourced() {
# https://unix.stackexchange.com/a/215279
[ "${#FUNCNAME[@]}" -ge 2 ] \
&& [ "${FUNCNAME[0]}" = '_is_sourced' ] \
&& [ "${FUNCNAME[1]}" = 'source' ]
}
# usage: docker_process_init_files [file [file [...]]]
# ie: docker_process_init_files /always-initdb.d/*
# process initializer files, based on file extensions
docker_process_init_files() {
# mysql here for backwards compatibility "${mysql[@]}"
mysql=( docker_process_sql )
echo
local f
for f; do
case "$f" in
*.sh) mysql_note "$0: running $f"; . "$f" ;;
*.sql) mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
*.sql.gz) mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
*) mysql_warn "$0: ignoring $f" ;;
esac
echo
done
}
mysql_check_config() {
local toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) errors
if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
mysql_error $'mysqld failed while attempting to check config\n\tcommand was: '"${toRun[*]}"$'\n\t'"$errors"
fi
}
# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
mysql_get_config() {
local conf="$1"; shift
"$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \
| awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
# match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)"
}
# Do a temporary startup of the MySQL server, for init purposes
docker_temp_server_start() {
"$@" --skip-networking --socket="${SOCKET}" &
mysql_note "Waiting for server startup"
local i
for i in {30..0}; do
# only use the root password if the database has already been initializaed
# so that it won't try to fill in a password file when it hasn't been set yet
extraArgs=()
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
extraArgs+=( '--dont-use-mysql-root-password' )
fi
if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then
break
fi
sleep 1
done
if [ "$i" = 0 ]; then
mysql_error "Unable to start server."
fi
}
# Stop the server. When using a local socket file mysqladmin will block until
# the shutdown is complete.
docker_temp_server_stop() {
if ! mysqladmin --defaults-extra-file=<( _mysql_passfile ) shutdown -uroot --socket="${SOCKET}"; then
mysql_error "Unable to shut down server."
fi
}
# Verify that the minimally required password settings are set for new databases.
docker_verify_minimum_env() {
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
fi
}
# creates folders for the database
# also ensures permission for user mysql of run as root
docker_create_db_directories() {
local user; user="$(id -u)"
# TODO other directories that are used by default? like /var/lib/mysql-files
# see https://github.com/docker-library/mysql/issues/562
mkdir -p "$DATADIR"
if [ "$user" = "0" ]; then
# this will cause less disk access than `chown -R`
find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
fi
}
# initializes the database directory
docker_init_database_dir() {
mysql_note "Initializing database files"
installArgs=( --datadir="$DATADIR" --rpm )
if { mysql_install_db --help || :; } | grep -q -- '--auth-root-authentication-method'; then
# beginning in 10.4.3, install_db uses "socket" which only allows system user root to connect, switch back to "normal" to allow mysql root without a password
# see https://github.com/MariaDB/server/commit/b9f3f06857ac6f9105dc65caae19782f09b47fb3
# (this flag doesn't exist in 10.0 and below)
installArgs+=( --auth-root-authentication-method=normal )
fi
# "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
mysql_install_db "${installArgs[@]}" "${@:2}"
mysql_note "Database files initialized"
}
# Loads various settings that are used elsewhere in the script
# This should be called after mysql_check_config, but before any other functions
docker_setup_env() {
# Get config
declare -g DATADIR SOCKET
DATADIR="$(mysql_get_config 'datadir' "$@")"
SOCKET="$(mysql_get_config 'socket' "$@")"
# Initialize values that might be stored in a file
file_env 'MYSQL_ROOT_HOST' '%'
file_env 'MYSQL_DATABASE'
file_env 'MYSQL_USER'
file_env 'MYSQL_PASSWORD'
file_env 'MYSQL_ROOT_PASSWORD'
declare -g DATABASE_ALREADY_EXISTS
if [ -d "$DATADIR/mysql" ]; then
DATABASE_ALREADY_EXISTS='true'
fi
}
# Execute sql script, passed via stdin
# usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
# ie: docker_process_sql --database=mydb <<<'INSERT ...'
# ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
docker_process_sql() {
passfileArgs=()
if [ '--dont-use-mysql-root-password' = "$1" ]; then
passfileArgs+=( "$1" )
shift
fi
# args sent in can override this db, since they will be later in the command
if [ -n "$MYSQL_DATABASE" ]; then
set -- --database="$MYSQL_DATABASE" "$@"
fi
mysql --defaults-file=<( _mysql_passfile "${passfileArgs[@]}") --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" "$@"
}
# Initializes database with timezone info and root password, plus optional extra db/user
docker_setup_db() {
# Load timezone info into database
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
# sed is for https://bugs.mysql.com/bug.php?id=20545
mysql_tzinfo_to_sql /usr/share/zoneinfo \
| sed 's/Local time zone must be set--see zic manual page/FCTY/' \
| docker_process_sql --dont-use-mysql-root-password --database=mysql
# tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is not set yet
fi
# Generate random root password
if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
fi
# Sets root password and creates root users for non-localhost hosts
local rootCreate=
# default root to listen for connections from anywhere
if [ -n "$MYSQL_ROOT_HOST" ] && [ "$MYSQL_ROOT_HOST" != 'localhost' ]; then
# no, we don't care if read finds a terminating character in this heredoc
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
read -r -d '' rootCreate <<-EOSQL || true
CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ;
GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;
EOSQL
fi
# tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is just now being set
docker_process_sql --dont-use-mysql-root-password --database=mysql <<-EOSQL
-- What's done in this file shouldn't be replicated
-- or products like mysql-fabric won't work
SET @@SESSION.SQL_LOG_BIN=0;
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
-- 10.1: https://github.com/MariaDB/server/blob/d925aec1c10cebf6c34825a7de50afe4e630aff4/scripts/mysql_secure_installation.sh#L347-L365
-- 10.5: https://github.com/MariaDB/server/blob/00c3a28820c67c37ebbca72691f4897b57f2eed5/scripts/mysql_secure_installation.sh#L351-L369
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%' ;
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
FLUSH PRIVILEGES ;
${rootCreate}
DROP DATABASE IF EXISTS test ;
EOSQL
# Creates a custom database and user if specified
if [ -n "$MYSQL_DATABASE" ]; then
mysql_note "Creating database ${MYSQL_DATABASE}"
docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;"
fi
if [ -n "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
mysql_note "Creating user ${MYSQL_USER}"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;"
if [ -n "$MYSQL_DATABASE" ]; then
mysql_note "Giving user ${MYSQL_USER} access to schema ${MYSQL_DATABASE}"
docker_process_sql --database=mysql <<<"GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;"
fi
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
}
_mysql_passfile() {
# echo the password to the "file" the client uses
# the client command will use process substitution to create a file on the fly
# ie: --defaults-file=<( _mysql_passfile )
if [ '--dont-use-mysql-root-password' != "$1" ] && [ -n "$MYSQL_ROOT_PASSWORD" ]; then
cat <<-EOF
[client]
password="${MYSQL_ROOT_PASSWORD}"
EOF
fi
}
# check arguments for an option that would cause mysqld to stop
# return true if there is one
_mysql_want_help() {
local arg
for arg; do
case "$arg" in
-'?'|--help|--print-defaults|-V|--version)
return 0
;;
esac
done
return 1
}
_main() {
# if command starts with an option, prepend mysqld
if [ "${1:0:1}" = '-' ]; then
set -- mysqld "$@"
fi
# skip setup if they aren't running mysqld or want an option that stops mysqld
if [ "$1" = 'mysqld' ] && ! _mysql_want_help "$@"; then
mysql_note "Entrypoint script for MySQL Server ${MYSQL_VERSION} started."
mysql_check_config "$@"
# Load various environment variables
docker_setup_env "$@"
docker_create_db_directories
# If container is started as root user, restart as dedicated mysql user
if [ "$(id -u)" = "0" ]; then
mysql_note "Switching to dedicated user 'mysql'"
exec gosu mysql "$BASH_SOURCE" "$@"
fi
# there's no database, so it needs to be initialized
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
docker_verify_minimum_env
docker_init_database_dir "$@"
mysql_note "Starting temporary server"
docker_temp_server_start "$@"
mysql_note "Temporary server started."
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*
mysql_note "Stopping temporary server"
docker_temp_server_stop
mysql_note "Temporary server stopped"
echo
mysql_note "MySQL init process done. Ready for start up."
echo
fi
fi
exec "$@"
}
# If we are sourced from elsewhere, don't perform any further actions
if ! _is_sourced; then
SERVER_ID=${SERVER_ID:-33}
READONLY=${READONLY:-1}
cat >>/etc/mysql/mariadb.conf.d/settings.cnf <<EOF
server_id = ${SERVER_ID}
replicate-do-db = ${REPLICATE_DO_DB}
EOF
if [ "$READONLY" = "1" ] ; then
echo "read-only" >> /etc/mysql/mariadb.conf.d/settings.cnf
fi
sudo service cron start
_main "$@"
fi

View File

@ -1,8 +1,17 @@
#!/bin/bash
# slave not configured
RES=$(mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e 'SHOW SLAVE STATUS\G')
if [ "a$RES" = "a" ]; then
exit 0
fi
# slave ok
RES=$(mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e 'SHOW SLAVE STATUS\G' | egrep '(Slave_IO_Running|Slave_SQL_Running):' | awk -F: '{print $2}' | tr '\n' ',')
if [ "$RES" = " Yes, Yes," ]; then
exit 0
fi
# slave not ok
exit 1

1
maria-include.cnf Normal file
View File

@ -0,0 +1 @@
!includedir /etc/mysql/mariadb.conf.d/

View File

@ -1,2 +1,3 @@
mysql ALL = (ALL) NOPASSWD: /usr/sbin/service cron start
mysql ALL = (ALL) NOPASSWD: /usr/sbin/cron
mysql ALL = (ALL) NOPASSWD: /usr/bin/chown