bash command for runniung multiple commands in docker container - mysql

I'm trying to set up a database with a table inside a docker container. For correct working of DB, I need to run the following command:
--default-authentication-plugin=mysql_native_password
ps: I don't understand what this command exactly is for, but it prevents some strange logs by setting the DB up.
For set up, I use docker-compose as follow:
db:
image: mysql
command: >
bash -c "--init-file /pictureapi_mydb_response.sql
&& --default-authentication-plugin=mysql_native_password"
volumes:
- ./pictureapi_mydb_response.sql:/pictureapi_mydb_response.sql
restart: always
ports:
- 3307:3306
environment:
MYSQL_ROOT_PASSWORD: ${DB_MYSQL_PASS}
source
I'm getting the following errors:
bash: --: invalid option
db_1 | Usage: bash [GNU long option] [option] ...
db_1 | bash [GNU long option] [option] script-file ...
db_1 | GNU long options:
db_1 | --debug
db_1 | --debugger\
How should I actually run two or more commands if "bash" instruction doesn't work?

The Docker Hub mysql image is configured so that, if the command: starts with -, the entire command is assumed to be mysqld startup options. It's not actually "a command", and you can't use bash to run it. If you need multiple startup options, just combine them together into a single command::
command: --init-file /pictureapi_mydb_response.sql --default-authentication-plugin=mysql_native_password
When you launch a Docker container, its "entrypoint" and "command" parts are combined into a single command, so the command is passed as additional arguments to the entrypoint if both are present. The most common pattern is that the command is a complete executable command on its own, but there's an alternate pattern where the entrypoint is (or provides) the main command to run and the command just provides extra options.
The Docker Hub mysql container has a rather involved entrypoint script, but it eventually concludes with this logic:
# if command starts with an option, prepend mysqld
if [ "${1:0:1}" = '-' ]; then
set -- mysqld "$#"
fi
That is, if you run a container with
command: --an-option-starting-with-minus
the actual command the container runs is mysqld --an-option-starting-with-minus. So if you have multiple mysqld options you need to set, you can just pass them as the "command" and they'll get handled appropriately.

Related

docker-compose volume question and error --initialize specified but the data directory has files in it. Aborting

I had a spring-boot project that used mysql docker-image so I didn't need to download the mysql benchwork. For other reasons I had to start over so I created a new project that uses the same mysql docker image I previously used.
My docker-compose.yml mysql service looks like this
version: "3.7"
services:
db:
image: mysql:5.7
command: --lower_case_table_names=1
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: farming_db
MYSQL_USER: root
MYSQL_PASSWORD: root
restart: always
volumes:
- "./database/farming_db/:/var/lib/mysql" #local
- farming_db:/var/lib/mysql/data #docker
ports:
- "3306:3306"
container_name: farming_mysql
networks:
- backend-network
When I run
docker-compose up
This is the error :
Attaching to farming_mysql, farming_server_springboot_1
farming_mysql | 2021-03-18 07:03:20+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.33-1debian10 started.
farming_mysql | 2021-03-18 07:03:20+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
farming_mysql | 2021-03-18 07:03:20+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.33-1debian10 started.
farming_mysql | 2021-03-18 07:03:21+00:00 [Note] [Entrypoint]: Initializing database files
farming_mysql | 2021-03-18T07:03:21.058436Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server opti
on (see documentation for more details).
farming_mysql | 2021-03-18T07:03:21.063630Z 0 [ERROR] --initialize specified but the data directory has files in it. Aborting.
farming_mysql | 2021-03-18T07:03:21.063710Z 0 [ERROR] Aborting
farming_mysql |
farming_mysql exited with code 1
springboot_1 |
I understood that my directory is not empty. I am trying to use "./database/farming_db/:/var/lib/mysql" and "farming_db:/var/lib/mysql/data" both as the volume directories. I think the problem is with the latter directory because the prior directory is empty. I'm having a problem deleting the contents in the latter directory because I don't know how to access it.
So this is what I've tried :
I deleted all the containers and then deleted all the volumes.docker volume prune but didn't work.
I searched that I could do rm -rf /usr/local/var/mysql but I don't know where I can execute this command since the container won't run properly at all.
I deleted the mysql image and just ran docker-compose up again. This seems to pull a new mysql image from somewhere? but I still get the same error. I guess volume directory has nothing do with the docker image itself.
I deleted the "- farming_db:/var/lib/mysql/data #docker" line from the docker-compose. But the same error is still occuring!
I'm using Windows10.
My question :
How can I access the directory? I don't know where to use the rm -rf command.
Why does this error still occur even when I erase "- farming_db:/var/lib/mysql/data #docker" from the docker-compose?
And also could anyone explain what I am doing? I'm new to docker and I don't really understand these volume problems.
Run docker system prune --volumes
This frees up the memory by removing all unused containers. Sometimes, the mentioned issue can occur due to memory limitations
Generally I emptied the volume's data directory and just changed the versions of the MySQL.
So in steps:
empty volume directory content
modify docker-compose.yml mysql version from 5.7 to 5.7.16
This line indicate that mysql container is storing the data inside a directory database in the same directory than your docker-compose.yml:
volumes:
- "./database/farming_db/:/var/lib/mysql" #local
This kind of volume isn't managed by Docker, it's just a directory in your filesystem, this is why docker volume prune doesn't work. I know that, because it starts with a "path" relative or absolute.
The other volume, farming_db, are managed by Docker. I know that because it starts with a simple name. This kinds of volume are managed by Docker and are removed with prune.
So, answering:
In the same directory than your docker-compose.yml you can remove that database folder.
Because the first volume, the one with /var/lib/mysql still exists. MySQL keeps all files inside this directory and any other child directory are a database.
You're just trying to put a container running and docker-compose hides a lot of details.
This is just a detail, but MYSQL_USER should be different than root.
You can let Docker manage the entire volume, creating a single volume to hold all data, in this case I named it as mysql_data:
volumes:
- mysql_data:/var/lib/mysql
Or, you can explore a bit more the docker run equivalent command to get used with it:
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=root \
-e MYSQL_DATABASE=farming_db \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypass \
-v mysql_data:/var/lib/mysql \
-p 3306:3306 \
mysql:5.7
As vencedor's answer, it worked for me. If anyone need stay with mysql 5.7, you can add these lines to your db service in docker-compose.yml:
- /etc/group:/etc/group:ro
- /etc/passwd:/etc/passwd:ro
user: "1000:1000"
I used docker-compose to run mysql image and encountered the error.
I use the following configuration to set volume.
- ./mysql/data:/var/lib/mysql/data
Then I changed it to the following and the error was solved.
- ./mysql:/var/lib/mysql

Best way to initialize DB script while building docker image

I am building a docker machine using the image "mysql". I have some setup script to run for the first time the machine is built. This setup script will create some database and dabase users with specified permmissions.
Following are the minimized version of my files..
pcdb1.entrypoint.sh
#!/bin/sh
mysql -uroot -p'pass123' -e 'show databases MYENTRYDB;'
Dockerfile
FROM mysql:5.7
COPY ./pcdb1.entrypoint.sh /
ENTRYPOINT ["/pcdb1.entrypoint.sh"];
I am getting the following error in the log
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
pcdb1 exited with code 1
What I understood is, my script is trying to run before mysql is started. But I am not sure how to do it properly. Can I get a suggestion?
EDIT: 20181007
I have found the way you mentioned in question--initialize DB while building docker image. But with a little difference, the way I found seems like initializing DB while running a container from image, although the initializing script was specified while building the image.
According to the official information about mysql:5.7, there is paragraph named "Initializing a fresh instance". We could just add a initializing script into the directory /docker-entrypoint-initdb.d, the default ENTRYPOINT and CMD of image mysql:5.7 would execute it after database start-up.
For example:
FROM mysql:5.7
COPY init-database.sql /docker-entrypoint-initdb.d/
content of init-database.sql:
create database light;
create user 'light'#'%' identified by 'abc123';
grant all privileges on light.* to 'light'#'%' identified by 'abc123';
grant all privileges on light.* to 'light'#'localhost' identified by 'abc123';
Build new image:
docker build -t light/mysql:5.7 .
Run a container:
docker run -tid --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD='abc123' light/mysql:5.7
Examine initialization:
docker run -ti mysql /bin/bash
root#25e73d40c4ff:/# mysql -uroot -p
Enter password: (abc123)
Welcome to the MySQL monitor.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
All work well.
Former answer below.
How to start mysql damon in container?
First of all, you are right on "trying to run before mysql is started" part. But still, there is a missing on "how MySQL starts exactly". If you execute docker history mysql:5.7 --no-trunc, you could see three important records among output like below:
/bin/sh -c #(nop) CMD ["mysqld"]
/bin/sh -c #(nop) ENTRYPOINT ["docker-entrypoint.sh"]
/bin/sh -c ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh
So far we should know when we start a mysql container with command below, the exact initial command in container is docker-entrypoint.sh mysqld.
docker run -tid -e MYSQL_ROOT_PASSWORD='abc123' mysql:5.7
How to initiate mysql in container?
Secondly, let's now have a check on docker-entrypoint.sh script.
There is a specific line like below, just at roughly middle position of this script, which means to start mysql daemon.
mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
After starting mysql, we could see lots of initiating statements in docker-entrypoint.sh script. Such as creating root user with password or not, granting privileges to root, creating database declared by users with MYSQL_DATABASE env and so on.
Now here are solutions offered for you.
Self-defining the docker-entrypoint.sh script.
In this way, you could whatever you want which is legal in mysql.
Get the whole entrypoint.sh script on your host.
Add your self-definition of mysql in the script, make your
self-defining content at the bottom of this script. I assume you
don't want to mess it with original content.
Build a new mysql image for your own with command and Dockerfile below.
command: docker build -t mysql:self .
Dockerfile:
FROM mysql:5.7
COPY /path/to/your-entrypoint.sh /
ENTRYPOINT ["/your-entrypoint.sh"]
CMD ["mysqld"]
If your don't want a new image, there is another way to change
ENTRYPOINT when you run a container. But still, you should make your own script available in container.
docker run -tid -v /path/to/your-entrypoint.sh:/entrypoint.sh -p 3306:3306 -e MYSQL_ROOT_PASSWORD='abc123' mysql:5.7
Using default ENVs provided by mysql:5.7
In this way, there is a limit, especially on "specified permmissions" you mentioned.
The ENVs you need are: MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD.
The command should like this:
docker run -tid -e MYSQL_ROOT_PASSWORD='abc123' -e MYSQL_DATABASE='apps' -e MYSQL_USER='light' -e MYSQL_PASSWORD='abc123' mysql:5.7
This means that the database apps and user light will be created automatically, and the user light will be granted superuser permissions for the database apps.
More reference here on hub.docker.com.

how to start multi instances in one mysql docker container

I want to deploy data slot to the distributed mysql databases via middleware,need one mysql docker container running two instances with different port, eg. 3306 and 3316.
tried many ways, such as:
Add mysql_3316.sh:
#!/bin/bash
/entrypoint.sh --defaults-file=/etc/mysql/my_3316.cnf
in the rc.local:
#!/bin/sh -e
/usr/local/bin/mysql_3316.sh || exit 1
exit 0
and modified the Dockerfile like below,
RUN touch /etc/mysql/my_3316.cnf
COPY mysql_3316.sh /usr/local/bin/mysql_3316.sh
RUN chmod +x /usr/local/bin/mysql_3316.sh
COPY rc.local /etc/rc.local
RUN chmod +x /etc/rc.local
RUN chown root:root /etc/rc.local
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 3316
CMD ["mysqld"]
it doesn't work while the mysql container comes up, but the 3316 mysql
port instance works by run the /entrypoint.sh --defaults-file=/etc/mysql/my_3316.cnf shell line manually.
tried the init.d ,
RUN touch /etc/mysql/my_3316.cnf
COPY mysql_3316.sh /etc/init.d/mysql_3316
RUN chmod +x /etc/init.d/mysql_3316
RUN update-rc.d mysql_3316 defaults 99
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 3316
CMD ["mysqld"]
doesn't work too.
tried the crontab,
#reboot /usr/local/bin/mysql_3316.sh
#Don't remove the empty line at the end of this file. It is required to run the cron job
and the Dockerfile as that,
COPY mysql_3316.sh /usr/local/bin/mysql_3316.sh
RUN chmod +x /usr/local/bin/mysql_3316.sh
ADD crontab /etc/cron.d/docker-cron
RUN chmod +x /etc/cron.d/docker-cron
RUN crontab /etc/cron.d/docker-cron
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 3316
CMD ["mysqld"]
doesn't work third.
It's been spent much on this key, almost give up...
Any kindly suggestion are welcomed please.
The docker-compose.yml for mysql right here:
services:
mysql:
image: mysql:latest
container_name: mysql
hostname: mysql
restart: unless-stopped
networks:
dockernet:
ipv4_address: 172.18.0.5
ports:
- 3306:3306
- 3316:3316
volumes:
- /Docker/mysql/:/var/lib/mysql/
- ./docker/mysql/mysql/my.cnf:/etc/mysql/my.cnf
- ./docker/mysql/mysql/my_3316.cnf:/etc/mysql/my_3316.cnf
- ./docker/mysql/mysql/logs/:/var/log/mysql/
- ./docker/mysql/mysql/init/:/docker-entrypoint-initdb.d/
entrypoint: ['/entrypoint.sh', '--default-authentication-plugin=mysql_native_password']
Normally you do NOT want to run more than one process in the same container. Despite your title I really think that what you are looking for is to start two containers, both from a MySQL image.
You should not need to change any startup scripts, Dockerfile or anything else to start up similar containers bound to different ports.
Remember that the EXPOSE command only exposes the ports to different containers, not to the outside world.
To access the port you need to use the -p flag with your docker run: https://docs.docker.com/engine/reference/run/#expose-incoming-ports
You can use the same docker image from the same Dockerfile. Just give different -p parameter when you run.
Edit:
You added your docker-compose.yml after my initial response. Using docker-compose will make my advice about -p obsolete, and you should use the ports: section of the docker-compose.yml to vary the port numbers instead.
This answer, however, might not be what you are looking for because based on your comment I think I do not fully understand your use case here.
Use the stock mysql container and just run:
docker run -p3306:3306 --name mysql1 mysql
docker run -p3316:3306 --name mysql2 mysql
# plus appropriate -d -e ... -v ... as needed on both commands
Don't try to build your own image and definitely don't try to run two servers with expected different lifetimes in a single container.

increase max_allowed_packet size in mysql docker

We are using Docker for mysql, We are facing the below error while running
Packet for query is too large (12884616 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.; nested exception is com.mysql.jdbc.PacketTooBigException: Packet for query is too large (12884616 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.
now we need to increase max_allowed_packet size in mysql configuration, Can anyone help me on docker command to increase max_allowed_packet.
As an argument to the container command:
docker run -it -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql:5.7 --max-allowed-packet=67108864
See "Configuration without a cnf file" at https://hub.docker.com/_/mysql/, copied here for posterity:
Configuration without a cnf file Many configuration options can be
passed as flags to mysqld. This will give you the flexibility to
customize the container without needing a cnf file. For example, if
you want to change the default encoding and collation for all tables
to use UTF-8 (utf8mb4) just run the following:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
If you would like to see a complete list of available options, just run:
$ docker run -it --rm mysql:tag --verbose --help
When using docker-compose (as asked in the comments), add a command key with the arguments:
version: "3"
services:
data:
image: "mysql:5.7.20"
command: --max_allowed_packet=32505856 # Set max_allowed_packet to 256M (or any other value)
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=db
- MYSQL_USER=user
- MYSQL_PASSWORD=user_password
When using docker-compose (as asked in the comments), add a command key with the arguments, for example:
version: "3"
services:
data:
image: "mysql:5.7.20"
# Set max_allowed_packet to 256M (or any other value)
command: --max_allowed_packet=32505856
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=db
- MYSQL_USER=user
- MYSQL_PASSWORD=user_password
Whilst this works for the MySQL docker images, it may not work for all is it overwrites the default command.
More info: Docker Compose - Command
I think you should modify it in your Dockerfile like this :
RUN sed -ire 's/max_allowed_packet.*=.*/max_allowed_packet = YOURVALUE/g' /etc/mysql/my.cnf

How can I initialize a MySQL database with schema in a Docker container?

I am trying to create a container with a MySQL database and add a schema to these database.
My current Dockerfile is:
FROM mysql
MAINTAINER (me) <email>
# Copy the database schema to the /data directory
COPY files/epcis_schema.sql /data/epcis_schema.sql
# Change the working directory
WORKDIR data
CMD mysql -u $MYSQL_USER -p $MYSQL_PASSWORD $MYSQL_DATABASE < epcis_schema.sql
In order to create the container I am following the documentation provided on Docker and executing this command:
docker run --name ${CONTAINER_NAME} -e MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} -e MYSQL_USER=${DB_USER} -e MYSQL_PASSWORD=${DB_USER_PASSWORD} -e MYSQL_DATABASE=${DB_NAME} -d mvpgomes/epcisdb
But when I execute this command the Container is not created and in the Container status it is possible to see that the CMD was not executed successfully, in fact only the mysql command is executed.
Anyway, is there a way to initialize the database with the schema or do I need to perform these operations manually?
I had this same issue where I wanted to initialize my MySQL Docker instance's schema, but I ran into difficulty getting this working after doing some Googling and following others' examples. Here's how I solved it.
1) Dump your MySQL schema to a file.
mysqldump -h <your_mysql_host> -u <user_name> -p --no-data <schema_name> > schema.sql
2) Use the ADD command to add your schema file to the /docker-entrypoint-initdb.d directory in the Docker container. The docker-entrypoint.sh file will run any files in this directory ending with ".sql" against the MySQL database.
Dockerfile:
FROM mysql:5.7.15
MAINTAINER me
ENV MYSQL_DATABASE=<schema_name> \
MYSQL_ROOT_PASSWORD=<password>
ADD schema.sql /docker-entrypoint-initdb.d
EXPOSE 3306
3) Start up the Docker MySQL instance.
docker-compose build
docker-compose up
Thanks to Setting up MySQL and importing dump within Dockerfile for clueing me in on the docker-entrypoint.sh and the fact that it runs both SQL and shell scripts!
I am sorry for this super long answer, but, you have a little way to go to get where you want. I will say that normally you wouldn't put the storage for the database in the same container as the database itself, you would either mount a host volume so that the data persists on the docker host, or, perhaps a container could be used to hold the data (/var/lib/mysql). Also, I am new to mysql, so, this might not be super efficient. That said...
I think there may be a few issues here. The Dockerfile is used to create an image. You need to execute the build step. At a minimum, from the directory that contains the Dockerfile you would do something like :
docker build .
The Dockerfile describes the image to create. I don't know much about mysql (I am a postgres fanboy), but, I did a search around the interwebs for 'how do i initialize a mysql docker container'. First I created a new directory to work in, I called it mdir, then I created a files directory which I deposited a epcis_schema.sql file which creates a database and a single table:
create database test;
use test;
CREATE TABLE testtab
(
id INTEGER AUTO_INCREMENT,
name TEXT,
PRIMARY KEY (id)
) COMMENT='this is my test table';
Then I created a script called init_db in the files directory:
#!/bin/bash
# Initialize MySQL database.
# ADD this file into the container via Dockerfile.
# Assuming you specify a VOLUME ["/var/lib/mysql"] or `-v /var/lib/mysql` on the `docker run` command…
# Once built, do e.g. `docker run your_image /path/to/docker-mysql-initialize.sh`
# Again, make sure MySQL is persisting data outside the container for this to have any effect.
set -e
set -x
mysql_install_db
# Start the MySQL daemon in the background.
/usr/sbin/mysqld &
mysql_pid=$!
until mysqladmin ping >/dev/null 2>&1; do
echo -n "."; sleep 0.2
done
# Permit root login without password from outside container.
mysql -e "GRANT ALL ON *.* TO root#'%' IDENTIFIED BY '' WITH GRANT OPTION"
# create the default database from the ADDed file.
mysql < /tmp/epcis_schema.sql
# Tell the MySQL daemon to shutdown.
mysqladmin shutdown
# Wait for the MySQL daemon to exit.
wait $mysql_pid
# create a tar file with the database as it currently exists
tar czvf default_mysql.tar.gz /var/lib/mysql
# the tarfile contains the initialized state of the database.
# when the container is started, if the database is empty (/var/lib/mysql)
# then it is unpacked from default_mysql.tar.gz from
# the ENTRYPOINT /tmp/run_db script
(most of this script was lifted from here: https://gist.github.com/pda/9697520)
Here is the files/run_db script I created:
# start db
set -e
set -x
# first, if the /var/lib/mysql directory is empty, unpack it from our predefined db
[ "$(ls -A /var/lib/mysql)" ] && echo "Running with existing database in /var/lib/mysql" || ( echo 'Populate initial db'; tar xpzvf default_mysql.tar.gz )
/usr/sbin/mysqld
Finally, the Dockerfile to bind them all:
FROM mysql
MAINTAINER (me) <email>
# Copy the database schema to the /data directory
ADD files/run_db files/init_db files/epcis_schema.sql /tmp/
# init_db will create the default
# database from epcis_schema.sql, then
# stop mysqld, and finally copy the /var/lib/mysql directory
# to default_mysql_db.tar.gz
RUN /tmp/init_db
# run_db starts mysqld, but first it checks
# to see if the /var/lib/mysql directory is empty, if
# it is it is seeded with default_mysql_db.tar.gz before
# the mysql is fired up
ENTRYPOINT "/tmp/run_db"
So, I cd'ed to my mdir directory (which has the Dockerfile along with the files directory). I then run the command:
docker build --no-cache .
You should see output like this:
Sending build context to Docker daemon 7.168 kB
Sending build context to Docker daemon
Step 0 : FROM mysql
---> 461d07d927e6
Step 1 : MAINTAINER (me) <email>
---> Running in 963e8de55299
---> 2fd67c825c34
Removing intermediate container 963e8de55299
Step 2 : ADD files/run_db files/init_db files/epcis_schema.sql /tmp/
---> 81871189374b
Removing intermediate container 3221afd8695a
Step 3 : RUN /tmp/init_db
---> Running in 8dbdf74b2a79
+ mysql_install_db
2015-03-19 16:40:39 12 [Note] InnoDB: Using atomics to ref count buffer pool pages
...
/var/lib/mysql/ib_logfile0
---> 885ec2f1a7d5
Removing intermediate container 8dbdf74b2a79
Step 4 : ENTRYPOINT "/tmp/run_db"
---> Running in 717ed52ba665
---> 7f6d5215fe8d
Removing intermediate container 717ed52ba665
Successfully built 7f6d5215fe8d
You now have an image '7f6d5215fe8d'. I could run this image:
docker run -d 7f6d5215fe8d
and the image starts, I see an instance string:
4b377ac7397ff5880bc9218abe6d7eadd49505d50efb5063d6fab796ee157bd3
I could then 'stop' it, and restart it.
docker stop 4b377
docker start 4b377
If you look at the logs, the first line will contain:
docker logs 4b377
Populate initial db
var/lib/mysql/
...
Then, at the end of the logs:
Running with existing database in /var/lib/mysql
These are the messages from the /tmp/run_db script, the first one indicates that the database was unpacked from the saved (initial) version, the second one indicates that the database was already there, so the existing copy was used.
Here is a ls -lR of the directory structure I describe above. Note that the init_db and run_db are scripts with the execute bit set:
gregs-air:~ gfausak$ ls -Rl mdir
total 8
-rw-r--r-- 1 gfausak wheel 534 Mar 19 11:13 Dockerfile
drwxr-xr-x 5 gfausak staff 170 Mar 19 11:24 files
mdir/files:
total 24
-rw-r--r-- 1 gfausak staff 126 Mar 19 11:14 epcis_schema.sql
-rwxr-xr-x 1 gfausak staff 1226 Mar 19 11:16 init_db
-rwxr-xr-x 1 gfausak staff 284 Mar 19 11:23 run_db
Another way based on a merge of serveral responses here before :
docker-compose file :
version: "3"
services:
db:
container_name: db
image: mysql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=mysql
- MYSQL_DATABASE=db
volumes:
- /home/user/db/mysql/data:/var/lib/mysql
- /home/user/db/mysql/init:/docker-entrypoint-initdb.d/:ro
where /home/user.. is a shared folder on the host
And in the /home/user/db/mysql/init folder .. just drop one sql file, with any name, for example init.sql containing :
CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'#'%' IDENTIFIED BY 'mysql';
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'#'localhost' IDENTIFIED BY 'mysql';
USE mydb
CREATE TABLE CONTACTS (
[ ... ]
);
INSERT INTO CONTACTS VALUES ...
[ ... ]
According to the official mysql documentation, you can put more than one sql file in the docker-entrypoint-initdb.d, they are executed in the alphabetical order
The other simple way, use docker-compose with the following lines:
mysql:
from: mysql:5.7
volumes:
- ./database:/tmp/database
command: mysqld --init-file="/tmp/database/install_db.sql"
Put your database schema into the ./database/install_db.sql. Every time when you build up your container, the install_db.sql will be executed.
I've tried Greg's answer with zero success, I must have done something wrong since my database had no data after all the steps: I was using MariaDB's latest image, just in case.
Then I decided to read the entrypoint for the official MariaDB image, and used that to generate a simple docker-compose file:
database:
image: mariadb
ports:
- 3306:3306
expose:
- 3306
volumes:
- ./docker/mariadb/data:/var/lib/mysql:rw
- ./database/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
Now I'm able to persist my data AND generate a database with my own schema!
After Aug. 4, 2015, if you are using the official mysql Docker image, you can just ADD/COPY a file into the /docker-entrypoint-initdb.d/ directory and it will run with the container is initialized. See github: https://github.com/docker-library/mysql/commit/14f165596ea8808dfeb2131f092aabe61c967225 if you want to implement it on other container images
The easiest solution is to use tutum/mysql
Step1
docker pull tutum/mysql:5.5
Step2
docker run -d -p 3306:3306 -v /tmp:/tmp -e STARTUP_SQL="/tmp/to_be_imported.mysql" tutum/mysql:5.5
Step3
Get above CONTAINER_ID and then execute command docker logs to see the generated password information.
docker logs #<CONTAINER_ID>
Since I struggled with this problem recently, I'm adding a docker-compose file that really helped me:
version: '3.5'
services:
db:
image: mysql:5.7
container_name: db-container
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- "./scripts/schema.sql:/docker-entrypoint-initdb.d/1.sql"
- "./scripts/data.sql:/docker-entrypoint-initdb.d/2.sql"
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: test
MYSQL_USER: test-user
MYSQL_PASSWORD: password
ports:
- '3306:3306'
healthcheck:
test: "/usr/bin/mysql --user=root --password=password --execute \"SHOW DATABASES;\""
interval: 2s
timeout: 20s
retries: 10
You just need to create a scripts folder in the same location as the docker-compose.yml file above.
The scripts folder will have 2 files:
schema.sql: DDL scripts (create table...etc)
data.sql: Insert statements that you want to be executed right after schema creation.
After this, you can run the command below to erase any previous database info (for a fresh start):
docker-compose rm -v -f db && docker-compose up
For the ones not wanting to create an entrypoint script like me, you actually can start mysqld at build-time and then execute the mysql commands in your Dockerfile like so:
RUN mysqld_safe & until mysqladmin ping; do sleep 1; done && \
mysql -e "CREATE DATABASE somedb;" && \
mysql -e "CREATE USER 'someuser'#'localhost' IDENTIFIED BY 'somepassword';" && \
mysql -e "GRANT ALL PRIVILEGES ON somedb.* TO 'someuser'#'localhost';"
or source a prepopulated sql dump:
COPY dump.sql /SQL
RUN mysqld_safe & until mysqladmin ping; do sleep 1; done && \
mysql -e "SOURCE /SQL;"
RUN mysqladmin shutdown
The key here is to send mysqld_safe to background with the single & sign.
After to struggle a little bit with that, take a look the Dockerfile using named volumes (db-data).
It's important declare a plus at final part, where I mentioned that volume is [external]
All worked great this way!
version: "3"
services:
database:
image: mysql:5.7
container_name: mysql
ports:
- "3306:3306"
volumes:
- db-data:/docker-entrypoint-initdb.d
environment:
- MYSQL_DATABASE=sample
- MYSQL_ROOT_PASSWORD=root
volumes:
db-data:
external: true
Below is the Dockerfile I used successfully to install xampp, create a MariaDB with scheme and pre populated with the info used on local server(usrs,pics orders,etc..)
FROM ubuntu:14.04
COPY Ecommerce.sql /root
RUN apt-get update \
&& apt-get install wget -yq \
&& apt-get install nano \
&& wget https://www.apachefriends.org/xampp-files/7.1.11/xampp-linux-x64-7.1.11-0-installer.run \
&& mv xampp-linux-x64-7.1.11-0-installer.run /opt/ \
&& cd /opt/ \
&& chmod +x xampp-linux-x64-7.1.11-0-installer.run \
&& printf 'y\n\y\n\r\n\y\n\r\n' | ./xampp-linux-x64-7.1.11-0-installer.run \
&& cd /opt/lampp/bin \
&& /opt/lampp/lampp start \
&& sleep 5s \
&& ./mysql -uroot -e "CREATE DATABASE Ecommerce" \
&& ./mysql -uroot -D Ecommerce < /root/Ecommerce.sql \
&& cd / \
&& /opt/lampp/lampp reload \
&& mkdir opt/lampp/htdocs/Ecommerce
COPY /Ecommerce /opt/lampp/htdocs/Ecommerce
EXPOSE 80