MySQLのセットアップとDockerfile内のダンプのインポート


127

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のビルド中にデータベースの作成をセットアップし、インポートをダンプする方法に関するアイデアはありますか?


これは、各RUNコマンドが異なるコンテナで実行されるためです。これはよくここで説明されていますstackoverflow.com/questions/17891669/...
Kuhessを

これは、RUNコマンドのコンテキストが異なることを説明しています。しかし、私はデーモンではなく、コンテキストに依存しています。
vinnylinux 2014

1
はい。しかし、それがMySQLに接続できない理由を説明しています。それは、それが最初のRUN行でのみ実行されているためです。
Kuhess 2014

SQLステートメントを実行するには、MySQLを起動し、同じコンテナーでMySQLクライアントを使用する必要がありRUNます。あなたはここにソフトウェアの複数ステップのインストールで例を見つけることができます:stackoverflow.com/questions/25899912/install-nvm-in-docker/...
Kuhess

docker -composeでサービスを確認することもできます:docs.docker.com/compose/wordpress/#build-the-projectこれを使用して、mysqlをアプリにアタッチできます
aurny2420289

回答:


122

RUNaの各命令はDockerfile異なるレイヤーで実行されます(のドキュメントでRUN説明されています)。

には、Dockerfile3つの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

どのようにしてその情報を保持できるか考えていますか?Dockerfileビルドで作成しているデータベースとテーブルは、コンテナーでデータを実行するときに使用できません。:(
vinnylinux '18

1
それはあなたが何を意味するかによります。複数のdocker run実行にわたってデータを保持したい場合は、ボリュームをマウントする必要があります。ダンプを含むコンテナだけが必要で、それ以上の変更を保持したくない場合は、内のVOLUME命令を削除できますDockerfile
Kuhess 2014

16
私が取得ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)ログの次のソリューション1.をしようとしたときmysqld_safe Starting mysqld daemon with databases from /var/lib/mysqlmysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
Vituel

1
mysqlがデータベースを作成したかどうかを確認するために、起動時にスクリプトをチェックする方がはるかに良いと思います。ある場合はそのままにし、それ以外の場合は実行mysql_init_dbしてデータベース構造にロードします。これにより、テスト時にデータベースを自動的にリセットする柔軟性が得られますが、異なるデータセットを永続化またはテストする場合は、を使用して/ var / lib / mysqlにボリュームをマウントするだけdocker run -v ...です。
tu-Reinstate Monica-dor duh 2016年

1
@trevorgrayson-それも機能しません。これでエラーERROR 2003(HY000): '127.0.0.1'(111)のMySQLサーバーに接続できません
Deep

166

公式のmysql dockerイメージの最新バージョンでは、起動時にデータをインポートできます。これが私の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

ここdocker/dataでは、docker-composeの実行元のフォルダーに関連するdata-dump.sqlを使用しています。そのsqlファイルを/docker-entrypoint-initdb.dコンテナのこのディレクトリにマウントしています。

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

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

データコンテナは、永続化のために開始状態である必要さえありません。


1
これは私見より良い答えです。自分で画像を作成することはできません。このヒントをありがとう。
Metal3d 2015年

5
ボリュームに関する1つのマイナーな変更:- ./docker/data:/docker-entrypoint-initdb.d.コンテナーディレクトリの前のを削除しました。
David Sinclair、

7
これは正しい手順ですが、ユースケースにはあまり対応していません。Dockerの利点の1つは、環境を非常にすばやく起動できることです。起動時にDockerがMySQL DBをインポートする間、3〜4分待つ必要がある場合、この利点は失われます。目的は、データベースにデータが既に含まれているコンテナーを用意して、コンテナーをできるだけ早く使用できるようにすることです。
Garreth McDaid

3
この回答はまだ最新バージョンで機能していますか?はもう機能していないようです
Daniel

2
ここでのdocker-composeの例はv3ではなくv2であることに注意してください。「volumes_from:」はv3ではサポートされていません。
アーネスト

37

私がしたことは、SQLダンプを「db-dump」フォルダにダウンロードしてマウントしました。

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

docker-compose up初めて実行すると、ダンプがdbに復元されます。


3
:実際に何が起きているのかをよりよく理解するために、実行中のスクリプトへのリンク:1を加えて1、github.com/docker-library/mariadb/blob/...を
トムImrei

6
最新でmysqlはダンプされたsqlファイルがロードされないようで、5.6を使用してもInnoDbストレージエンジンに問題があります。
2016年

1
ここでも同じですが、そのような指示があり、ロギングでinitファイルをロードしているのを見たことさえありますが、dbは空です!
ホルムス2017年

11

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

1)最初に、次のような.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"

3)次に、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を使用してdbをダンプし、mysqlフォルダ内にdata.sqlを配置します

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 's / MYSQL_DATABASE /' $ MYSQL_DATABASE '/ g' /etc/mysql/data.sql」コマンドを使用して、MYSQL_DATABASEプレースホルダーを自分が設定したDBの名前に置き換えたのです。 .envファイル。

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

これで、コンテナをビルドして実行する準備ができました


.envファイルを使用する方法が好きです。ただし、これによると、.envファイル機能はdocker-compose upコマンドを使用した場合にのみ機能し、では機能しませんdocker stack deploy。したがって、.env本番環境でファイルを使用する場合は、で導入されたDockerシークレットをチェックアウトすることをお勧めしますdocker 17.06。次に、開発フェーズdocker compose upと本番docker stack deployフェーズの両方でシークレットと一緒に.envファイルを使用できます
ira

素晴らしいアプローチですが、提案したコマンドの代わりにRUN sed -i '1s/^/CREATE DATABASE IF NOT EXISTS $ MYSQL_DATABASE ;\nUSE $ MYSQL_DATABASE を使用することをお勧めします。このようにして、お持ちのダンプファイルを使用できます。大量のデータを扱う場合に便利です。);\n/' data.sqlsed
TomaszKapłońskiDec

9

これはの使用バージョンv3ですdocker-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私が持っているdata含まれているDIR .sqlダンプファイルを。.sqlテーブルごとにダンプファイルを作成できるので、これは便利です。

走るだけdocker-compose upでいいです。データは停車地間で自動的に保持されます。あなたがしたい場合は、データを削除し、新しい「吸い込む」.sqlファイルを実行しdocker-compose down、その後docker-compose up

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


2
この答えは私を助けました。docker-compose downdocker-composeを再起動しても変化がないので、上のメモは非常に重要でした。この場合、MYSQL_DATABASEは必須変数です
nxmohamad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.