在Docker中保留MySQL数据

abh*_*sek 7 mysql docker dockerfile

我是Docker的新手.我已使用以下Dockerfile 成功创建了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"]
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望docker镜像包含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有几个文件,我认为这些文件需要运行mysql及其初始数据库.但是,如果我挂载我的本地卷和ls内部/var/lib/mysql(在容器内),它是空的.这就是MySQL没有启动的原因,我无法从容器外部保留数据.我的问题是:如何让它运行并持久保存本地目录中的数据.

Ale*_*TRE 4

问题

这里发生的是,在构建 Docker 映像时创建一个空数据库:

mysql_install_db --user=mysql --verbose=1 --basedir=/usr --datadir=/var/lib/mysql --rpm > /dev/null && \
Run Code Online (Sandbox Code Playgroud)

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

解决方案

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

  1. 如果您使用已安装的卷启动容器,则随后将执行数据库初始化,并且您的数据实际上将写入主机的 FS 中
  2. 您必须将这些信息作为环境变量传递

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

警告

不过,有些警告。并不真正推荐您制作图像的方式,因为 Docker 的理念是“每个容器一个进程”。这里遇到的困难是,您必须在同一个容器(apache、Mysql 等)上启动多个服务,因此您可能必须在入口点中对这两个服务执行操作,这很令人困惑。此外,如果一项服务失败,您的容器仍将启动,但无法按预期工作。

然后,我建议将您在每个进程中所做的事情拆分为 1 个映像,然后使用原始 Docker 启动它们,或者使用类似docker-compose.

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