首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在码头持久化MySQL数据

在码头持久化MySQL数据
EN

Stack Overflow用户
提问于 2016-12-15 12:46:36
回答 2查看 5.6K关注 0票数 7

我是码头新来的。我已经使用以下Dockerfile成功地创建了一个Docker映像:

代码语言:javascript
复制
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"]

理想情况下,我希望码头映像包含Apache、PHP和MySQL --所有这些都在一个映像中。我希望这张图像尽可能的便携。这样,每当我需要启动一个新项目时,我就可以创建一个新的容器并挂载卷,然后继续编写代码。

当我启动一个新的容器时,我会如愿地得到所有的东西。但是mysql数据不能挂载。我认为这是因为安装是单向的(还是单向的?)如果我在启动新容器时添加了-v /project_dir/data:/var/lib/mysql,mysql就不会启动,因为project_dir/data是空的。我的问题是:

  1. 如何将数据从我的project_dir加载到容器内的/var/lib/mysql
  2. 如何为不同的容器设置不同的mysql密码?

编辑:--如果我不挂载本地卷(即project_dir/data)并启动容器,获得一个shell tty,我会看到/var/lib/mysql有几个文件,我认为运行/var/lib/mysql及其初始数据库需要这些文件。但是,如果我在/var/lib/mysql (容器内)中挂载本地卷和/var/lib/mysql,那么它是空的。这就是为什么MySQL没有启动,我不能从容器外部持久化数据的原因。我的问题是:如何让它运行并从本地目录中持久化数据。

EN

回答 2

Stack Overflow用户

发布于 2016-12-15 13:08:12

问题

这里要做的是在构建Docker映像时创建一个空数据库:

代码语言:javascript
复制
mysql_install_db --user=mysql --verbose=1 --basedir=/usr --datadir=/var/lib/mysql --rpm > /dev/null && \

但是当您从这个映像创建一个容器时,您可以在/var/lib/mysql文件夹上挂载一个卷。这将隐藏容器数据,以公开主机的文件夹。因此,您看到的是一个空文件夹。

解决方案

如果您查看一下/mysql/,您会发现这个问题是通过在容器实际启动时创建数据库来解决的,而不是在创建映像时解决的。这回答了你们的两个问题:

  1. 如果您使用已挂载的卷启动容器,那么数据库init将在随后执行,并且您的数据实际上将写入主机的FS中
  2. 您必须将这些信息作为env变量传递。

换句话说,使用ENTRYPOINT中的脚本,而不是直接在映像中插入您的DB。

警告

不过,也有一些警告。您所做的形象并不是真正的推荐,因为Docker的理念是“每个容器一个过程”。这里遇到的困难是,您必须在同一个容器(apache、Mysql等)上启动多个服务,因此您可能必须在入口点对这两种服务进行操作,这是令人困惑的。另外,如果一个服务失败,您的容器将仍然处于运行状态,但不能按预期工作。

然后,我建议将您在每个进程中所做的分割为1个映像,然后要么使用原始Docker启动它们,要么使用类似于docker-compose的用户。

此外,这将使您能够使用来自Docker:https://hub.docker.com的现有和高度可配置的映像,这将使您受益。你的工作少了,出错的也少了。

票数 4
EN

Stack Overflow用户

发布于 2016-12-15 14:03:05

当您在码头容器中有一个数据库时,使用卷是唯一的方法。也许我们应该声明“容器中的数据库”意味着不使用卷,并且在标准的10 in (或者如果修改了默认大小时更大)中有数据,而在卷中的数据库意味着docker run -v myvolume...

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

我完全同意Alexandre的回答,但我认为将数据库放在容器中是错误的,这也是出于另一个原因。默认情况下,图像的大小(运行时的容器)是10 GB。对于一些可执行文件、库和配置文件来说,这应该是相当舒适的。您可以修改此默认值,并在创建图像时添加更大的值。但是当你达到这个新的极限时会发生什么呢?假设您认为您的数据库的大小将是100 GB,而实际上,您所放的数据比计划的要多,最终您需要的数据是计划的5到20倍?卷可以放在SAN上,并在需要时进行扩展。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41164549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档