ワンコマンドで立ち上がるdApp開発環境をDockerで生成する(Truffle&Ganache)

# はじめに
DApp開発を学習するうえで簡易なものを作ってみようということで、環境構築から。
思っていたよりも簡単にできた。

WSL2&docker環境を想定。
dockerの使い方的な説明には触れない。



## 完成品のリポジトリ

https://github.com/PokoPoko2ry/dapp-sample

# 環境概要
Dockerでワンコマンドで立ち上がるよう各コンテナの定義をする。

調べてみると、Solidity開発ならフレームワークとしてTruffleと
ローカルのブロックチェーンネットワークにGanacheがよいということで
これらを利用した環境を作成してゆく。
最終的な構成はこのような形

```
.
├── app
│   ├── build
│   │   └── contracts
│   │       ├── ConvertLib.json
│   │       └── MetaCoin.json
│   ├── contracts
│   │   ├── ConvertLib.sol
│   │   └── MetaCoin.sol
│   ├── LICENSE
│   ├── migrations
│   │   └── 1_deploy_contracts.js
│   ├── test
│   │   ├── metacoin.js
│   │   └── TestMetaCoin.sol
│   └── truffle-config.js
└── docker
    ├── docker-compose.yml
    ├── ganache
    │   └── dockerfile
    └── truffle
        └── dockerfile
```

## Truffleの構築
公式のインストール情報ページを参考にイメージを構築していく
https://trufflesuite.com/docs/truffle/how-to/install/

node、npmが必要なようなのでnodeのイメージを基に作成

```yml:truffle/dockerfile
FROM node:18-bullseye-slim


# どこまで影響があるかは不明だが、公式のドキュメントに下記のような記述があるためとりあえず
# nodeユーザーを用いて構築する。
# Warning: Avoid using the sudo command when installing Truffle, this can cause permission errors.

ARG UID=1000
RUN  npm install -g npm && chgrp -R node /usr/ && chmod 770 -R /usr && chmod 770 -R /srv
USER ${UID}

# truffleのインストール
RUN npm install -g truffle
```

## Ganacheの構築
公式のREADMEによるとimageが公開されているようなのでありがたく利用させてもらう。
https://github.com/trufflesuite/ganache#docker

``` yml:truffle/dockerfile
FROM trufflesuite/ganache-cli:v6.12.2
```

## docker-compose構築
TruffleとGanacheを合わせた環境を定義する。
作成したら、docker-compose.ymlの階層でdocker-compose build & docker-compose up -dで
コンテナを立ち上げる
```yml:docker-compose.yml
version: '3.6'
services:
  truffle:
    container_name: truffle
    build: ./truffle
    ports:
      - "8888:8888"
    tty: true
    volumes:
      - ../app:/srv/:cached
  ganache:
    container_name: ganache
    build: ./ganache
    ports:
       - "8545:8545"
    stdin_open: true
    tty: true

```

## Dapp立ち上げ&動作確認
立ち上がったTruffleコンテナに入り、サンプルアプリをDLする。

```
$ truffle unbox metacoin

Starting unbox...
=================

✓ Preparing to download box
✓ Downloading
✓ Cleaning up temporary files
✓ Setting up box

Unbox successful, sweet!

Commands:

  Compile contracts: truffle compile
  Migrate contracts: truffle migrate
  Test contracts:    truffle test

```

これでサンプルのDapp、Metacoinが生成された。
ganacheのコンテナに接続するため、truffle-config.jsの内容を編集する。

developmentの部分のコメントアウトを外し、ホストをganacheのコンテナに向ける。
docker-composeで立ち上げている場合はコンテナ名で接続できる。


```truffle-config.js
  networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache, geth, or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
    development: {
      host: 'ganache', // Localhost (default: none)
      port: 8545, // Standard Ethereum port (default: none)
      network_id: '*', // Any network (default: none)
    },
    //
    // goerli: {
    //   provider: () => new HDWalletProvider(mnemonic, `https://goerli.infura.io/v3/${infuraProjectId}`),
    //   network_id: 5,       // Goerli's id
    //   chain_id: 5
    // }
  },
```
テスト実行
```
$ truffle test

Compiling your contracts...
===========================
> Compiling ./contracts/ConvertLib.sol-bin. Attempt #1
> Compiling ./contracts/MetaCoin.sol
> Compiling ./test/TestMetaCoin.sol
> Artifacts written to /tmp/test--43-TUQM2FrW3HNE
> Compiled successfully using:
   - solc: 0.8.13+commit.abaa5c0e.Emscripten.clang
⠴ Fetching solc version list from solc-bin. Attempt #1
✓ Downloading compiler. Attempt #1.
  TestMetaCoinc version list from solc-bin. Attempt #1
    ✔ testInitialBalanceUsingDeployedContract (73ms)#1
    ✔ testInitialBalanceWithNewMetaCoin (49ms)tempt #1
✓ Downloading compiler. Attempt #1.
  Contract: MetaCoin
    ✔ should put 10000 MetaCoin in the first account (59ms)
    ✔ should call a function that depends on a linked library (65ms)
    ✔ should send coin correctly (122ms)in. Attempt #1
✓ Downloading compiler. Attempt #1.

  5 passing (4s)
```

## 参考
https://trufflesuite.com/docs/truffle/how-to/install/