dingo_d
dingo_d

Reputation: 11670

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?

Upvotes: 1

Views: 2532

Answers (1)

Jacob Tomlinson
Jacob Tomlinson

Reputation: 3773

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.

Upvotes: 3

Related Questions