Docker Composeコマンドなどのショートカット(direnv方式)

### 目的

主にローカルデバッグのために`docker compose up -d`、`docker compose down`ぐらいを実行するのはさておき、

`docker compose exec rails-app bin/rails db:migrate`
`docker compose exec database psql -U database`

など実行系のサブコマンドに続いてコンテナ内のコマンドを実行すると、入力するコマンドが長くなる、コマンドを間違えたり忘れたり覚えにいなど、めんどくさいので簡略化のためにショートカットを用いたいことがある[^forme]。

[^forme]: 自分は`history`+`!番号`で行っていました。

### 解決方法例

- プロジェクトの`bin/`配下にスクリプトを置く。
- `alias`で短い名称を付与する(`.bash_profile`等に記述)。
- `make`でコマンドを実行する（`Makefile`に記述)。

これらの方法としてQiitaの記事では、

https://qiita.com/acro5piano/items/740ea0726be6a745333d

https://qiita.com/kulikala/items/f736629497a974ca82cb

https://qiita.com/nexus4812/items/2165d16c00976a679f09

などがあり、それぞれメリット・デメリットがあると思う。
例えば、`alias`は基本的に個人的なものになりプロジェクトでは共有しにくいし、`make`は本来はビルドに関するツールなので**生成**に関するものだけを記述したい[^forme2]。

[^forme2]: 例えばC/C++などのプロジェクトでは大抵`Makefile`で**生成**のためのルールを記述するが、ここにデバッグ用のdockerの**実行**コマンドを混ぜたくない。あくまでも個人的には。

> GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.

https://www.gnu.org/software/make/

### [direnv](https://direnv.net/) による解決方法

https://qiita.com/naogify/items/94b7862a212887b2cdd8

こちらを使って、プロジェクトで共通に利用できるものとし、コマンドとして意味がわかりやすいものとして利用できる様にしてみる。

デメリットとしては、

- まず、`direnv`をインストールしなくてはいけない（逆にプロジェクト内で利用したい人だけインストールすれば良い[^forme])。
- `direnv`は本来はその名の通り、そのディレクトリーで**環境変数**を割り当ててくれるツールなので`alias`,`functions`を利用するのは想定外[^direnv73]の方法になる。
- そもそも、クレデンシャル情報などを登録することが多いので、`.gitignore`に`.envrc`を記載せよとの情報が多いのでプロジェクトの方針として管理外にする運用かもしれない。
  - しかし、https://github.com/github/gitignore のテンプレートには`.envrc`が登録済みのものは存在していません。

[^direnv73]: [Picking up aliases and functions #73](https://github.com/direnv/direnv/issues/73) - https://github.com/direnv/direnv

上記の点が許容できるなら、`direnv`利用の元、`.envrc`に次のスクリプトを記述する。

```sh
# Picking up aliases and functions
#   - https://github.com/direnv/direnv/issues/73
export_function() {
  local name=$1
  local alias_dir=$PWD/.direnv/aliases
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  local target="$alias_dir/$name"
  if declare -f "$name" >/dev/null; then
    echo "#!/usr/bin/env bash" > "$target"
    declare -f "$name" >> "$target" 2>/dev/null
    echo "$name \$@" >> "$target"
    chmod +x "$target"
  fi
}

myproject() {
  case $1 in
  up)
    docker compose up -d ;;
  restart)
    docker compose stop
    docker compose up -d ;;
  down)
    docker compose down ;;
  migrate)
    docker compose exec rails-app bin/rails db:migrate ;;
  foo)
    docker compose exec foo-service foo-command ;;
  *)
    echo "Usage:"
    echo "  ${FUNCNAME[0]} <sub command>" ;;
  esac
}
export_function myproject
```

これにて、

```sh
$ myproject up        # docker compose up
$ myproject migrate   # docker compose exec rails-app bin/rails db:migrate
$ myproject down      # docker compose down
```

こんな感じでショートカットコマンドが実現できる。そのプロジェクト(`myproject`)を起動、再起動、終了、○○を実行するという、意味がわかりやすく、覚えやすい、ショートカットとして利用できる。

実際のプロジェクトへの適用では`myproject`部分をプロジェクト名なり開発コードなりに置き換えて、`case`文の中にそれぞれの言語やフレームワークやツールのコマンド軍を記述し`;;`で終了させる。

### `direnv`の環境変数を適用したい場合

次の行を`.envrc`に追加し

```sh
if [ -e ".envrc.local" ]; then source .envrc.local; fi
```
`.envrc.local`に
```sh
export FOO_PASSWORD=p@ssw0rd
```
などし、`.gitignore`には`.envrc.local`だけ登録すれば良い。