【MySQL・Windows・Docker】MySQLコンテナに dumpファイルをインポートする方法

database システム開発

<環境>
OS : Windows
DB : MySQL
仮想化ツール : Docker
コマンドラインシェル : PowerShell / git bash / コマンドプロンプト

Windows 上で起動している MySQL のコンテナに dump ファイルをインポートする方法を調べてると、結構一筋縄では行かなかった。

dumpファイルをエクスポート:PowerShellコマンド(コンテナの外から実行)

コンテナの外からダンプを取る場合、コマンドはこんな感じです。

MySQL のコンテナ名は「mysql」です。

docker-compose exec mysql mysqldump --user=root --password=password myapp01 > dump_file_20221119.sql

自身の環境で実行する時、「–user」「–password」を適当に読み替えてください。
また、スキーマは「myapp01」を指定しています。

コマンドを実行すると、dump_file_20221119.sql というファイルが出力されます。
ここまでは順調。

dumpファイルをインポート

PowerShellコマンド(コンテナの外から実行)【エラー】

通常通りインポートコマンドを実行してみる。

docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql

実行結果は、こんな感じです。

PS C:\kaki\work> docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql
発生場所 行:1 文字:90
+ ... ql --host=localhost --user=root --password=password myapp01 < dump_fi ...
+                                                                 ~
演算子 '<' は、今後の使用のために予約されています。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RedirectionNotSupported

PowerShell では、「<」を含むコマンドは使えないみたいです。

エスケープさせるにはどうすれば? と思って調べてみても、「<」はエスケープ出来ないみたいです。

(参考)
特殊文字について – PowerShell | Microsoft Learn

試しに「`<」「”<“」で実行してみましたが、どれも上手く行きませんでした。

PowerShellコマンド(コンテナの外から実行:別コマンド)【エラー】

dumpファイルをインポートする命令は「<」を使うほかにも、「-e」オプションを使う方法があります。

(参考)
MySQLリファレンスマニュアル::mysqldump — データベースバックアッププログラム

(使用例)
shell> mysql -e “source /path-to-backup/backup-file.sql” db_name

という事で実験。

docker-compose exec mysql mysql --user=root --password=password -e "source dump_file_20221119.sql" myapp01

以下、実行結果。

ERROR at line 1: Failed to open file 'dump_file_20221119.sql'

調査してみたところ、”-e” オプションを使用してファイルを使用する場合、コンテナ中のファイルが対象となるようです。

試しにコンテナの内部にdumpファイルを配置して実験してみると、ファイルを認識している事が確認できました。

ファイルを認識したところで、以下のようなエラーが出てしまいましたが。

ERROR: ASCII '\0' appeared in the statement, but this is not allowed unless option --binary-mode is enabled and mysql is run in non-interactive mode. Set --binary-mode to 1 if ASCII '\0' is expected. Query: '��m'.

powershellのデフォルト処理文字コードがCP932(≒SJIS)が原因のようです。

(参考)
Mysqlデータベースをwindowsでdumpしてubuntuでインポートする

エラーメッセージを素直に読むと、binary-mode を 1 にセットすればよいのでは?
と思って実験してみるも、上手く行かず。

(参考)
mysql Client Options

実行コマンド

docker-compose exec mysql mysql --user=root --password=password -e "source dump_file_20221119.sql" myapp01 --binary-mode

出力結果

ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'source dump_file_20221119.sql' at line 1

ちなみに、binary-mode オプションをググってみると、「–binary-mode=1」「binary-mode 0」等の良く分からない記述も多々発見できました。(どれもエラーとなりました)

何故そんな記述が乱立しているのかはよく分かりませんが、公式サイトの内容を参考にする事にします。

とはいえ、この問題が解決できたとしても、コンテナの中のファイルが対象になってしまうという時点で、採用するのは相当苦しい方法となりました。

一応、MySQL Workbench の付属コマンドを使用してエクスポートをすると、上記のエラーが発生せずにインポートできる事を確認しました。

コマンドは以下のような感じです。

MySQL Workbench の付属コマンドを使用してエクスポート

& "C:\Program Files\MySQL\MySQL Workbench 8.0 CE\mysqldump.exe" --result-file=dump_file_20221119.sql myapp01 --user=root --password=password --host=127.0.0.1 --port=3306 --set-gtid-purged=OFF --skip-lock-tables --skip-add-locks --skip-column-statistics

シェルは Powershell を使用しています。
Powershell は実行ファイルにスペースを含んでいると通常通り実行できず、上記のような小細工を挟む必要があります。

ファイルは MySQL のコンテナ内に保持する必要があります。

PowerShell スクリプトを実行【エラー】

PowerShell スクリプトを作成し、それを実行したら上手くいくのでは?
と考えて実験。

「dump-import.ps1」というファイルを作成して実行してみました。
ファイルの内容は、こんな感じ。

dump-import.ps1

Write-Host "dump importing..."

# docker-compose exec mysql bash
docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql

実行コマンドは以下。

PowerShell -ExecutionPolicy RemoteSigned .\dump-import.ps1

実行結果

PS C:\kaki\work\tmp> PowerShell -ExecutionPolicy RemoteSigned .\dump-import.ps1
発生場所 C:\kaki\work\dump-import.ps1:4 文字:90
+ ... ql --host=localhost --user=root --password=password myapp01 < dump_fi ...
+                                                                 ~
演算子 '<' は、今後の使用のために予約されています。
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : RedirectionNotSupported

結果、変わらず。

ちなみに、「docker-compose exec mysql bash」が正常に実行できる事は確認出来ました。

git bash を使う【エラー】

PowerShell を使う事を諦め、git bash で実験。

実行結果

$ docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql
the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'

「winpty」を使えばいいらしい。

良く分からないが、コマンドの先頭に「winpty」を付けて実行するといいそうな。

(参考)
the input device is not a TTY. If you are using mintty, try prefixing the command with ‘winpty’ · Issue #2888 · vercel/hyper

という事で、再び実行。

$ winpty docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql
stdin is not a tty

「stdin is not a tty」という無常のメッセージが。

調べてみると、こんなのが見つかった。

docker-compose on wsl: stdin is not a tty · Issue #166 · rprichard/winpty

It’s a long standing issue with Docker.
The way it does terminal detection only works with cmd.exe and powershell.exe at the moment. Any third-party terminal breaks that detection and gives the message.

どうやら、Docker コマンドを実行する場合は、先頭に winpty を使用できず、powershell と cmd を直接使わないといけないみたい。(Windows の場合)

ちなみに「winpty」は、こういうものらしいです。

[Git Bash] winpty コマンドについて調べてみた | MSeeeeN | 大阪発 IT メディア by MSEN

winpty コマンドは、 Windows のコンソールプログラムと UNIX の仮想端末を通信させるためのインタフェース です。

コマンドプロンプトを使う【エラー】

という事で、cmd で実験。

C:\kaki\work>docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql
the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'

先頭に「winpty」を付けて実験してみる。

C:\kaki\work\ryuki-prd>winpty docker-compose exec mysql mysql --host=localhost --user=root --password=password myapp01 < dump_file_20221119.sql
'winpty' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

ダメでした。

コンテナの内部から実行【成功(ただし、効率悪い)】

コンテナの中に入ってインポートコマンドを実行。

ホストとの共有フォルダが無い場合、volumes を編集する必要がある。
編集例、こんな感じ。

docker-compose.yml

  mysql:
    image: mysql:5.7

#(中略)

    volumes:
      - db-data:/var/lib/mysql
      - ./shared_db:/shared_db  # ホストとの共有ボリュームを追加

エクスポートしたダンプファイルを「containers/tmp」に保存し、mysql コンテナにログイン。
コンテナ内の「/tmp」ディレクトリにて、インポートコマンドを実行。

欠点:コンテナをビルドし直す必要がある。面倒。

そもそもダンプファイルをインポートするだけで docker-compose.yml を編集してコンテナをビルドし直すとか、明らかに手順がおかしいだろ。

MySQL Workbench を使う

という事で、Windows 上で起動している MySQL のコンテナに dump ファイルをインポートするのは、MySQL Workbench が一番良いのではないでしょうか。

ちなみに、上記のコマンドラインで実行した dmpファイルをインポートすると、文字コード絡みの面倒くさそうなエラーが発生したので、エクスポートも MySQL Workbench を使った方が良さそうです。

MySQL Workbench:エクスポート

1.Server → Data Export

sqlworkbench01

2.Start Export

エクスポートするスキーマを選択。(図では「myapp01」)

Export Self-Contained File を選択。
(これを選択しない場合、テーブルごとに dmpファイルが作成され、ファイル数が非常に多くなります)

出力ファイル名を設定。

その後、「Start Export」

sqlworkbench02

3.エクスポート完了

sqlworkbench03

MySQL Workbench:インポート

1.既存のスキーマを削除

「myapp01」をフルインポートするので、既存のスキーマを削除。

sqlworkbench04

2.Create Schema

削除したスキーマを再作成。(図では「myapp01」)

sqlworkbench05

Name を入力後、「Apply」

sqlworkbench06

Algorithm、Lock Type はデフォルト設定でOKです。
sqlworkbench07

スキーマが作成されます。
sqlworkbench08

3.Server → Data Import

sqlworkbench09

4.Start Import

「Import from Self-Contained File」を選択し、エクスポートファイルを指定。

「Default Target Schema」にて、対象となるスキーマを指定。

その後、「Start Import」

sqlworkbench10

5.インポート完了

sqlworkbench11

雑感

PowerShell で「<」が使えるようになってくれないかな。

コメント

タイトルとURLをコピーしました