ganache-cli(Docker版)を永続化してみた

# ganache-cli(Docker版)を永続化したい！
Docker版のganache-cliを使っていてデータを永続化したい！と思い調べてみました。

調べてみると、[ganache-cliをインストールしてオプション実行する方法](https://y-nakajo.hatenablog.com/entry/2018/12/02/142400)や、[dockerファイルを自分で作成して永続する方法](https://befool.co.jp/blog/8823-scholar/dapps-using-ganache-cli/)などみつかりましたが、ganache-cliのdockerをそのまま利用する方法が見つかりませんでした...

なので、ganache-cliのdockerをそのまま使ってぱぱっと永続化させてみました。

## 実施環境
Windows10

# やってみる
[ganache-cli GitHub](https://github.com/trufflesuite/ganache-cli)をみると、コンテナを作成する際にオプション付ければ効くようなので、とりあえずやってみました。

ganache-cliで利用するオプションは以下の3つです。
--mnemonic : ニーモニックの指定
--networkId : ネットワークIDの指定
--db : チェーンを保存するディレクトリパスの指定

チェーンを保存するディレクトリパスの他にニーモニックとネットワークIDを設定しないと永続化しないらしいので、上記オプションを設定して動作させていきたいと思います。

また、ポートフォワーディングもさせたいのでdockerで -p オプションも追加します。

それでは、やってみます！

```terminal
$ docker run -it --name gt -p 8545:8545 trufflesuite/ganache-cli -i 5777 -m "test dignity cupboard vault crazy jar sand write trap humor glimpse feel" --db /data
Ganache CLI v6.4.1 (ganache-core: 2.5.3)
(node:1) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
{ [Error: ENOENT: no such file or directory, open 'C:/Program Files (x86)/PortableGit/data/!blockHashes!0x68414881405b5bf39093d2be0612a7de4a9a3e01059a982c2078dd9ea6d944e1']
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path:
   'C:/Program Files (x86)/PortableGit/data/!blockHashes!0x68414881405b5bf39093d2be0612a7de4a9a3e01059a982c2078dd9ea6d944e1' }
eth_blockNumber

```
エラー！
パスが変なことになってる!!!

VSCode上でunixコマンドを使うために「C:\git-sdk-64\git-bash.exe」を利用しているのですが、その辺りが影響して変になっている？
と、思うので普通にコマンドプロンプトから実行しています。

```terminal
$ docker run -it --name gt -p 8545:8545 trufflesuite/ganache-cli -i 5777 -m "test dignity cupboard vault crazy jar sand write trap humor glimpse feel" --db /data
Ganache CLI v6.4.1 (ganache-core: 2.5.3)
(node:1) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
{ [Error: ENOENT: no such file or directory, open '/data/!blockHashes!0x85fe02f623d60cf97eee9951d08c54ec4fe1956ae32162999bbbcdcf0a754e8d']
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path:
   '/data/!blockHashes!0x85fe02f623d60cf97eee9951d08c54ec4fe1956ae32162999bbbcdcf0a754e8d' }
eth_blockNumber
```
エラー!
でも、パスは変ではなくなりましたね...

コンテナ上に指定したパスにディレクトリがないのが原因だと思うので、ありそうなパスを設定して再実行！

```terminal
$ docker run -it --name gt -p 8545:8545 trufflesuite/ganache-cli -i 5777 -m "test dignity cupboard vault crazy jar sand write trap humor glimpse feel" --db /root
Ganache CLI v6.4.1 (ganache-core: 2.5.3)
(node:1) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

Available Accounts
==================
(0) 0x7ac6fac041d4522f8c362d78efec60396364c559 (~100 ETH)
(1) 0xb7e478a1b92c8312ce298fd1f7500ed8bedd4da7 (~100 ETH)
(2) 0x0060cd130503b92b7ca6e35793002bd149e14486 (~100 ETH)
(3) 0x4fdd03ea775a490242cbe1382997f477d2ccc59e (~100 ETH)
(4) 0x77911940f91157234e18e77166514dbaba7f459d (~100 ETH)
(5) 0x951d94319cf3bc6b4bff5a33779c5a723b0b0c4e (~100 ETH)
(6) 0x46bfe6f8492e30d8465cfb8e71ac7b9c320e20e3 (~100 ETH)
(7) 0x5aa02a3eb327018dfa8ab746b97ce18f86ceb2f2 (~100 ETH)
(8) 0x0ea09203d9cbba052a21a2c24b68494775be57b0 (~100 ETH)
(9) 0x9e694b573a7c0f9a0112248cbe5823490e69ad8e (~100 ETH)

Private Keys
==================
(0) 0xa7cc8232ebd84cb2e7ec6548247958349245f2f7fa5ae8932ee685c3e4e337cc
(1) 0x68612f49e208e4520576b8d7c4a3a0a92099eff5ff0293c8783303a13eba92de
(2) 0xe9af3d439fe3675abbd9b1d2460b1fa2197e110bf4d7251aeb0c5e137c97e788
(3) 0x2afd91ee7448708b7be2f7c4b6973bf6ba02973bdc2b8b10aeec3dfa632add06
(4) 0x8150961114932b58b4060f0f819fd971f0f644b7b7aabef8d93177e90d623dc2
(5) 0x26eca9d40ba07290aa3601e68d010d20116942eed3b7f1dd7bc33b219d00e4b6
(6) 0xbfa75666ec62f476673084b4b4c91366394c030bf17445f72da9b90b48e757a2
(7) 0x6b13e0784d3357311c77160475fa40eeeb2ed61352db113334b6b9346e0eaffd
(8) 0xaa7006153d8c8563f54757ce862386ecfd8f3ff881d4489ebe1b315bc2d4a3a1
(9) 0xb543d4afa9f6bf79b7ea1c9db5e8c7fcbd38bcbc742a05285241c2c5da1a1c0b

HD Wallet
==================
Mnemonic:      test dignity cupboard vault crazy jar sand write trap humor glimpse feel
Base HD Path:  m/44'/60'/0'/0/{account_index}

Gas Price
==================
20000000000

Gas Limit
==================
6721975

Listening on 0.0.0.0:8545
eth_blockNumber
```
いけました！！！！

これで/rootディレクトリ配下にganache-cliのデータファイルが作成されているはずです。
docker止めてもデータが永続化していることを確認するため、Metamaskで適当に送金してアカウント1のETHを減らします。

アカウント情報確認
![WS000010.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/d1acf3b1-e77b-f330-63c1-c4613a0471a1.jpeg)

アカウント1からアカウント2に送金
![WS000011.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/890d0db3-6fc9-f8e8-156e-e0b79fe22716.jpeg)

減っていることを確認
![WS000012.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/0dc8410c-5f71-6adc-01b8-86e076bf5997.jpeg)

次に一度ganacheのコンテナを停止、再起動します。

```terminal
$ docker stop gt
gt
$ docker start gt
gt
```
ganache(Docker)は再起動のたびにデータが初期化されるので、再度Metamaskにウォレットをインポートしてアカウント1のETHが減ったままであればデータが永続化されたはずです。

念のために(キャッシュなどが残っていないように)Metamaskを一度削除してから、再度ローカルネットに接続しウォレットをインポートします。

インポート
![WS000013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/5c064a33-f50a-c6f3-d613-2174acb21d6c.jpeg)

アカウント情報表示
![WS000014.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/1afb8875-582d-a30a-9985-9bd10ffbed98.jpeg)

ETHが減っていません！初期化されていません！！
一応送金できるか確認。

![WS000015.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/e23e7cf3-8ea0-fb5f-598b-b98a9b71d99c.jpeg)

ちゃんと送金できました。
上手く永続化できていそうです。

![WS000016.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359665/b7a150d7-f08f-25df-8abb-1b47632f5caa.jpeg)

# まとめ
Docker版のganache-cliを永続化してみました。

db用のパス指定先が存在するディレクトリしかできないのが(自動で作ってくれない)少し厄介ですが、これで再起動するたびに初期化されることはなくなりました！
出力先ディレクトリ配下のファイルを複製などすれば、スナップショット的な使い方ができそうで便利そうです！
※一応、dockerの共有ディレクトリ設定(自動でディレクトリが作成されるので)のパスをdb用のパス設定で実行してみたのですが、無理でした。