Saving MySQL Data in Docker

I am new to Docker. I successfully created a Docker image with the following Docker file:

From alpine:3.4 MAINTAINER SomeName - domain.tld # Timezone ENV TIMEZONE Asia/Kolkata # RUN sed -i 's#dl-cdn\.alpinelinux\.org#mirrors\.aliyun\.com#' /etc/apk/repositories # install mysql, apache and php and php extensions, tzdata, wget RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \ apk add --update \ mysql mysql-client \ apache2 \ curl wget \ tzdata \ php5-apache2 \ php5-cli \ php5-phar \ php5-zlib \ php5-zip \ php5-bz2 \ php5-ctype \ php5-mysqli \ php5-mysql \ php5-pdo_mysql \ php5-opcache \ php5-pdo \ php5-json \ php5-curl \ php5-gd \ php5-gmp \ php5-mcrypt \ php5-openssl \ php5-dom \ php5-xml \ php5-iconv \ php5-xdebug@community RUN curl -sS https://getcomposer.org/installer | \ php -- --install-dir=/usr/bin --filename=composer # configure timezone, mysql, apache RUN cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && \ echo "${TIMEZONE}" > /etc/timezone && \ mkdir -p /run/mysqld && chown -R mysql:mysql /run/mysqld /var/lib/mysql && \ mysql_install_db --user=mysql --verbose=1 --basedir=/usr --datadir=/var/lib/mysql --rpm > /dev/null && \ mkdir -p /run/apache2 && chown -R apache:apache /run/apache2 && chown -R apache:apache /var/www/localhost/htdocs/ && \ sed -i 's#AllowOverride none#AllowOverride All#' /etc/apache2/httpd.conf && \ sed -i 's#ServerName www.example.com:80#\nServerName localhost:80#' /etc/apache2/httpd.conf && \ sed -i '/skip-external-locking/a log_error = \/var\/lib\/mysql\/error.log' /etc/mysql/my.cnf && \ sed -i '/skip-external-locking/a general_log = ON' /etc/mysql/my.cnf && \ sed -i '/skip-external-locking/a general_log_file = \/var\/lib\/mysql\/query.log' /etc/mysql/my.cnf # Configure xdebug RUN echo "zend_extension=xdebug.so" > /etc/php5/conf.d/xdebug.ini && \ echo -e "\n[XDEBUG]" >> /etc/php5/conf.d/xdebug.ini && \ echo "xdebug.remote_enable=1" >> /etc/php5/conf.d/xdebug.ini && \ echo "xdebug.remote_connect_back=1" >> /etc/php5/conf.d/xdebug.ini && \ echo "xdebug.idekey=PHPSTORM" >> /etc/php5/conf.d/xdebug.ini && \ echo "xdebug.remote_log=\"/tmp/xdebug.log\"" >> /etc/php5/conf.d/xdebug.ini #start apache RUN echo "#!/bin/sh" > /start.sh && \ echo "httpd" >> /start.sh && \ echo "nohup mysqld --skip-grant-tables --bind-address 0.0.0.0 --user mysql > /dev/null 2>&1 &" >> /start.sh && \ echo "sleep 3 && mysql -uroot -e \"create database db;\"" >> /start.sh && \ echo "tail -f /var/log/apache2/access.log" >> /start.sh && \ chmod u+x /start.sh WORKDIR /var/www/localhost/htdocs/ EXPOSE 80 EXPOSE 3306 #VOLUME ["/var/www/localhost/htdocs","/var/lib/mysql","/etc/mysql/"] ENTRYPOINT ["/start.sh"] 

Ideally, I want the docker image to contain Apache, PHP and MySQL - all in one image. I want the image to be as portable as possible. So that every time I needed to start a new project, I can just create a new container and mount the volumes and continue with the code.

When I launch a new container, I get everything as expected. But mysql data cannot be installed. I think this is because the installation is one-way (or is it?). If I add -v /project_dir/data:/var/lib/mysql when starting a new container, mysql does not start because project_dir/data empty. My questions:

  • How to set data from my project_dir to /var/lib/mysql inside a container?
  • How to set different mysql passwords in different containers?

Edit: If I do not mount my local volume (i.e. project_dir/data ) and do not start the container, we get the tty shell, I see that /var/lib/mysql has several files that I assume are necessary to start mysql and it source databases. But if I mount my local volume and ls inside /var/lib/mysql (inside the container), it is empty. This is why MySQL does not start, and I cannot save data outside the container. My question is: how can I run it and save data from a local directory.

+6
source share
2 answers

Problem :

What happens here is that you create an empty database when creating a Docker image:

 mysql_install_db --user=mysql --verbose=1 --basedir=/usr --datadir=/var/lib/mysql --rpm > /dev/null && \ 

But when you create a container from this image, you mount the volume in the /var/lib/mysql folder. This hides the data of your containers to open your host folder. Thus, you see an empty folder.

Solution :

If you look at https://hub.docker.com/_/mysql/ , you will see that this problem is solved by creating a database when the container actually starts, and not when the image is created. This answers your questions:

  • If you start your container with the volume installed, then the database initialization will start and your data will actually be written to your FS host
  • You must pass this information as env variables

In other words, start your database using a script in ENTRYPOINT , and not directly on the image.

Warnings

Some warnings. The way you made your image is not really recommended, because Docker's philosophy is "one process per container." The difficulty that you are encountering here is that you will have to run several services in one container (apache, Mysql, etc.), so you may have to do something at both entry points, which is confusing. In addition, one service does not work, your container will still work, but it does not work as expected.

Then I would suggest splitting what you did as 1 image per process, or starting them with raw Docker, or a user like docker-compose .

In addition, it will help you in that you can use existing and custom images from the Docker Hub: https://hub.docker.com . Less work for you and less error prone.

+4
source

When you have a database in the docker container, using the volume is the only way. Maybe we should say that “the database inside your container” means not using the volume and having data in the standard 10 GB (or more if the default size was changed), but the database in the volume means docker run -v myvolume...

doc docs.docker.com/engine/tutorials/dockervolumes is required to view

I completely agree with Alexandre's answer, but I think it’s wrong to put your database in your container, also for another reason. By default, the image size (so the container when it starts) is 10 GB. This should be pretty handy for some executables, libraries, and configuration files. You can change this default value and add a larger value when creating the image. But what happens when you click this new limit? Suppose you think your database will be 100 GB in size, but in fact you are putting more data than planned, and you ultimately need 5 or 20 times more? The volume can be in the SAN and expanded if necessary.

-one
source

Source: https://habr.com/ru/post/1013186/


All Articles