2016-12-15 2 views
5

Я новичок в Docker. Я успешно создал Docker изображение со следующим Dockerfile:Сохранение данных MySQL в 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 \ 
    [email protected] 

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 в разные контейнеры?

Edit: Если я не монтировать локальный объем (т.е. project_dir/data) и запустить контейнер, получить TTY оболочки, я вижу, что /var/lib/mysql есть несколько файлов, которые я предполагаю, что необходимо для запуска MySQL и его исходные базы данных. Но если я монтирую свой локальный том и ls внутри /var/lib/mysql (внутри контейнера), он пуст. Вот почему MySQL не запускается, и я не могу сохранить данные с за пределами контейнера. Мой вопрос: как я могу запустить его и сохранить данные из локального каталога.

+2

Изображение должно быть независимым от вашей локальной среды. Вы должны использовать VOLUME, чтобы отметить каталог, который будет монтироваться снаружи. И когда вы запускаете образ в докере, вы подключаете его к своей локальной среде с использованием параметров '-v'. Этот способ работает даже на Kubernetes. – JosMac

+0

Не используйте Docker для этого прецедента. Docker - это технология приложений. Вы создаете контейнер ОС/Золотое изображение. Используйте виртуальную машину или если вы настаиваете на том, чтобы использовать контейнеры только для охлаждения, используйте контейнер ОС (например, OpenVZ). У вас будет много проблем с вашим текущим aproach. – bartimar

ответ

4

Проблема:

Что происходит здесь в том, что вы создаете пустую базу данных, а Docker изображение строится:

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

Но при создании контейнера из этого образа, смонтируйте том в папке /var/lib/mysql. Это скрывает данные ваших контейнеров, чтобы открыть папку вашего хоста. Таким образом, вы видите пустую папку.

Решение:

Если вы посмотрите на https://hub.docker.com/_/mysql/, вы увидите, что эта проблема решается путем создания базы данных, когда контейнер на самом деле начинается не тогда, когда создается изображение. Это отвечает как ваши вопросы:

  1. Если вы начинаете свой контейнер с смонтированным тома, то инициализация базы данных будет выполняться после этого, и Ваши данные будут фактически написаны в FS вашего хоста
  2. Вы должны пройти те информация как переменные env

Другими словами, запустите свою БД со сценарием в ENTRYPOINT, а не непосредственно на изображении.

Предупреждения:

Некоторые предупреждения, хотя. То, как вы сделали свое изображение, на самом деле не рекомендуется, потому что философия Докера является «одним процессом на контейнер». Трудность, с которой вы здесь сталкиваетесь, заключается в том, что вам придется запускать несколько сервисов в одном контейнере (apache, Mysql и т. Д.), Поэтому вам, возможно, придется делать что-то в обеих точках входа, что запутывает. Кроме того, одна служба не работает, ваш контейнер все равно будет работать, но не работает, как ожидалось.

Я бы предложил разделить то, что вы сделали, как на 1 изображение за процесс, либо начать их с необработанного Docker, либо пользователь примерно docker-compose.

Кроме того, это принесет вам пользу в том, что вы сможете использовать уже существующие и настраиваемые изображения, начиная с Docker Hub: https://hub.docker.com. Меньшая работа для вас и меньше склонности к ошибкам.

+0

Спасибо. Делает большой смысл. Тем не менее, я действительно новичок в Docker. Не могли бы вы немного объяснить, как добавить скрипт в 'ENTRYPOINT'? Не используется ли 'ENTRYPOINT' внутри Dockerfile? Если да, то в чем разница между _running сценария, когда изображение построено_ и _ризуем скрипт при запуске контейнера_? Разве Dockerfile не используется только для создания изображения? – abhisek

+0

Взгляните на https://github.com/docker-library/mysql/tree/10eb5eab8d3d793c49a701ed7a42e1e5d1c9bb59/8.0. Вот как выглядит образ MySQL. Еще раз, я рекомендую вам использовать его (выберите нужную версию mysql). Теперь, чтобы ответить на ваши вопросы: 'ENTRYPOINT' - это команда, которая должна выполняться при запуске контейнера. Для этого вам нужно определить его в файле Docker. Так что да, Dockerfile используется для создания образа, но также дает указания о том, что делать, когда вы создаете из него контейнер. Например, настройте и запустите процесс. –

-1

Когда у вас есть база данных в контейнере докера, использование тома - единственный способ пойти. Возможно, мы должны указать, что «база данных внутри вашего контейнера» означает не использование тома и наличие данных в стандартном 10 ГБ (или больше, если размер по умолчанию был изменен), а база данных в объеме означает docker run -v myvolume...

документы doc. docker.com/engine/tutorials/dockervolumes является обязательным для просмотра

Я полностью согласен с ответом Александра, но я думаю, что неправильно помещать вашу базу данных в ваш контейнер, а также по другой причине. По умолчанию размер изображения (так что контейнер при его запуске) составляет 10 ГБ. Это должно быть довольно удобно для некоторых исполняемых файлов, библиотек и файлов конфигурации. Вы можете изменить это значение по умолчанию и добавить большее значение при создании изображения. Но что происходит, когда вы нажимаете этот новый предел? Предположим, вы думаете, что размер вашей базы данных будет 100 ГБ, а на самом деле вы помещаете больше данных, чем планировалось, и вам в конечном итоге нужно в 5 или 20 раз больше? Том может быть в SAN и при необходимости расширен.

+0

Что значит: «поместите свою базу данных в свой контейнер»? Вы имеете в виду НЕ использовать громкость? –

+0

Нет, я имею в виду, что использование объема - единственный способ для хранения базы данных. – user2915097

+0

Хорошо, тогда мой ответ может быть недостаточно ясным, потому что это то, что я советую :). Вы видите, как я мог бы его улучшить? –

Смежные вопросы