taskfile.dev でdocker-compose等の引数多すぎ問題を一挙にシンプルにする



# TLDR
- golangで書かれたタスクランナー
- Taskfile.ymlでタスク定義
- ```task dev```とか```task bash```とかいう感じで呼び出し
- ```task cp_from --- target.file``` みたいな感じで引数も渡せる
- それぞれのタスクから他のタスクを呼び出すことも可能
- ```docker-compose -f...``` を```task dev```などに割り当てて引数付き呼び出しを簡略化

# 導入
みなさん今日もdocker使ってますか？
引数多すぎて指がつったりしてませんか??
僕はこの件がずっと気になっていて、どうやったら解決できるかを思い出しては色々調べていました。

phpならcomposer.jsonに書く?
jsならpackage.jsonに書く?
それともgruntとかgulp??
ないなー、それはないなー。
dockerにまつわる操作をまとめたいんだから違うよねー。

とあるPaaSのサポートさんは、Makefileとかに書けば、とか提案してくれたんですが、依存関係もないし、今更Makefileかよと思いこの件しばらく棚上げしてました。そうしたら昨日ふと見つけたこのプロジェクト。

# taskfile.dev
<div align="center">
<img src="https://taskfile.dev/Logo.png" width="300" >
</div>

[taskfile.dev](https://taskfile.dev)

## インストール
MacならHomebrewでインストール可能です。

```bash
brew install go-task/tap/go-task
```

[その他各パッケージマネージャー(Snap, Scoop, Aur)にも対応。](https://taskfile.dev/#/installation)

## タスク定義と呼び出し
```yml
# Taskfile.yml
version: '3'

hello:
  cmds:
    - echo 'hello world' 
```
ここでは```hello```がタスク名ですね。cmdsで実行時に呼び出されるコマンドを定義。
コマンドラインから```task タスク名```でタスクを呼び出します。

```bash
❯ task hello

task: [hello] echo 'hello world'
hello world
```

## 変数、環境変数、引数、.envなどなど

[詳細はUsageに書いていますが](https://taskfile.dev/#/usage)、だいたいみんながやりたいと思いそうなことを紹介しておきます。

### 変数

独自に変数を定義することができます。```vars:```で定義します。先頭に書いてグローバルに定義しても良いし各タスクローカルの変数を定義することもできます。[スタイルガイド](https://taskfile.dev/#/styleguide)には、大文字スネークケースが推奨されています。
変数参照時は ```{{ .VAR＿NAME }}```と書きます。

```yml
vars:
  MY_NAME: 'foo'

tasks:
  hello_global:
    cmds:
      - echo 'hello world' {{ .MY_NAME }}

  hello_local:
    vars:
      MY_NAME: 'foobar'
    cmds:
      - echo 'hello world' {{ .MY_NAME }}

```

```bash
❯ task hello_global

task: [hello] echo 'hello world' foo
hello world foo
```

ローカル変数はグローバル変数を上書きしますが、特に警告は出ないようです。

```bash
❯ task hello_local

task: [hello] echo 'hello world' foobar
hello world foobar
```

### 環境変数
環境変数は```{{ .ENVVAR_NAME }}```で呼び出せます。
環境変数はグローバルのvarsでは上書きできますが、

```yml
vars:
  SHELL: "sheeeeel"

tasks:
  hello_env:
    cmds:
      - echo 'hello' {{ .SHELL }}
```
```
❯ task hello_env

task: [hello_dotenv] echo 'hello' sheeeeel
hello sheeeeel
```
ローカルのvarsでは上書きできません。

```yml
tasks:
  hello_env:
    vars:
      SHELL: "sheeeeel"
    cmds:
      - echo 'hello' {{ .SHELL }}
```
```
❯ task hello_env

task: [hello_dotenv] echo 'hello' /bin/bash
hello /bin/bash
```


### 引数
taskコマンド呼び出し時の引数は ```{{ .CLI_ARGS }}```で参照。

```yml
tasks:
  hello_args:
    cmds:
      - echo 'hello' {{ .CLI_ARGS }}
```

呼び出し時は``` -- ```をつけて呼び出しコマンド名と区別します。

```bash
❯ task hello_args -- string from args

task: [hello_args] echo 'hello' string from args
hello string from args
```

### .env

.envファイルは```dotenv```指示子で読み込みを指定します。

```.env
# .env
DOTVAR='value from .env'
```

```yml
dotenv: ['.env']

tasks:
  hello_dotenv:
    cmds:
      - echo 'hello' {{ .DOTVAR }}
```

```bash
❯ task hello_dotenv

task: [hello_dotenv] echo 'hello world' value from .env
hello value from .env
```


## 実際の使用例

僕は複雑になるdocker-composeの呼び出しを定義して簡略にしてみました。

```yml

version: '3'

vars:
  BASE_CMD: 'docker-compose'
  DEV_COMPOSE_FILE: 'docker-compose-develop.yml'
  APP_CONTAINER: 'app'
  APP_CONTAINER_IMAGE: 'myproject_app_1'

tasks:
  dev:
    cmds:
      - "{{ .BASE_CMD }} -f {{ .DEV_COMPOSE_FILE }} up"

  bash:
    cmds:
      - "{{ .BASE_CMD }} -f {{ .DEV_COMPOSE_FILE }} exec {{ .APP_CONTAINER }} bash"

  cp_from:
    cmds:
      - CONTAINER_ID=$(docker ps| grep {{ .APP_CONTAINER_IMAGE }} | awk '{ print $1 }'); docker cp $CONTAINER_ID:/var/www/html/{{ .CLI_ARGS}} .

  cp_to:
    cmds:
      - CONTAINER_ID=$(docker ps| grep {{ .APP_CONTAINER_IMAGE }} | awk '{ print $1 }'); docker cp {{ .CLI_ARGS}} $CONTAINER_ID:/var/www/html/
```


その他、色々使い道を思いついたらまた追記していこうと思います。