Skip to content
This repository has been archived by the owner on Nov 8, 2019. It is now read-only.

Commit

Permalink
A reworked version of #194
Browse files Browse the repository at this point in the history
These changes are based on the code that from https://github.com/sclorg/mariadb-container.
Even if the image is meant to work in OpenShift, it doesn't mean that it shouldn't
work outside of OpenShift -- the opposite is true, the image should be usable on
Atomic or normal Fedora Server/Workstation/Cloud without any issues as well.
  • Loading branch information
hhorak committed May 26, 2016
1 parent 8952fa4 commit 4ed1619
Show file tree
Hide file tree
Showing 28 changed files with 1,287 additions and 299 deletions.
56 changes: 49 additions & 7 deletions mariadb/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,55 @@
FROM fedora
MAINTAINER http://fedoraproject.org/wiki/Cloud
RUN dnf -y update && dnf clean all
RUN dnf -y install mariadb-server pwgen psmisc net-tools hostname && \
dnf clean all

ADD scripts /scripts
RUN chmod 755 /scripts/*
# MariaDB image for OpenShift.
#
# Volumes:
# * /var/lib/mysql/data - Datastore for MariaDB
# Environment:
# * $MYSQL_USER - Database user name
# * $MYSQL_PASSWORD - User's password
# * $MYSQL_DATABASE - Name of the database to create
# * $MYSQL_ROOT_PASSWORD (Optional) - Password for the 'root' MySQL account

ENV MYSQL_VERSION=10.0 \
HOME=/var/lib/mysql

LABEL summary="MariaDB is a multi-user, multi-threaded SQL database server" \
io.k8s.description="MariaDB is a multi-user, multi-threaded SQL database server" \
io.k8s.display-name="MariaDB 10.0" \
io.openshift.expose-services="3306:mysql" \
io.openshift.tags="database,mysql,mariadb,mariadb100"

VOLUME ["/var/lib/mysql", "/var/log/mysql"]
EXPOSE 3306

CMD ["/bin/bash", "/scripts/start.sh"]
# This image must forever use UID 27 for mysql user so our volumes are
# safe in the future. This should *never* change, the last test is there
# to make sure of that.
# https://git.fedorahosted.org/cgit/setup.git/tree/uidgid
# policycoreutils installed for restorecon called in container-setup script
RUN INSTALL_PKGS="rsync tar gettext hostname bind-utils policycoreutils mariadb-server" && \
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
dnf clean all && \
mkdir -p /var/lib/mysql/data && chown -R mysql.0 /var/lib/mysql && \
rpm -q --qf '%{version}' mariadb-server | grep -e '10\.0\.' && \
test "$(id mysql)" = "uid=27(mysql) gid=27(mysql) groups=27(mysql)"

# Get prefix path and path to scripts rather than hard-code them in scripts
ENV CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/mysql \
MYSQL_PREFIX=/usr

ADD root /

# this is needed due to issues with squash
# when this directory gets rm'd by the container-setup
# script.
RUN rm -rf /etc/my.cnf.d/*
RUN /usr/libexec/container-setup

VOLUME ["/var/lib/mysql/data"]

USER 27

ENTRYPOINT ["container-entrypoint"]
CMD ["run-mysqld"]
219 changes: 131 additions & 88 deletions mariadb/README.md
Original file line number Diff line number Diff line change
@@ -1,88 +1,131 @@
dockerfiles-fedora-mariadb
==========================

Based on scollier's mysql dockerfile.

This repo contains a recipe for making a Docker container for mariadb
on Fedora.

Setup
-----

Check your Docker version

# docker version

Perform the build

# docker build --rm -t <yourname>/mariadb .

Check the image out.

# docker images

Launching MariaDB
-----------------

### Stand-alone database: ###

# docker run --name=mariadb -d -p 3306:3306 <yourname>/mariadb

This will create the system tables and a database named 'db', with user 'dbuser' and a generated password. To find out what the password is, check the logs:

# docker logs mariadb | grep -E '^USER|^PASS'

### Adjustable configuration ###

Create a data volume container:

# docker run --name=mariadb-data -v /var/lib/mysql \
--entrypoint /bin/echo <yourname>/mariadb "MariaDB data volume"

Now create the persistent container, using the data volume container for storage:

# docker run --name=mariadb --volumes-from=mariadb-data \
-p 3306:3306 -d <yourname>/mariadb

The container will not re-initialise an already-initialised data volume.

Using your MariaDB container
----------------------------

Connecting to mariadb:

# mysql --protocol=tcp db -udbuser -p

Use the password indicated in the 'docker logs' output.

Create a sample table:

\> CREATE TABLE test (name VARCHAR(10), owner VARCHAR(10),
-> species VARCHAR(10), birth DATE, death DATE);

Linking with another container
------------------------------

To arrange for linking with another container, set the USER, PASS, and NAME environment variables when creating the mariadb container. You don't need to expose any ports, as they are available to other containers automatically:

# docker run --name=mariadb --volumes-from=mariadb-data \
-e USER=user -e PASS=mypassword -e NAME=mydb \
-d <yourname>/mariadb

This will create a database named 'mydb', and a user 'user' with the specified password. To link another container to this one, use the --link option to 'docker run':

# docker run --link=mariadb:db -d <yourname>/mydbapp

As we've set the alias for the linked mariadb container to 'db', the 'mydbapp' container will have environment variables set to give it the information it needs:

- DB_PORT will specify the protocol, host, and port
- DB_ENV_NAME will be 'mydb'
- DB_ENV_USER will be 'user'
- DB_ENV_PASS will be 'mypassword'

Using mariadb as a client to an existing mariadb container
----------------------------------------------------------

To run a query against an existing container, using the client from this container image, create a new container linked to the existing one:

# docker run --rm --link=mariadb:db -i -t <yourname>/mariadb sh -c 'mysql -h $DB_PORT_3306_TCP_ADDR -P $DB_PORT_3306_TCP_PORT -u$DB_ENV_USER -p$DB_ENV_PASS'
MariaDB Docker image
====================

This container image includes MariaDB server 10.0 for OpenShift and general usage.

Environment variables and volumes
----------------------------------

The image recognizes the following environment variables that you can set during
initialization by passing `-e VAR=VALUE` to the Docker run command.

| Variable name | Description |
| :--------------------- | ----------------------------------------- |
| `MYSQL_USER` | User name for MySQL account to be created |
| `MYSQL_PASSWORD` | Password for the user account |
| `MYSQL_DATABASE` | Database name |
| `MYSQL_ROOT_PASSWORD` | Password for the root user (optional) |

The following environment variables influence the MySQL configuration file. They are all optional.

| Variable name | Description | Default
| :------------------------------ | ----------------------------------------------------------------- | -------------------------------
| `MYSQL_LOWER_CASE_TABLE_NAMES` | Sets how the table names are stored and compared | 0
| `MYSQL_MAX_CONNECTIONS` | The maximum permitted number of simultaneous client connections | 151
| `MYSQL_MAX_ALLOWED_PACKET` | The maximum size of one packet or any generated/intermediate string | 200M
| `MYSQL_FT_MIN_WORD_LEN` | The minimum length of the word to be included in a FULLTEXT index | 4
| `MYSQL_FT_MAX_WORD_LEN` | The maximum length of the word to be included in a FULLTEXT index | 20
| `MYSQL_AIO` | Controls the `innodb_use_native_aio` setting value in case the native AIO is broken. See http://help.directadmin.com/item.php?id=529 | 1
| `MYSQL_TABLE_OPEN_CACHE` | The number of open tables for all threads | 400
| `MYSQL_KEY_BUFFER_SIZE` | The size of the buffer used for index blocks | 32M (or 10% of available memory)
| `MYSQL_SORT_BUFFER_SIZE` | The size of the buffer used for sorting | 256K
| `MYSQL_READ_BUFFER_SIZE` | The size of the buffer used for a sequential scan | 8M (or 5% of available memory)
| `MYSQL_INNODB_BUFFER_POOL_SIZE`| The size of the buffer pool where InnoDB caches table and index data | 32M (or 50% of available memory)
| `MYSQL_INNODB_LOG_FILE_SIZE` | The size of each log file in a log group | 8M (or 15% of available available)
| `MYSQL_INNODB_LOG_BUFFER_SIZE` | The size of the buffer that InnoDB uses to write to the log files on disk | 8M (or 15% of available memory)
| `MYSQL_DEFAULTS_FILE` | Point to an alternative configuration file | /etc/my.cnf
| `MYSQL_BINLOG_FORMAT` | Set sets the binlog format, supported values are `row` and `statement` | statement

You can also set the following mount points by passing the `-v /host:/container` flag to Docker.

| Volume mount point | Description |
| :----------------------- | -------------------- |
| `/var/lib/mysql/data` | MySQL data directory |

**Notice: When mouting a directory from the host into the container, ensure that the mounted
directory has the appropriate permissions and that the owner and group of the directory
matches the user UID which is running inside the container.**

Usage
---------------------------------

For this, we will assume that you are using the `fedora/mariadb` image.
If you want to set only the mandatory environment variables and not store
the database in a host directory, execute the following command:

```
$ docker run -d --name mariadb_database -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e MYSQL_DATABASE=db -p 3306:3306 fedora/mariadb
```

This will create a container named `mariadb_database` running MySQL with database
`db` and user with credentials `user:pass`. Port 3306 will be exposed and mapped
to the host. If you want your database to be persistent across container executions,
also add a `-v /host/db/path:/var/lib/mysql/data` argument. This will be the MySQL
data directory.

If the database directory is not initialized, the entrypoint script will first
run [`mysql_install_db`](https://dev.mysql.com/doc/refman/5.6/en/mysql-install-db.html)
and setup necessary database users and passwords. After the database is initialized,
or if it was already present, `mysqld` is executed and will run as PID 1. You can
stop the detached container by running `docker stop mariadb_database`.


MariaDB auto-tuning
-------------------

When the MySQL image is run with the `--memory` parameter set and you didn't
specify value for some parameters, their values will be automatically
calculated based on the available memory.

| Variable name | Configuration parameter | Relative value
| :-------------------------------| ------------------------- | --------------
| `MYSQL_KEY_BUFFER_SIZE` | `key_buffer_size` | 10%
| `MYSQL_READ_BUFFER_SIZE` | `read_buffer_size` | 5%
| `MYSQL_INNODB_BUFFER_POOL_SIZE` | `innodb_buffer_pool_size` | 50%
| `MYSQL_INNODB_LOG_FILE_SIZE` | `innodb_log_file_size` | 15%
| `MYSQL_INNODB_LOG_BUFFER_SIZE` | `innodb_log_buffer_size` | 15%


MySQL root user
---------------------------------
The root user has no password set by default, only allowing local connections.
You can set it by setting the `MYSQL_ROOT_PASSWORD` environment variable. This
will allow you to login to the root account remotely. Local connections will
still not require a password.

To disable remote root access, simply unset `MYSQL_ROOT_PASSWORD` and restart
the container.


Changing passwords
------------------

Since passwords are part of the image configuration, the only supported method
to change passwords for the database user (`MYSQL_USER`) and root user is by
changing the environment variables `MYSQL_PASSWORD` and `MYSQL_ROOT_PASSWORD`,
respectively.

Changing database passwords through SQL statements or any way other than through
the environment variables aforementioned will cause a mismatch between the
values stored in the variables and the actual passwords. Whenever a database
container starts it will reset the passwords to the values stored in the
environment variables.

Default my.cnf file
-------------------
With environment variables we are able to customize a lot of different parameters
or configurations for the mysql bootstrap configurations. If you'd prefer to use
your own configuration file, you can override the `MYSQL_DEFAULTS_FILE` env
variable with the full path of the file you wish to use. For example, the default
location is `/etc/my.cnf` but you can change it to `/etc/mysql/my.cnf` by setting
`MYSQL_DEFAULTS_FILE=/etc/mysql/my.cnf`

Changing the replication binlog_format
--------------------------------------
Some applications may wish to use `row` binlog_formats (for example, those built
with change-data-capture in mind). The default replication/binlog format is
`statement` but to change it you can set the `MYSQL_BINLOG_FORMAT` environment
variable. For example `MYSQL_BINLOG_FORMAT=row`. Now when you run the database
with `master` replication turned on (ie, set the Docker/container `cmd` to be
`run-mysqld-master`) the binlog will emit the actual data for the rows that change
as opposed to the statements (ie, DML like insert...) that caused the change.
10 changes: 10 additions & 0 deletions mariadb/root/etc/my.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[mysqld]

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links = 0

# http://www.percona.com/blog/2008/05/31/dns-achilles-heel-mysql-installation/
skip_name_resolve

!includedir /etc/my.cnf.d

92 changes: 92 additions & 0 deletions mariadb/root/usr/bin/cgroup-limits
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/python3

"""
Script for parsing cgroup information
This script will read some limits from the cgroup system and parse
them, printing out "VARIABLE=VALUE" on each line for every limit that is
successfully read. Output of this script can be directly fed into
bash's export command. Recommended usage from a bash script:
set -o errexit
export_vars=$(cgroup-limits) ; export $export_vars
Variables currently supported:
MAX_MEMORY_LIMIT_IN_BYTES
Maximum possible limit MEMORY_LIMIT_IN_BYTES can have. This is
currently constant value of 9223372036854775807.
MEMORY_LIMIT_IN_BYTES
Maximum amount of user memory in bytes. If this value is set
to the same value as MAX_MEMORY_LIMIT_IN_BYTES, it means that
there is no limit set. The value is taken from
/sys/fs/cgroup/memory/memory.limit_in_bytes
NUMBER_OF_CORES
Number of detected CPU cores that can be used. This value is
calculated from /sys/fs/cgroup/cpuset/cpuset.cpus
NO_MEMORY_LIMIT
Set to "true" if MEMORY_LIMIT_IN_BYTES is so high that the caller
can act as if no memory limit was set. Undefined otherwise.
"""

from __future__ import print_function
import sys


def _read_file(path):
try:
with open(path, 'r') as f:
return f.read().strip()
except IOError:
return None


def get_memory_limit():
"""
Read memory limit, in bytes.
"""

limit = _read_file('/sys/fs/cgroup/memory/memory.limit_in_bytes')
if limit is None or not limit.isdigit():
print("Warning: Can't detect memory limit from cgroups",
file=sys.stderr)
return None
return int(limit)


def get_number_of_cores():
"""
Read number of CPU cores.
"""

core_count = 0

line = _read_file('/sys/fs/cgroup/cpuset/cpuset.cpus')
if line is None:
print("Warning: Can't detect number of CPU cores from cgroups",
file=sys.stderr)
return None

for group in line.split(','):
core_ids = list(map(int, group.split('-')))
if len(core_ids) == 2:
core_count += core_ids[1] - core_ids[0] + 1
else:
core_count += 1

return core_count


if __name__ == "__main__":
env_vars = {
"MAX_MEMORY_LIMIT_IN_BYTES": 9223372036854775807,
"MEMORY_LIMIT_IN_BYTES": get_memory_limit(),
"NUMBER_OF_CORES": get_number_of_cores()
}

env_vars = {k: v for k, v in env_vars.items() if v is not None}

if env_vars.get("MEMORY_LIMIT_IN_BYTES", 0) >= 92233720368547:
env_vars["NO_MEMORY_LIMIT"] = "true"

for key, value in env_vars.items():
print("{0}={1}".format(key, value))
2 changes: 2 additions & 0 deletions mariadb/root/usr/bin/container-entrypoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
exec "$@"
1 change: 1 addition & 0 deletions mariadb/root/usr/bin/mysqld-master
1 change: 1 addition & 0 deletions mariadb/root/usr/bin/mysqld-slave
Loading

0 comments on commit 4ed1619

Please sign in to comment.