web-dev-qa-db-ja.com

MySQLをセットアップしてDockerfile内にダンプをインポートする

LAMPプロジェクト用にDockerfileを設定しようとしていますが、MySQLの起動時にいくつか問題があります。 Dockerfileには以下の行があります。

VOLUME ["/etc/mysql", "/var/lib/mysql"]
ADD dump.sql /tmp/dump.sql
RUN /usr/bin/mysqld_safe & sleep 5s
RUN mysql -u root -e "CREATE DATABASE mydb"
RUN mysql -u root mydb < /tmp/dump.sql

しかし、私はこのエラーを受け続けます:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)

Dockerfileのビルド中にデータベースの作成とダンプのインポートを設定する方法について何かアイデアはありますか?

110
vinnylinux

RUN内の各Dockerfile命令は、異なる層で実行されます( RUNのドキュメント で説明されているように)。

Dockerfileには、3つのRUN命令があります。問題は、MySQLサーバーが最初に起動されるだけであるということです。他の人はMySQLを実行していないので、mysqlクライアントとの接続エラーが発生します。

この問題を解決するには2つの解決策があります。

解決策1:1行のRUNを使う

RUN /bin/bash -c "/usr/bin/mysqld_safe --skip-grant-tables &" && \
  sleep 5 && \
  mysql -u root -e "CREATE DATABASE mydb" && \
  mysql -u root mydb < /tmp/dump.sql

解決策2:スクリプトを使う

実行可能スクリプトinit_db.shを作成します。

#!/bin/bash
/usr/bin/mysqld_safe --skip-grant-tables &
sleep 5
mysql -u root -e "CREATE DATABASE mydb"
mysql -u root mydb < /tmp/dump.sql

これらの行をあなたのDockerfileに追加してください:

ADD init_db.sh /tmp/init_db.sh
RUN /tmp/init_db.sh
107
Kuhess

公式の最新版 mysql docker image は起動時にデータをインポートすることを可能にします。これが私のdocker-compose.ymlです。

data:
  build: docker/data/.
mysql:
  image: mysql
  ports:
    - "3307:3306"
  environment:
    MYSQL_ROOT_PASSWORD: 1234
  volumes:
    - ./docker/data:/docker-entrypoint-initdb.d
  volumes_from:
    - data

ここで、私は私のdata-dump.sqlをdocker/dataの下に置いています。これはdocker-composeが実行されているフォルダからの相対パスです。そのsqlファイルをコンテナのこのディレクトリ/docker-entrypoint-initdb.dにマウントしています。

これがどのように機能するのかを知りたい場合は、GitHubの docker-entrypoint.sh をご覧ください。彼らはデータのインポートを許可するためにこのブロックを追加しました

    echo
    for f in /docker-entrypoint-initdb.d/*; do
        case "$f" in
            *.sh)  echo "$0: running $f"; . "$f" ;;
            *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;;
            *)     echo "$0: ignoring $f" ;;
        esac
        echo
    done

Mysqlコンテナを停止して削除した後もデータを永続化したい場合は、docker-compose.ymlファイルにあるように別のデータコンテナを用意する必要があります。データコンテナDockerfileの内容は非常に単純です。

FROM n3ziniuka5/ubuntu-Oracle-jdk:14.04-JDK8

VOLUME /var/lib/mysql

CMD ["true"]

永続化のためにデータコンテナを開始状態にする必要すらありません。

151
Rajiv

私がしたことは "db-dump"フォルダに私のSQLダンプをダウンロードしてそれをマウントすることでした:

mysql:
 image: mysql:5.6
 environment:
   MYSQL_ROOT_PASSWORD: pass
 ports:
   - 3306:3306
 volumes:
   - ./db-dump:/docker-entrypoint-initdb.d

初めてdocker-compose upを実行すると、ダンプはデータベースに復元されます。

33
Petru

Docker-entrypoint-initdb.dアプローチを使用しました(ありがとう@Kuhess)しかし、私の場合は、.envファイルで定義したいくつかのパラメータに基づいてDBを作成したいので、これらを行いました。

1)最初に私のdocker rootプロジェクトディレクトリにこのような.envファイルを定義します

MYSQL_DATABASE=my_db_name
MYSQL_USER=user_test
MYSQL_PASSWORD=test
MYSQL_ROOT_PASSWORD=test
MYSQL_PORT=3306

2)それではdocker-compose.ymlファイルを定義します。だから私は私の環境変数を定義するためにargsディレクティブを使い、私はそれらを.envファイルから設定しました。

version: '2'
services:
### MySQL Container
    mysql:
        build:
            context: ./mysql
            args:
                - MYSQL_DATABASE=${MYSQL_DATABASE}
                - MYSQL_USER=${MYSQL_USER}
                - MYSQL_PASSWORD=${MYSQL_PASSWORD}
                - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
        ports:
            - "${MYSQL_PORT}:3306"

それではDockerfileを含むmysqlフォルダを定義します。だからDockerfileはこれです

FROM mysql:5.7
RUN chown -R mysql:root /var/lib/mysql/

ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD

ENV MYSQL_DATABASE=$MYSQL_DATABASE
ENV MYSQL_USER=$MYSQL_USER
ENV MYSQL_PASSWORD=$MYSQL_PASSWORD
ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD

ADD data.sql /etc/mysql/data.sql
RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql
RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d

EXPOSE 3306

4) mysqldumpを使って自分のデータベースをダンプし、data.sqlをmysqlフォルダの中に入れます。

mysqldump -h <server name> -u<user> -p <db name> > data.sql

このファイルは通常のSQLダンプファイルですが、先頭に2行追加して、ファイルを次のようにします。

--
-- Create a database using `MYSQL_DATABASE` placeholder
--
CREATE DATABASE IF NOT EXISTS `MYSQL_DATABASE`;
USE `MYSQL_DATABASE`;

-- Rest of queries
DROP TABLE IF EXISTS `x`;
CREATE TABLE `x` (..)
LOCK TABLES `x` WRITE;
INSERT INTO `x` VALUES ...;
...
...
...

それで何が起こっているかというと、私は "RUN sed -i/MYSQL_DATABASE/'$ MYSQL_DATABASE'/g '/etc/mysql/data.sql"コマンドを使用してMYSQL_DATABASEプレースホルダーを自分が設定した私のDBの名前に置き換えます。 .envファイルに.

|- docker-compose.yml
|- .env
|- mysql
     |- Dockerfile
     |- data.sql

これでコンテナを構築して実行する準備が整いました

9
Saman Shafigh

これはv3docker-compose.ymlを使った作業バージョンです。重要なのは ボリューム ディレクティブです。

mysql:
  image: mysql:5.6
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_USER: theusername
    MYSQL_PASSWORD: thepw
    MYSQL_DATABASE: mydb
  volumes:
    - ./data:/docker-entrypoint-initdb.d

docker-compose.ymlがあるディレクトリに、.sqlダンプファイルを含むdataディレクトリがあります。テーブルごとに.sqlダンプファイルを作成できるので、これはいい方法です。

私は単にdocker-compose upを実行していますし、行ってもいいです。データは自動的に停止しても保持されます。データを削除して新しい.sqlファイルを「吸い込む」場合は、docker-compose downを実行してからdocker-compose upを実行します。

ボリュームを削除せずにmysqlドッカーが/docker-entrypoint-initdb.d内のファイルを再処理する方法を知っている場合は、コメントを残してください。この回答を更新します。

5
rynop