在Docker中保留MySQL数据

我是Docker的新手。 我用下面的Dockerfile成功创build了一个Docker 镜像

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"] 

理想情况下,我希望docker映像包含Apache,PHP和MySQL – 全都在一个映像中。 我希望图像尽可能便携。 所以每次我需要开始一个新的项目时,我都可以创build一个新的容器并装入卷并继续进行编码。

当我开始一个新的容器,我得到一切按预期。 但是mysql数据不能被挂载。 我认为这是因为挂载是单向的(或者是它)?如果我在添加-v /project_dir/data:/var/lib/mysql时启动一个新的容器,mysql不会启动,因为project_dir/data是空的。 我的问题是:

  1. 如何将数据从我的project_dir装载到容器/var/lib/mysql
  2. 我怎样才能设置不同的MySQL密码到不同的容器?

编辑:如果我不装载我的本地卷(即project_dir/data ),并启动容器,得到一个shelltty,我看到/var/lib/mysql有几个文件,我认为是需要运行MySQL及其初始数据库。 但是,如果我挂载我的本地卷和ls里面的/var/lib/mysql (容器内),它是空的。 这就是为什么MySQL不启动,我不能从容器持久化数据。 我的问题是:如何让它运行并从本地目录中坚持数据。

问题是

这里发生的事情是在Docker镜像构build时创build一个空的数据库:

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

但是当你从这个镜像创build一个容器时,你需要在/var/lib/mysql文件夹上挂载一个卷。 这将隐藏您的容器数据,以显示您的主机的文件夹。 因此,你看到一个空的文件夹。

解决scheme

如果你看一下https://hub.docker.com/_/mysql/ ,你会发现这个问题是通过在容器实际启动时创build数据库来解决的,而不是在创build图像时。 这回答你的问题:

  1. 如果你使用装入的卷启动你的容器,那么数据库init将会被执行,而你的数据将被写入你的主机的FS
  2. 您必须将这些信息作为envvariables传递

换句话说,在ENTRYPOINT使用脚本初始化数据库,而不是直接在图像中。

警告

一些警告,但。 你做你的形象的方式并不是真的被推荐,因为Docker的理念是“每个容器一个进程”。 你在这里遇到的困难是,你必须在同一个容器(apache,Mysql等)上启动多个服务,所以你可能不得不在你的入口点做两件事情,这是令人困惑的。 另外,一个服务失败,你的容器仍然会弹起来,但不能按预期工作。

然后我会build议将每个进程的内容分成1个图像,然后用原始的Docker或者像docker-compose这样的用户来启动它们。

另外,这将使您能够使用Docker Hub中已有的高度可configuration的映像: https : //hub.docker.com 。 为您减less工作,减less错误发生。

当您在Docker容器中有一个数据库时,使用卷是唯一的方法。 也许我们应该说“数据库里面的数据库”意味着不使用卷和数据在标准10GB(或更大,如果默认大小已被修改)和数据库在一个卷意味着docker run -v myvolume...

文档docs.docker.com/engine/tutorials/dockervolumes是必看的

我完全同意亚历山大的回答,但我认为把你的数据库放入你的容器是不对的,也是另一个原因。 默认情况下,图像的大小(运行时是容器)为10 GB。 这对于一些可执行文件,库和configuration文件应该是相当舒服的。 你可以修改这个默认值,并且在创build图片的时候放一个更大的值。 但是,当你达到这个新的限制时会发生什么? 假设你认为数据库的大小为100GB,事实上,你input的数据比计划的多,你最终需要5到20倍的数据呢? 卷可以在SAN上并在需要时进行扩展。