ローカル開発に便利なShellScript

# 概要

昨今、DockerやVagrantなどが発展し、ローカル環境での開発が主流になってきています。
そんな中で、composer　installの流し忘れやmigrationの流し忘れなど様々なことが起因し、ローカルの開発環境構築に時間がかかってしまうことが少なからずあり、
また、Dockerの知識が0の場合、コマンドなどを学習する必要もあるため、業務に着手するまでの時間的コストが大幅にかかってしまうことも少なくありません。

本投稿では、そのような作業フローを簡略化し、誰でも簡単にローカルの開発環境を作成できるヘルパーの作成を紹介します。

# サンプルコード

### ディレクト階層

```
.
├── .git
├── .gitignore
├── README.md
├── build.sh
├── docker
│   ├── .env
│   ├── コンテンツ_db
│   │   ├── Dockerfile
│   │   ├── DockerfileM1
│   │   ├── cnf
│   │   │   └── db.cnf
│   │   └── db_data
│   │       └─── .gitignore
│   ├── コンテンツ_localstack
│   │   ├── .gitignore
│   │   └── data
│   ├── コンテンツ_redis
│   │   └── redis_data
│   ├── コンテンツ_web
│   │   ├── Dockerfile
│   │   ├── DockerfileM1
│   │   ├── docker.conf
│   │   ├── httpd.conf
│   │   ├── php.ini
│   │   ├── redis.ini
│   │   ├── ssl
│   │   │   └── SSL証明書
│   │   ├── ssl.conf
│   │   └── xdebug.ini
│   ├── docker-compose.yml
│   └── docker-compose_m1.yml
├── docker_helper.sh
├── laravel
│   ├── .editorconfig
│   ├── .env
│   ├── .gitattributes
│   ├── .gitignore
│   ├── .styleci.yml
│   ├── README.md
│   ├── app
│   ├── artisan
│   ├── bootstrap
│   ├── composer.json
│   ├── composer.lock
│   ├── config
│   ├── database
│   ├── info.php
│   ├── local.env
│   ├── package.json
│   ├── phpmd.xml
│   ├── phpstan.neon
│   ├── phpunit.xml
│   ├── public
│   ├── resources
│   ├── routes
│   ├── server.php
│   ├── storage
│   ├── tests
│   ├── vendor
│   └── webpack.mix.js
├── log
│   ├── .gitignore
│   └── php_errors.log
└── nfs_session
    └── .gitignore
```



```docker_helper.sh
#!/bin/sh

mode=$1
chip=`uname -m`
localip='@@割り当てを行うローカルループバックアドレス@@'
main_domain='@@ローカル用ドメインを入力@@'
scheme='@@プロジェクトのスキーマを入力@@'
document_root='@@ドキュメントルート@@'

target_yml_intel='docker-compose.yml'
target_yml_m1='docker-compose.yml'

# キャッシュなしビルド
function cleanbuild {
    select_container
    docker-compose -p $scheme -f ${target_yml} build --no-cache  ${container}
}

# ビルド
function build {
    select_container
    docker-compose -p $scheme -f ${target_yml} build ${container}
}


# up (ビルドあり)
function up {
    select_container
    docker-compose -p $scheme -f ${target_yml} up -d --build ${container}
    contents_build
    view_access_info
}

# 起動
function start {
    select_container
    docker-compose -p $scheme -f ${target_yml} start ${container}
    view_access_info
}

# 停止
function stop {
    select_container
    docker-compose -p $scheme -f ${target_yml} stop ${container}
}

# 再起動
function restart {
    select_container
    docker-compose -p $scheme -f ${target_yml} restart ${container}
    view_access_info
}

# コンテンツの構築
function contents_build {
    docker exec @@コンテンツのコンテナ名@@ /bin/bash -c "cd ${document_root} && composer install"
    docker exec @@コンテンツのコンテナ名@@ /bin/bash -c "cd ${document_root} && rm .env"
    docker exec @@コンテンツのコンテナ名@@ /bin/bash -c "cd ${document_root} && cp ${ENV}.env .env"
    docker exec @@コンテンツのコンテナ名@@ /bin/bash -c "cd ${document_root} && php artisan migrate"
}

# seederの読み込み
function load_seeders {


    if [ -z $seeders ] ; then
        search_seeders
        load_seeders
    elif [ "$seeders" = 'all' ] ; then
        array=($(ls ../laravel/database/seeders))
        for eachValue in ${array[@]}; do
            if [ "$eachValue" != "DatabaseSeeder.php" ]; then
                eachValue=`echo ${eachValue} | sed 's/\.[^\.]*$//'`
                seeders=${eachValue}
                docker exec @@コンテンツのコンテナ名@@ /bin/bash -c "cd ${document_root} && php artisan db:seed --class=${seeders}"
            fi
        done
    else [ -z $seeders ]
        docker exec @@コンテンツのコンテナ名@@ /bin/bash -c "cd ${document_root} && php artisan db:seed --class=${seeders}"
    fi

}

# シーダーの検索
function search_seeders {

    array=($(ls ../laravel/database/seeders))

    echo "どのSeederを読み込みますか？"
    echo "- \033[0;32m all\033[0;39m"
    for eachValue in ${array[@]}; do
        if [ "$eachValue" != "DatabaseSeeder.php" ]; then
            eachValue=`echo ${eachValue} | sed 's/\.[^\.]*$//'`
            echo "- \033[0;32m ${eachValue}\033[0;39m"
        fi
    done
    read seeders 


    if [ -z $seeders ] ; then
        search_seeders
    fi
}

# 対象コンテナを選択
function select_container {
    tmp=`cat $target_yml | grep container_name | grep -v "#"`
    echo "----------------------------"
    echo "対象のコンテナを選択してください"
    echo - : "\033[0;32m all or 入力なしでreturn \033[0;39m"
    echo ${tmp//container_name:/\\033[0;39m\\n- : \\033[0;32m}

    echo '\033[0;39m'
    read container

    if [ "$container" = 'all' ] ; then
        container=''
    fi
}

# 接続情報を表示
function view_access_info {
    echo "==========================================="
    echo 
    echo "hostsの設定が必要です"
    echo "$localip      $main_domain"
    echo
    echo
    echo "WebURL https://$main_domain/"
    echo
    echo
    echo "DB access"
    echo "Host : $localip"
    echo "Port : 3306"
    echo "User : root"
    echo "Passwd : @@DBのルートパスワード@@"
    echo
    echo "コンテナ内からのDBアクセス"
    echo
    echo "Host : @@DBのコンテナ名@@"
    echo "Port : 3306"
    echo "User : @@DBのユーザー名@@"
    echo "Passwd : @@DBのパスワード@@"
    echo
    echo
    echo "==========================================="
}



# ローカルループバックアドレス　のチェック
localipcheck=`ifconfig lo0 |grep $localip`
if [ -z $localipcheck ] ; then
    echo "\033[0;31mローカルループバックアドレス $localip がありません \033[0;39m"
    echo "sudo ifconfig lo0 alias $localip"
    echo "を実行してください"
    exit
fi

# チップセットの判別
if [ $chip = "arm64" ]; then
    echo "CPU : M1"
    target_yml=$target_yml_m1
else
    echo "CPU : Intel"
    target_yml=$target_yml_intel
fi

# 実行区分を選択
if [ -z $mode ] ; then
    echo 実行区分を入力してください
    echo - "\033[0;32m cleanbuild \033[0;39m (--no-cacheオプションが付きます)"
    echo - "\033[0;32m build \033[0;39m"
    echo - "\033[0;32m up \033[0;39m (ビルドします + Laravel環境の構築を行います)"
    echo - "\033[0;32m start \033[0;39m"
    echo - "\033[0;32m stop \033[0;39m"
    echo - "\033[0;32m restart \033[0;39m"
    echo - "\033[0;32m contents_build \033[0;39m (Laravel環境の更新を行います)"
    echo - "\033[0;32m load_seeders \033[0;39m (Laravel開発環境用seedersを読み込みます)"
    read mode 
fi

cd docker

# 入力に応じた関数を実行
case "$mode" in
    "cleanbuild" ) cleanbuild ;;
    "build" ) build ;;
    "up" ) up ;;
    "start" ) start ;;
    "stop" ) stop ;;
    "restart" ) restart ;;
    "contents_build" ) contents_build ;;
    "load_seeders" ) load_seeders ;;
    * ) echo "オプションが不正です"
esac

```

# 解説

### ローカルループバックアドレスの確認
ローカルループバックアドレスが端末上に設定されているか確認を行います

```
localip='@@割り当てを行うローカルループバックアドレス@@'
```


```
# ローカルループバックアドレス　のチェック
localipcheck=`ifconfig lo0 |grep $localip`
if [ -z $localipcheck ] ; then
    echo "\033[0;31mローカルループバックアドレス $localip がありません \033[0;39m"
    echo "sudo ifconfig lo0 alias $localip"
    echo "を実行してください"
    exit
fi
```

### チップセットの確認
M1チップとIntelチップで読み込むymlを変えたい場合に、自動的にチップセットを判別して、指定されたymlを読み込みます

```
chip=`uname -m`

target_yml_intel='docker-compose.yml'
target_yml_m1='docker-compose.yml'

```

```
# チップセットの判別
if [ $chip = "arm64" ]; then
    echo "CPU : M1"
    target_yml=$target_yml_m1
else
    echo "CPU : Intel"
    target_yml=$target_yml_intel
fi
```

### 実行区分を選択
実行区分が引数で指定されている場合は引数の実行区分を実行し、
指定がない場合は対話で入力を促します

```
sh docker_helper.sh {実行区分}
```


```
# 実行区分を選択
mode=$1

if [ -z $mode ] ; then
    echo 実行区分を入力してください
    echo - "\033[0;32m cleanbuild \033[0;39m (--no-cacheオプションが付きます)"
    echo - "\033[0;32m build \033[0;39m"
    echo - "\033[0;32m up \033[0;39m (ビルドします + Laravel環境の構築を行います)"
    echo - "\033[0;32m start \033[0;39m"
    echo - "\033[0;32m stop \033[0;39m"
    echo - "\033[0;32m restart \033[0;39m"
    echo - "\033[0;32m contents_build \033[0;39m (Laravel環境の更新を行います)"
    echo - "\033[0;32m load_seeders \033[0;39m (Laravel開発環境用seedersを読み込みます)"
    read mode 
fi
```


### 入力に応じた関数を実行する
入力された実行区分に合わせて、関数を実行します。
この他にも、独自で追加したいものがあれば、関数を追加で作成し、
こちらのcase に登録することで実行が可能となります

```
# 入力に応じた関数を実行
case "$mode" in
    "cleanbuild" ) cleanbuild ;;
    "build" ) build ;;
    "up" ) up ;;
    "start" ) start ;;
    "stop" ) stop ;;
    "restart" ) restart ;;
    "contents_build" ) contents_build ;;
    "load_seeders" ) load_seeders ;;
    * ) echo "オプションが不正です"
esac
```

### 接続情報の表示
コンテナが立ち上がり、接続可能な状態になる場合、接続情報を最後に表示しることで、
接続情報を他の人に確認しなくても良くなります

```
# up (ビルドあり)
function up {
    select_container
    docker-compose -p $scheme -f ${target_yml} up -d --build ${container}
    contents_build
    view_access_info
}


# 接続情報を表示
function view_access_info {
    echo "==========================================="
    echo 
    echo "hostsの設定が必要です"
    echo "$localip      $main_domain"
    echo
    echo
    echo "WebURL https://$main_domain/"
    echo
    echo
    echo "DB access"
    echo "Host : $localip"
    echo "Port : 3306"
    echo "User : root"
    echo "Passwd : @@DBのルートパスワード@@"
    echo
    echo "コンテナ内からのDBアクセス"
    echo
    echo "Host : @@DBのコンテナ名@@"
    echo "Port : 3306"
    echo "User : @@DBのユーザー名@@"
    echo "Passwd : @@DBのパスワード@@"
    echo
    echo
    echo "==========================================="
}

```


# まとめ
対話式で実行することで、表示された内容に沿って入力していくことで、環境の構築が可能となります。
本投稿では up　に環境構築をまとめてあります。

- コンテナのビルド + 起動
- コンテンツの必要な処理を実行
- アクセス情報の表示

※　ご意見、ご感想などコメントにていただけると嬉しいです。