<環境>
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」を付けて実行するといいそうな。
という事で、再び実行。
$ 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
2.Start Export
エクスポートするスキーマを選択。(図では「myapp01」)
Export Self-Contained File を選択。
(これを選択しない場合、テーブルごとに dmpファイルが作成され、ファイル数が非常に多くなります)
出力ファイル名を設定。
その後、「Start Export」
3.エクスポート完了
MySQL Workbench:インポート
1.既存のスキーマを削除
「myapp01」をフルインポートするので、既存のスキーマを削除。
2.Create Schema
削除したスキーマを再作成。(図では「myapp01」)
Name を入力後、「Apply」
Algorithm、Lock Type はデフォルト設定でOKです。
スキーマが作成されます。
3.Server → Data Import
4.Start Import
「Import from Self-Contained File」を選択し、エクスポートファイルを指定。
「Default Target Schema」にて、対象となるスキーマを指定。
その後、「Start Import」
5.インポート完了
雑感
PowerShell で「<」が使えるようになってくれないかな。
コメント