I'm trying to create a setup where when I do a "docker run" off a Dockerfile that I've created, docker will install and setup mysql, and then create a database for me to use.
Below is my simple docker file that pulls from the existing dockerfile/mysql
FROM dockerfile/mysql
COPY dbsetup.sql /tmp/dbsetup.sql
RUN bash -c "/usr/bin/mysqld_safe &" && \
sleep 5 && \
mysql -u root -e "CREATE DATABASE mydb"
It seems to run, but when I connect to the DB (using the IP I received from the boot2docker ip command), the database doesnt' exist.
Anyone have any ideas?
Note: I had originally tried to run all three of those commands in separate RUN statements, but that didn't work. Explanation of why here.
You should take example on the dockerfile/mysql Dockerfile which has the following RUN statement:
RUN echo "mysqld_safe &" > /tmp/config \
&& echo "mysqladmin --silent --wait=30 ping || exit 1" >> /tmp/config \
&& echo "mysql -e 'GRANT ALL PRIVILEGES ON *.* TO \"root\"#\"%\" WITH GRANT OPTION;'" >> /tmp/config \
&& bash /tmp/config \
&& rm -f /tmp/config
In your case you would put in your Dockerfile:
RUN echo "mysqld_safe &" > /tmp/config \
&& echo "mysqladmin --silent --wait=30 ping || exit 1" >> /tmp/config \
&& echo "mysql -u root -e \"CREATE DATABASE mydb\"" >> /tmp/config \
&& bash /tmp/config \
&& rm -f /tmp/config
I would advise either using the standard mysql container image or borrow from its dockerfile
It uses environment variables to control the database name and admin credentials.
Related
I am developing a "one file script" for run MySQL database inside Docker and many useful thinks. The script should create a container with MySQL and after that create a new user with maximum privileges.
The problem occurs when I try to connect to MySQL command line from the bash script. Part of the script:
#!/bin/bash
mysqlContainerName=project-mysql
mysqlRootUsername=root
mysqlRootPassword=root_pass
mysqlUsername=db_user
mysqlPassword=db_pass
mysqlDb=project_db
echo -e "Creating container \e[31m$mysqlContainerName\e[0m"
docker run --rm -d \
--name=$mysqlContainerName \
--network api-network \
-p 3306:3306 \
-v /opt/docker-data/mysql-volumes:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=$mysqlRootPassword \
-e MYSQL_DATABASE=$mysqlDb \
-t mysql:8.0.19
docker exec $mysqlContainerName \
mysql -h 127.0.0.1 -P 3306 --protocol=tcp \
-uroot -p$mysqlRootPassword -e "CREATE USER '$mysqlUsername'#'localhost' IDENTIFIED BY
'$mysqlPassword';"
So, container successfully created, but all the time I get an error message: ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (111)
Any suggestions?
So, after a few hours of searching, I found a solution.
Added bash -c parameter and in quotes connection to MySQL and query.
docker exec $mysqlContainerName bash -c "mysql -h172.21.0.1 -P 3306 --protocol=tcp -u$mysqlRootUsername -p$mysqlRootPassword -e \"CREATE USER '$mysqlUsername'#'localhost' IDENTIFIED BY '$mysqlPassword';\"; exit;"
This question already has answers here:
Why docker container exits immediately
(16 answers)
Closed 5 years ago.
I'm trying to create a mysql image with Docker but it doesn't work correctly...
My goal is to create a custom image of MYSQL from Ubuntu Trusty. The image should execute the typical script to configure the database depending of the variables passed through command line but when I run 'docker run -d -e MYSQL_ROOT=docker -e MYSQL_DATABASE=wp ... ' the script works right but when it finished, the container stop.
I tried to 'nohup /usr/sbin/mysqld &' , exec '/usr/sbin/mysqld &' but nothing, the daemon die.
My dockerfile is the following:
FROM ubuntu:trusty
ENV DEBIAN_FRONTEND noninteractive
RUN \
apt-get update && \
apt-get -y install mysql-server-5.6 supervisor --no-install-recommends && \
apt-get -y clean && \
apt-get -y autoclean && \
rm -rf /var/lib/apt/lists/*
RUN \
ln -sf /dev/stderr /var/log/mysql/error.log && \
sed -i 's/127.0.0.1/0.0.0.0/' /etc/mysql/my.cnf
COPY config.sh /
VOLUME ["/var/lib/mysql"]
EXPOSE 3306
ENTRYPOINT ["/config.sh"]
And the script 'config.sh' :
#!/bin/bash -x
/usr/sbin/mysqld &
sleep 5
if [ $MYSQL_ROOT_PASSWORD ]
then
mysql -u root -e "SET PASSWORD FOR 'root'#'localhost' = PASSWORD('${MYSQL_ROOT_PASSWORD}') ;"
else
echo 'Error al establecer la contraseƱa de root.'
exit 1
fi
if [ $MYSQL_DATABASE ]
then
mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE} ;"
else
echo 'Error al crear la base de datos.'
fi
if [ $MYSQL_USER ] && [ $MYSQL_PASSWORD ]
then
mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'#'%' IDENTIFIED BY '${MYSQL_PASSWORD}' ; FLUSH PRIVILEGES ;"
elif [ $MYSQL_USER ]
then
mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'#'%' IDENTIFIED BY '${MYSQL_USER}' ; FLUSH PRIVILEGES ;"
else
echo 'No se pudo crear el usuario.'
fi
This is most likely because the order you do the commands.
You need the mysqld daemon in foreground, and you are putting it in background.
Just add something that waits forever at the end of your script:
#!/bin/bash -x
## YOUR INIT CODE HERE
## ...
## ...
tail -f /dev/null
I'm just getting started with Docker and was able to set up MySQL according to my needs, by running tutum/lamp and doing a bunch of exec. For example:
docker run -d -p 80:80 -p 3306:3306 --name test tutum/lamp
...
docker exec test mysqldump --host somehost --user someuser --password --databases somedatabase > dump.sql
docker exec test mysql -u root < dump.sql
However, I'm having issues converting this to a Dockerfile. Specifically, the following results in ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock':
FROM tutum/lamp
EXPOSE 80 3306
...
RUN mysqldump --host=$DB_IP --user=$DB_USER --password=$DB_PASSWORD --databases somedatabase > dump.sql
RUN mysql -u root < dump.sql
You will need to override run.sh in order to do that, because when you run a container it will install mysql for the first time.
That is why you can not connect to mysql prior to that (in my previous answer I wasn't aware of that).
I've managed to execute mysql command by adding this to Dockerfile
FROM tutum/lamp
ADD . /custom
RUN chmod 755 /custom/run.sh
CMD ["/custom/run.sh"]
Then in the same folder create a file run.sh
#!/bin/bash
VOLUME_HOME="/var/lib/mysql"
sed -ri -e "s/^upload_max_filesize.*/upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}/" \
-e "s/^post_max_size.*/post_max_size = ${PHP_POST_MAX_SIZE}/" /etc/php5/apache2/php.ini
if [[ ! -d $VOLUME_HOME/mysql ]]; then
echo "=> An empty or uninitialized MySQL volume is detected in $VOLUME_HOME"
echo "=> Installing MySQL ..."
mysql_install_db > /dev/null 2>&1
echo "=> Done!"
/create_mysql_admin_user.sh
else
echo "=> Using an existing volume of MySQL"
fi
( sleep 20 ; mysql -u root < /custom/dump.sql ; echo "*** IMPORT ***" ) &
exec supervisord -n
This file is the same as /run.sh with one line added to run sql import after 20 seconds to make sure mysql service is up and running (there must be more elegant way to run a command just after mysql is started, of course).
I'm having difficulty with a script I'm writing. The script is largely incomplete, but so far I expect it to be able to run containers successfully. When I execute the script I'm given an error with a container ID and "command not found". For example: ./wordpress: line 73: 3c0fba4984f3b70f0eb3f1c15a7b157f4862b9b243657a3d2f7141029fb6641a: command not found
The script I'm using is as follows:
#!/bin/bash
echo "Setting Constants"
MYSQL_ROOT_PASSWORD='password'
MYSQL_DATABASE='wordpress'
WORDPRESS_DB_PASSWORD='password'
WP_PORT='80'
DB_PORT='3306'
EPOCH=$(date +%s) # append EPOCH to container names for uniqueness
#FILE='blogcontainers' # filename containing container IDs
DB_CONTAINER_NAME="myblogdb$EPOCH"
WP_CONTAINER_NAME="myblog$EPOCH"
DB_IMG_NAME='blogdb' # MySQL Docker image
WP_IMG_NAME='blog' # WordPress Docker image
cd ~/myblog
WP_CID_FILE="$PWD/blog.cid"
DB_CID_FILE="$PWD/blogdb.cid"
if [ -f $DB_CID_FILE ]; then
DB_IMG_ID=$(sed -n '1p' $DB_CID_FILE)
else
echo "dbcid not found"
# set to baseline image
DB_IMG_ID="f09a5b2903dc"
fi
if [ -f $WP_CID_FILE ]; then
WP_IMG_ID=$(sed -n '1p' $WP_CID_FILE)
else
echo "wpcid not found"
# set to baseline image
WP_IMG_ID="a8d48bc2313d"
fi
DB_PATH='/var/lib/mysql' # standard MySQL path
WP_PATH='/var/www/html' # standard WordPress path
LOCAL_DB_PATH="/$PWD$DB_PATH"
LOCAL_WP_PATH="/$PWD$WP_PATH"
echo "Starting MySQL Container"
#DB_ID=
$(docker run \
-e MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD \
-e MYSQL_DATABASE=$MYSQL_DATABASE \
-v $LOCAL_WP_PATH:$DB_PATH \
-v /$PWD/.bash_history:$WP_PATH \
--name $DB_CONTAINER_NAME \
-p $DB_PORT:3306 \
--cidfile $DB_CID_FILE \
-d \
$DB_IMG_ID)
echo "Starting WordPress Container"
#WP_ID=
$(docker run \
-e WORDPRESS_DB_PASSWORD=$WORDPRESS_DB_PASSWORD \
--link $DB_CONTAINER_NAME:$DB_IMG_NAME \
-p $WP_PORT:80 \
-v $LOCAL_WP_PATH:$WP_PATH \
-v /$PWD/.bash_history:/root/.bash_history \
--name $WP_CONTAINER_NAME \
--cidfile $WP_CID_FILE \
-d \
$WP_IMG_ID)
echo $WP_CONTAINER_NAME
echo $WP_IMG_ID
echo "reached end"
#echo $WP_ID > $FILE # copy WordPress container ID to file
#echo $DB_ID >> $FILE # append MySQL container ID to file
After executing the code there usually is a MySQL container instance running. For example:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f2e9ab14c2e f09a5b2903dc "/entrypoint.sh mysql" 2 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp myblogdb1449768739
Also, both blog.cid and blogdb.cid are created successfully containing container IDs.
$ cat blog.cid
e6005bcb4dba524b121d02b301fbe421d67d60986c55d554a0e20443df27ed18
$ cat blogdb.cid
4f2e9ab14c2ea5361557a3714477d7758c993af3b08bbc7db529282a41f90959
I've been troubleshooting and searching around for answers, but I think it's time to have another set of eyes take a look at it. As always, any input/criticism are welcome.
You are using $(docker run ...) instead of simply docker run .... The command substitution ($(...)) runs the command, captures the output, and expands to that output. As a result, you are trying to run the output of docker run as a command.
I have followed the instruction in https://registry.hub.docker.com/_/mysql/ to pull an image and running a container in which it runs a MySQL server.
The container is running in the background and I would like to run some commands.
Which is the best way to connect to the container and execute this command from command line?
Thanks.
You can connect to your mysql container and run your commands using:
docker exec -it mysql bash -l
(Where mysql is the name you gave the container)
Keep in mind that anything you do will not persist to the next time your run a container from the same image.
docker exec -i some_mysql_container mysql -uroot -ppassword <<< "select database();"
To connect to the MySQL database using MySQL command line client.
I connect to the bash into the running MySQL container:
$ docker exec -t -i container_mysql_name /bin/bash
-i is the shortcut for --interactive option. This options is used for keep STDIN open even if not attached
-t is the shortcut for --tty option, used to allocate a pseudo-TTY
I run MySQL client from bash MySQL container:
$ mysql -uroot -proot
-u is shortcut for --user=name option, used to define user for login if not current user.
-p is shortcut for -password[=name] option, used to define password to use when connecting to server. If password is not given it's asked from the tty.
Disco!
In my case the <<< solution did not work.
Instead I used -e.
Example:
docker exec ${CONTAINER_NAME} mysql -u ${USER_NAME} -p${PASSWORD} -e "drop schema test; create schema test;"
For #Abdullah Jibaly solution, after tested in MySQL 5.7, it would only entered into bash terminal prompt, whereby you still need to enter mysql command second time.
In order to directly enter into MySQL command line client after run MySQL container with one line of command, just run the following:
docker exec -it container_mysql_name mysql -u username -p
Its possible with docker run, start a new container just to execute your mysql statement.
This approach helped me to workaround the access denied problem when you try to run a statement with docker exec using localhost to connect to mysql
$ docker run -it --rm mysql mysql -h172.17.0.2 -uroot -pmy-secret-pw -e "show databases;"
I use the following to create a command that will sort out at least a couple of cases with databases outside or inside the container (with -h and -P) and supporting -e:
cat > ~/bin/mysql <<'EOF'
#/bin/bash
MARGS=()
MPORT="3306"
while test $# != 0; do
if [[ $1 == -h ]]; then MHOST=$2; shift;
elif [[ $1 == -h* ]]; then MHOST=${1#"-h"};
elif [[ $1 == -e ]]; then MEXEC=$2; shift;
elif [[ $1 == -e* ]]; then MEXEC=${1#"-e"};
elif [[ $1 == --execute=* ]]; then MEXEC=${1#"--execute="};
elif [[ $1 == -P ]]; then MPORT=$2; shift;
elif [[ $1 == -P* ]]; then MPORT=${1#"-P"};
else MARGS="$MARGS $1"
fi
shift;
done
if [ -z "${MHOST+x}" ]; then
MHOST=localhost
fi
if [ $(docker inspect --format '{{ .State.Status }}' mysql) == "running" ]; then
if [ ! -z "${MHOST+x}" ]; then
if [ "$MHOST" == "localhost" -o "$MHOST" == "127.0.0.1" ]; then
CPORT=$(docker port mysql 3306/tcp)
if [ ${CPORT#"0.0.0.0:"} == $MPORT ]; then
#echo "aiming for container port ($MPORT -> $CPORT)";
MHOST=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mysql);
else
MHOST=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | head -1);
fi
fi
fi
fi
if [ -z "$MEXEC" ]; then
docker run --link mysql:mysql -i --rm mysql mysql "-h" $MHOST "-P" $MPORT $MARGS
else
docker run --link mysql:mysql -i --rm mysql mysql "-h" $MHOST "-P" $MPORT $MARGS <<< $MEXEC
fi
EOF
chmod +x ~/bin/mysql
i didn't find any of these solutions to be effective for my use case: needing to store the returned data from the SQL to a bash variable.
i ended up with the following syntax when making the call from inside a bash script running on the host computer (outside the docker mysql server), basically use 'echo' to forward the SQL statement to stdin on the docker exec command.
modify the following to specify the mysql container name and proper mysql user and password for your use case:
#!/bin/bash
mysqlCMD="docker exec -i _mysql-container-name_ mysql -uroot -proot "
sqlCMD="select count(*) from DBnames where name = 'sampleDB'"
count=`echo $sqlCMD | $mysqlCMD | grep -v count`
# count variable now contains the result of the SQL statement
for whatever reason, when i used the -e option, and then provided that string within the back-quotes, the interpreter modified the quotation marks resulting in SQL syntax failure.
richard