Create database on docker-compose startup
There is also an option to provide an init file for mysql
container which will be applied each time a container is created.
database:
image: mysql:5.7
ports:
- "33061:3306"
command: --init-file /data/application/init.sql
volumes:
- ./init.sql:/data/application/init.sql
environment:
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: homestead
MYSQL_USER: root
MYSQL_PASSWORD: secret
Such file (init.sql
) could contain your initial database structure and data - for example:
CREATE DATABASE IF NOT EXISTS dev;
CREATE DATABASE IF NOT EXISTS test;
USE dev;
CREATE TABLE IF NOT EXISTS (...);
The database is probably already initialized and the configuration is stored in /var/lib/mysql
. Since you defined a volume for that location the config will survive a restart. The MySQL image will not reconfigure the database over and over again, it only does this once.
volumes:
- dbdata:/var/lib/mysql
If your database is empty you can reset the database by performing docker-compose down -v
where the -v
removes the volumes defined in the volume section. See https://docs.docker.com/compose/reference/down/. On the next docker-compose up
the MySQL image will start fresh and will initialize the database with the configuration you've provided throug the environment section.
Answering your question ...
One thing I use to do when building a new docker container is understand what the image I pull from does when is builded.
In your docker-compose.yml tou have this
# The Database
database:
image: mysql:5.7
This is the image you pull from, "mysql:5.7"
Dockerhub is a repository where you can find info of this images.
Do a google search "mysql:5.7 dockerhub"
First result is https://hub.docker.com/_/mysql/
There you have your image 5.7, if you click on 5.7 you have this
https://github.com/docker-library/mysql/blob/607b2a65aa76adf495730b9f7e6f28f146a9f95f/5.7/Dockerfile
Which is the Dockerfile from the image, you can have a look at interesting things that happen when building the image.
One of this is ENTRYPOINT ["docker-entrypoint.sh"]
This is the file that got executed when image is ready
I you go one level up in the repo you will see this file
https://github.com/docker-library/mysql/tree/607b2a65aa76adf495730b9f7e6f28f146a9f95f/5.7
The you can see your environment variables being used to create new database etc...
file_env 'MYSQL_DATABASE'
if [ "$MYSQL_DATABASE" ]; then
echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
mysql+=( "$MYSQL_DATABASE" )
fi
The official MySQL docker image added support for init scripts in their base image. They document the feature under their "Initializing a fresh instance" on the Docker Hub page.
Here are the steps I took to solve creating multiple database and users in the MySQL docker image:
- Create the init file (the Docker image recognizes .sh, .sql, and .sql.gz files) named
setup.sql
in the local directory named.docker
- Place the commands inside
setup.sql
(see below for an example) - Mount the setup script into the directory
f
within thedocker-compose.yaml
file (see below for an example) - Run
docker-compose up -d
and MySQL will run the code insidesetup.sql
Note: the script will run files alphabetically, so keep that in mind.
Example docker-compose.yaml
version: "3.5"
services:
mysql:
image: mysql
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: SomeRootPassword1!
MYSQL_USER: someuser
MYSQL_PASSWORD: Password1!
MYSQL_DATABASE: somedatabase
volumes:
- .docker/setup.sql:/docker-entrypoint-initdb.d/setup.sql
- db_data:/var/lib/mysql
volumes:
db_data:
Example setup.sql
-- create the databases
CREATE DATABASE IF NOT EXISTS projectone;
-- create the users for each database
CREATE USER 'projectoneuser'@'%' IDENTIFIED BY 'somepassword';
GRANT CREATE, ALTER, INDEX, LOCK TABLES, REFERENCES, UPDATE, DELETE, DROP, SELECT, INSERT ON `projectone`.* TO 'projectoneuser'@'%';
FLUSH PRIVILEGES;