How to Install mysql-server via dockerfile - mysql

Does anybody knows how to install mysql-server via dockerfile? I have written a Dockerfile, but the build ends with an error: /bin/sh: 1: /usr/bin/mysqld: not found
USER root
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server-5.7
# Remove pre-installed database
RUN rm -rf /var/lib/mysql/*
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/"/etc/mysql/my.cnf
ENV DB_USER example
ENV DB_PASSWORD example
ENV DB_NAME example
ENV VOLUME_HOME "/var/lib/mysql"
EXPOSE 3306
RUN cp /etc/mysql/my.cnf /usr/share/mysql/my-default.cnf
RUN /usr/bin/mysqld && sleep 5 && \
mysql -uroot -e "CREATE USER '${DB_USER}'#'%' IDENTIFIED BY '${DB_PASSWORD}'" && \
mysql -uroot -e "GRANT ALL PRIVILEGES ON *.* TO '${DB_USER}'#'%' WITH GRANT OPTION" &&\
mysql -uroot -e "CREATE DATABASE ${DB_NAME}" && \
mysqladmin -uroot shutdown

For an ubuntu:16.04 base image, mysqld is found in /usr/sbin, not /usr/bin
If you can add a step RUN which mysqld before your final RUN command that will show you where the mysqld executable is found. It may vary depending on which base image/distro you're using.
You can also use RUN mysqld ... without a full path, if the file is in your $PATH
You may also need to update your RUN sed line as below, adding spaces around the quoted string:
RUN sed -i -e "s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf
Otherwise, you may see the following error:
The command '/bin/sh -c sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/"/etc/mysql/my.cnf' returned a non-zero code: 1

Related

Docker MySQL automatical Installation and configuration

On old MySQL 5.6 I was automatically installing it and creating all needed users and passwords, using the code below.
Is there a way to do the same on a new MySQL 8.0 so that it automatically installs into docker containers allows root without a password and creates all the above?
RUN yum -y install https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
RUN yum-config-manager --disable mysql57-community; yum-config-manager --enable mysql56-community
RUN yum -y install mysql-community-server mysql-community-client
#Configure MySQL
# Needed to create system tables etc.
chown -R mysql:mysql /var/lib/mysql
su -l mysql -c "/usr/bin/mysql-systemd-start pre"
# Start main service
(su -l mysql -c "/usr/bin/mysqld_safe --basedir=/usr") &
# Don't signal startup success before a ping works
su -l mysql -c "/usr/bin/mysql-systemd-start post"
mysql -e "CREATE DATABASE IF NOT EXISTS \`${USERNAME}\`;"
mysql -e "GRANT ALL PRIVILEGES ON \`${USERNAME}\`.* TO \`${USERNAME}\`#'%' IDENTIFIED BY \"${MYSQL_PASS}\";"
mysql -e "GRANT ALL PRIVILEGES ON \`${USERNAME}\`.* TO \`${USERNAME}\`#'localhost' IDENTIFIED BY \"${MYSQL_PASS}\";"
mysqladmin shutdown

Change mysql bind-address from command line in Vagrant

I am setting up a new vagrant box for a NodeJS project. For the database I will be using MySQL. I have setup a provisioning script to install everything I need and it all works great apart from accessing MySQL from the host machine (Using Sequel Pro). I have it working but I have to edit the /etc/mysql/my.cnf file in order to comment out the bind-address line.
Is there anyway to do this on the command line so I can add it to the provisioning script? If this is possible then any other dev that I share the project with would only need to do vagrant up and have everything ready to go.
Below are the parts of my script relevant to the MySQL setup:
#!/bin/bash
# Variables
DBHOST=localhost
DBNAME=vagrant
DBUSER=vagrant
DBPASSWD=test123
# Update packages
apt-get update
# Install MySQL
debconf-set-selections <<< "mysql-server mysql-server/root_password password $DBPASSWD"
debconf-set-selections <<< "mysql-server mysql-server/root_password_again password $DBPASSWD"
apt-get install -y mysql-server
mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME"
mysql -uroot -p$DBPASSWD -e "CREATE USER '$DBUSER'#'localhost' IDENTIFIED BY '$DBPASSWD'"
mysql -uroot -p$DBPASSWD -e "GRANT ALL PRIVILEGES ON $DBNAME.* TO '$DBUSER'#'localhost'"
mysql -uroot -p$DBPASSWD -e "CREATE USER '$DBUSER'#'10.0.2.2' IDENTIFIED BY '$DBPASSWD'"
mysql -uroot -p$DBPASSWD -e "GRANT ALL PRIVILEGES ON $DBNAME.* TO '$DBUSER'#'10.0.2.2'"
echo "Installed MySQL"
Thanks for any help you can provide.
You should be able to achieve this using sed command from your script
apt-get install -y mysql-server
sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/my.cnf
...
Note you might need to restart the service to take effect if you provision and do not restart the instance for the 1st use, add this then to your script
service mysql stop
service mysql start

Accessing docker container mysql databases

I am trying to access mysql databases from my docker host to the container.
It's my own dockerfile which install a database expose on port 3306.
I launch my docker with docker-compose, and my compose file is mapping 3308 host port on 3306 container port.
I can access to mysql from the host like this :
mysql -h localhost -P 3308 -u root -pMyPassword
It's working well, but what I can't figure out, is why I can't see any datas from my container?
From inside the container, I have a test databases which I can connect to without any problem. But when I connect from the host to the container mysql process, It seems to show me the mysql datas from the host machine, not from the container one.
Any ideas?
Thanks :)
EDIT 1 :
So here is the first way I can connect to mysql into the container :
docker exec -it MyContainer mysql -uroot -pMyPassword
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test_db |
+--------------------+
It show me my db : test_db
But If i access from :
mysql -h localhost -P 3308 -u root -pMyPassword
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
My test_db isn't here.
And the result of docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a0de6a691d72 MyContainer "docker-entrypoint.sh" 3 hours ago Up 3 hours 9000/tcp, 0.0.0.0:8085->80/tcp, 0.0.0.0:3308->3306/tcp, 0.0.0.0:8084->8000/tcp, 0.0.0.0:8086->8080/tcp MyContainer
EDIT 2 :
I am developing a standard docker container for web hosting production environnement. Each host is controlled by ajenti. The host work with an nginx reverse proxy which redistribute websites on correct container. Every thing is wokring well. So here is my Dockerfile :
FROM php:5.6-fpm
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
libxml2-dev \
python \
build-essential \
make \
gcc \
python-dev \
locales \
python-pip
RUN dpkg-reconfigure locales && \
locale-gen C.UTF-8 && \
/usr/sbin/update-locale LANG=C.UTF-8
ENV LC_ALL C.UTF-8
ARG MYSQL_ROOT_PASSWORD
RUN export DEBIAN_FRONTEND=noninteractive; \
echo mysql-server mysql-server/root_password password $MYSQL_ROOT_PASSWORD | debconf-set-selections; \
echo mysql-server mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD | debconf-set-selections;
RUN apt-get update && apt-get install -y -q mysql-server php5-mysql
RUN rm /etc/apt/apt.conf.d/docker-gzip-indexes
RUN apt-get update && apt-get install -y wget
RUN wget http://repo.ajenti.org/debian/key -O- | apt-key add -
RUN echo "deb http://repo.ajenti.org/debian main main debian" > /etc/apt/sources.list.d/ajenti.list
RUN apt-get update && apt-get install -y ajenti cron unzip ajenti-v ajenti-v-php-fpm ajenti-v-mysql ajenti-v-nginx
RUN apt-get install -y python-setuptools python-dev \
&& easy_install -U gevent==1.1b3 \
&& sed -i -e s/ssl_version=PROTOCOL_SSLv3/ssl_version=PROTOCOL_SSLv23/ /usr/local/lib/python2.7/dist-packages/gevent-1.1b3-py2.7-linux-x86_64.egg/gevent/ssl.py
EXPOSE 80 8000 8080 3306
RUN mkdir /tmp/tempfiles \
&& mv /srv /tmp/tempfiles \
&& mv /var/lib/mysql /tmp/tempfiles \
&& mv /var/log /tmp/tempfiles \
&& mv /etc/ajenti /tmp/tempfiles
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s /usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
As I said, I wanted to be able do deploy a new container easily. So I created a docker-entrypoint.sh which copy wanted files to my volume when I start the container :
#!/bin/bash
DIR="/var/lib/mysql"
# look for empty dir
if [ ! "$(ls -A $DIR)" ]; then
cp -avr /tmp/tempfiles/mysql /var/lib/
fi
# rest of the logic
DIR="/srv"
# look for empty dir
if [ ! "$(ls -A $DIR)" ]; then
cp -avr /tmp/tempfiles/srv /
fi
# rest of the logic
DIR="/var/log"
# look for empty dir
if [ ! "$(ls -A $DIR)" ]; then
cp -avr /tmp/tempfiles/log /var/
fi
# rest of the logic
DIR="/etc/ajenti"
# look for empty dir
if [ ! "$(ls -A $DIR)" ]; then
cp -avr /tmp/tempfiles/ajenti /etc/
fi
# rest of the logic
Finally, my docker-compose.yml to launch everything and map ports :
version: '2'
services:
ajenti:
build:
context: ./dockerfiles/
args:
MYSQL_ROOT_PASSWORD: MyPassword
volumes:
- ./logs:/var/log
- ./html:/srv
- ./ajenti:/etc/ajenti
- ./mysql-data:/var/lib/mysql
- ./apache2:/etc/apache2
ports:
- "8084:8000"
#NGINX
- "8085:80"
#APACHE
- "8086:8080"
- "3308:3306"
Hope this will help to find a solution !
I finally found a solution and it was pretty simple...
First of all, I need to let mysql bind external address, so I changed the line bind-address to '0.0.0.0' inside the container.
Next I just changed the command line with mysql -h 127.0.0.1 -P 3308 -u root -pMyPassword
Now it's fine, I can access container mysql data from the host.
Thanks all for your help :)
In my case I was confused because docker used a different host and port. So you need to find them then do this:
mysql -P <portnumber> -h <host IP> -u db_name -p
Most people would put the docker DB related variables into the environment of the docker container so do this:
sudo docker exec -it container_name env
See if there's a variable called DB_HOST or DB_PORT or something like that. If not then look thru the source code. If it's a PHP project then find a config directory and look in main.php and see
if you execute MySQL operation as entrypoint in the dockerfile file, you will only see that operation when you connect to the container. try changing the entrypoint.
https://docs.docker.com/engine/reference/builder/#entrypoint

Docker: MySQL refuses host IP unless I restart it manually

Here is my Dockerfile:
FROM debian:jessie-backports
RUN apt-get update --yes && apt-get upgrade --yes
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
git \
curl \
build-essential\
libssl-dev\
ca-certificates\
mysql-server\
redis-server\
elasticsearch
USER root
ENV HOME /root
# MYSQL SETUP
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/#bind-address = 0.0.0.0/" /etc/mysql/my.cnf
RUN sed -i -e"s/^#max_connections\s*=\s*100/max_connections = 200/" /etc/mysql/my.cnf
RUN echo "\n[mysqld]\nskip-grant-tables\n" >> /etc/mysql/my.cnf
VOLUME ["/var/lib/mysql", "/var/log/mysql"]
EXPOSE 3306
# REDIS SETUP
RUN echo "daemonize yes\nbind 0.0.0.0" >> /etc/redis/redis-serve.conf
RUN sed 's/^daemonize no/daemonize yes/' -i /etc/redis/redis.conf \
&& sed 's/^bind 127.0.0.1/bind 0.0.0.0/' -i /etc/redis/redis.conf \
&& sed 's/^# unixsocket /unixsocket /' -i /etc/redis/redis.conf \
&& sed 's/^# unixsocketperm 755/unixsocketperm 777/' -i /etc/redis/redis.conf \
&& sed '/^logfile/d' -i /etc/redis/redis.conf
VOLUME ["/var/lib/redis", "/var/log/redis"]
EXPOSE 6379 6380
# ELASTICSEARCH SETUP
RUN sed 's/^#START_DAEMON=true/START_DAEMON=true/' -i /etc/default/elasticsearch
VOLUME ["/opt/elasticsearch/data", "/opt/elasticsearch/logs"]
EXPOSE 9200 9300
ADD docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod 777 /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
The entrypoint:
#!/bin/bash
/etc/init.d/mysql start
/etc/init.d/redis-server start
/etc/init.d/elasticsearch start
/bin/bash
And the command I'm running to start the container:
docker run -i -t -p 3306:3306 -p 6379:6379 -p 9200:9200 -p 9300:9300 assethost
I want to connect to the MySQL server running in the container from the host, but this is what happens when I try to connect:
ERROR 1130 (HY000): Host '192.168.99.1' is not allowed to connect to this MySQL server
Both Redis and Elasticsearch expose themselves just fine. MySQL will only begin accepting external hosts if I restart it manually from the Bash shell that comes up from the entrypoint when I run the container. I have to run /etc/init.d/mysql restart. Only then, can I successfully connect from the host using the MySQL client.
Note that I am using docker-machine, so I have to give the MySQL client the host IP in order to connect.
How can I be able to connect from the host to the MySQL instance running in the container without having to manually restart MySQL?
Docker version 1.12.1, build 23cf638
I figured out a way to get the skip-grant-tables option to be applied on start.
Workaround
In docker-entrypoint.sh, I changed
/etc/init.d/mysql start to
HOME=/etc/mysql /usr/bin/mysqld_safe > /dev/null 2>&1 &
Other changes
Since there was already a [mysqld] section in my.cnf, I changed the following line in Dockerfile
RUN echo "\n[mysqld]\nskip-grant-tables\n" >> /etc/mysql/my.cnf
to
RUN sed -i '/\[mysqld\]/ a skip-grant-tables\nskip-name-resolve' /etc/mysql/my.cnf
I added skip-name-resolve so mysql doesn't attempt to resolve names for local ip addresses.
Caveats
The workaround no longer works when /etc/init.d/mysql restart is executed, but /etc/init.d/mysql stop; /etc/init.d/mysql start preserved the 'skip-grant-tables' option.
I'm guessing MySQL has already started after your installation and running sed to change configuration won't take effect. Entry point you have has mysql start but it is probably seeing that MySQL is already running and not doing anything. Try changing that command to mysql restart, so your entry point bash script becomes:
#!/bin/bash
/etc/init.d/mysql restart
/etc/init.d/redis-server start
/etc/init.d/elasticsearch start
/bin/bash
You're using skip-grant-tables flag to login without password. I think due to some reasons of /etc/init.d/mysql script, the flag is ignored on the first start, making the connection from the root#192.168.99.1 rejected. I believe Docker has nothing to do with this issue.
To answer your question, you don't have to restart by hand, you can change your entrypoint to either:
#!/bin/bash
/etc/init.d/mysql start
# Wait for mysql to be fully up, then restart (e.g., 5 seconds)
sleep 5
/etc/init.d/mysql restart
/etc/init.d/redis-server start
/etc/init.d/elasticsearch start
/bin/bash
Or, don't use /etc/init.d/mysql start, instead invoke mysqld directly
#!/bin/bash
mysqld &
/etc/init.d/redis-server start
/etc/init.d/elasticsearch start
/bin/bash
In addition, although creating one more [mysqld] group in my.cnf is not an issue, you should append new configuration to the existing group:
RUN sed -i '/\[mysqld\]/a skip-grant-tables' /etc/mysql/my.cnf
Refer the doc for several ways to start/stop Mysql server

Can't delete mysql database, table or even alter table inside docker

I want to have a mysql database with some basic dataset.
I create mysql docker image using this https://index.docker.io/u/brice/mysql/ Dockerfile, but delete VOLUME ["/var/lib/mysql", "/var/log/mysql"] line, so the Dockerfile looks like:
FROM ubuntu:12.10
MAINTAINER Brandon Rice <brice84#gmail.com>
RUN dpkg-divert --local --rename --add /sbin/initctl
RUN ln -s /bin/true /sbin/initctl
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get -y install mysql-server
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf
RUN /usr/bin/mysqld_safe & \
sleep 10s && \
mysql < create_my_db.sql && \
mysql -e "GRANT ALL ON *.* to 'root'#'%'; FLUSH PRIVILEGES"
EXPOSE 3306
CMD ["mysqld_safe"]
After that I build image such as:
docker build -t my_db_mysql .
Everything is ok while i append data, but when i want to delete db, for example:
FROM my_db_mysql
RUN /usr/bin/mysqld_safe & \
sleep 10s && \
mysql -e "DROP DATABASE my_db;"
EXPOSE 3306
CMD ["mysqld_safe"]
I obtain next error:
ERROR 6 (HY000) at line 1: Error on delete of './my_db//db.opt' (Errcode: 1)
It is appears not only when I want to build image, but even when I exec: mysql -u user -p -e "DROP DATABASE my_db;"
How to solve this?
Thanks
Update: Also I tried to run docker with different filesystem, e.g -s vfs or -s devicemapper, but nothing changed.
When I build image with VOLUME ["/var/lib/mysql", "/var/log/mysql"] - everything works properly, but i can't commit this changes.
Update: Seems I resolve this issue. Problem was in host machine with ubuntu 12.04. Issue disappeared when I update ubuntu to 13.10. Thank a lot!