Docker: MySQL refuses host IP unless I restart it manually - mysql

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

Related

Connecting to mysql in docker fails

I'm setting up a Dockerfile where I can run my automated tests, and I'm having troubles with connecting to mysql database.
The Dockerfile depends on a prevoously built image and looks like this:
# Stage 0, assign argument as multistage image alias
ARG PHP_IMAGE
FROM ${PHP_IMAGE} as image
# Stage 1, start tests
FROM php:7.2-fpm
RUN curl -sS https://getcomposer.org/installer | php \
&& chmod +x composer.phar && mv composer.phar /usr/local/bin/composer
RUN apt-get update && apt-get install -y gnupg
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
apt-get install -yq nodejs build-essential \
git unzip \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng-dev \
subversion \
&& curl -sL https://deb.nodesource.com/setup_8.x | bash - \
&& pecl install mcrypt-1.0.1 \
&& docker-php-ext-enable mcrypt \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install -j$(nproc) mysqli
RUN apt-get install -y mysql-server
RUN /etc/init.d/mysql start
RUN mysqladmin -u root -p status
RUN yes | pecl install xdebug \
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_enable=on" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_autostart=off" >> /usr/local/etc/php/conf.d/xdebug.ini
RUN npm install -g npm
COPY --from=image /var/www/html/ /var/www/html/
WORKDIR /var/www/html/
COPY scripts/develop.sh develop.sh
COPY scripts/docker-test.sh docker-test.sh
RUN ["/bin/bash", "-c", "bash develop.sh && bash docker-test.sh"]
I've added RUN mysqladmin -u root -p status to try to debug why connecting to mysql failed and I got
Enter password: mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")'
Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists!
To run this I am running
docker build -t $TEST_DOCKER_NAME --build-arg PHP_IMAGE=$DOCKER_IMAGE_NAME_PHP -f Dockerfile.test .
The TEST_DOCKER_NAME and DOCKER_IMAGE_NAME_PHP are stored in an env file and read from there. The PHP image was built successfuly and I'm using it to copy the files from there to here so that I can run PHPUnit.
When I remove that RUN line my build fails when I'm trying to run a script that creates the database
mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to MySQL server on 'localhost' (99 "Cannot assign requested address")'
Check that mysqld is running on localhost and that the port is 3306.
You can check this by doing 'telnet localhost 3306'
What do I need to do in my Dockerfile to make it work?
Answer to your specific problem
This is a common mistake people make when using docker. When you use the RUN directive in docker you are running a command through to completion, capturing the filesystem changes and then exiting.
So when you have the lines
RUN /etc/init.d/mysql start
RUN mysqladmin -u root -p status
The first one is starting mysql. But then the changes are captured, the container is exited and then a new one is started to run the mysqladmin command. Therefore the mysql process is no longer running.
To avoid this you could combine them into a single line like
RUN /etc/init.d/mysql start && mysqladmin -u root -p status
However you will need to do this every time you want to use mysql. Such as in your develop.sh.
Wider answer
It is not recommended to run multiple processes within your container and it is also not recommended to use init.d or other system startup frameworks within your container.
You seem to be treating your container like a virtual machine and are having issues because containers are not VMs.
I recommend you explore running mysql in a separate container and then using a tool like docker-compose to start and and stop your containers.

How to launch process with Fabric

How do you launch a process using Fabric?
I'm trying to write a task to reset MySQL's password, which requires I launch the mysqld_safe daemon using:
sudo bash -c "mkdir -p /var/run/mysqld; chown mysql /var/run/mysqld; mysqld_safe --skip-grant-tables &"
When I run this manually on the server, ps aux|grep -i mysql shows it's running just fine, but when I run this using Fabric's sudo(), it appears to terminate almost immediately. What am I doing wrong?
I've also tried using nohup like:
sudo bash -c "mkdir -p /var/run/mysqld; chown mysql /var/run/mysqld; nohup mysqld_safe --skip-grant-tables &"
but that had no effect.
http://www.fabfile.org/faq.html#why-can-t-i-run-programs-in-the-background-with-it-makes-fabric-hang has a very clear explanation of why that is. Also proposes the solution.
In your case, you should install dtach and run:
sudo(dtach -n `mktemp -u /tmp/{0}.XXXX` {1}'.format(some_name, cmd_to_execute))
You can drop the "sudo bash" in the beginning btw.

Why SSH connection to docker container is not working?

So i have this Dockerfile:
FROM debian:squeeze
MAINTAINER Name < email : >
# Update the repository sources list
RUN apt-get update
# Install apache, PHP, and supplimentary programs. curl and lynx-cur are for debugging the container.
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install apache2 build-essential php5 mysql-server openssh-server libapache2-mod-php5 php5-mysql php5-gd php-pear php-apc php5-curl curl lynx-cur
# Enable apache mods.
RUN a2enmod php5
RUN a2enmod rewrite
# Manually set up the apache environment variables
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
EXPOSE 80
# Copy site into place.
ADD www /var/www/site
# Update the default apache site with the config we created.
ADD apache-config.conf /etc/apache2/sites-enabled/000-default.conf
# start mysqld and apache
EXPOSE 3306
RUN mkdir /var/run/sshd
RUN echo 'root:123' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
EXPOSE 22
CMD bash -c ' (mysqld &); /usr/sbin/apache2ctl -D FOREGROUND;/usr/sbin/sshd -D'
it builds up, no problem,MySQL and Apache start and work fine but the ssh won't work and i don't know why. openssh-server is installed.
i tried starting it up like this:
#startup.sh file
#/bin/bash
sshd
+
ADD ./startup.sh /opt/startup.sh
ENTRYPOINT ["/opt/startup.sh"]
and many other,i'm stuck.
What am i doing wrong?
you are starting apache in the foreground, hence the apachectl process will never give back the hand to the shell that started it and thus the /usr/sbin/sshd -D will never be called (unless you kill apache).
The following instruction will start both mysql and apache in the background and then sshd in the foreground:
CMD bash -c ' (mysqld &); /usr/sbin/apache2ctl start;/usr/sbin/sshd -D'
While such a CMD statement is ok for tests I would advise using a different approach for running multiple processes in a single docker container:
supervisor
phusion/baseimage
Replace below lines of code in the docker file,
RUN mkdir /var/run/sshd
RUN echo 'root:123' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
Using these codes
RUN apt-get install -y openssh-server
RUN echo 'root:password' |chpasswd
RUN mkdir -p /var/run/sshd
this works for me.
Note: Use ssh only for debugging purpose, it is not a good practice at all.

Mysql installation on docker container

I am trying to run mysql into modified ubuntu image which includs installation of Node.js and basic mysql installation using below docker file
# Memcached
# use the ubuntu base image provided by dotCloud
FROM ubuntu/mysqlbase
MAINTAINER Hitesh
# make sure the package repository is up to dat//e
#RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
#RUN apt-get update
#RUN apt-get install -y mysql-client
#ENTRYPOINT ["wc", "-l"]
#ENTRYPOINT ["echo", "running"]
ENTRYPOINT mysqld_safe & sleep 10
#RUN mysql
RUN echo "[mysqld]" >/etc/mysql/conf.d/docker.cnf
RUN echo "bind-address = 0.0.0.0" >>/etc/mysql/conf.d/docker.cnf
RUN echo "innodb_flush_method = O_DSYNC" >>/etc/mysql/conf.d/docker.cnf
RUN echo "skip-name-resolve" >>/etc/mysql/conf.d/docker.cnf
RUN echo "init_file = /etc/mysql/init" >>/etc/mysql/conf.d/docker.cnf
RUN echo "GRANT ALL ON *.* TO root#'%'" >/etc/mysql/init
USER root
EXPOSE 3306
On running this server using below command
sudo docker run -p 3306:13306 mysql/dockerfiletest
Following error was encountered
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Can some one please suggest what is needed to be changed here. I want to use this container to be linked with other container which is essentially running my node.js app.
UPDATE: You should check exposed port number - in your example is(was) port for memcached (11211) and not the port for mysql (3306).
Anyway, I think that you may need to modify your Dockerfile - remove unnecessary sleep in entrypoint:
ENTRYPOINT ["/usr/bin/mysqld_safe"]
Then you should start your container this way (daemon mode):
root#machine:/# docker run -d -p 3306:<host port> <image id>
answer has already been accepted, but i think you could leave the sleep in your entrypoint if you change the '&' to '&&'. not sure if docker does any parsing of the entrypoint or just executes it, but bash treats '&' very differently than '&&'.
ENTRYPOINT mysqld_safe && sleep 10

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!