bash/zshとfzfでDocker関連コマンドの補完を行う方法

dockerコマンドはパラメータにコンテナIDやイメージIDを取るケースがあって入力が面倒です。 公式のbash/zsh用補完スクリプトを使うと各種ID類も補完できるようになるのですが、 Docker for Macをインストールするだけではそれらのスクリプトは有効にならないので、使い方を解説します。

また、fzfを使って候補のフィルタリングや複数選択を楽に行えるようにする方法についても説明します。

最終的にはこんな感じになります。

dockerとdocker-composeの補完スクリプト

Docker for Macにはbashとzsh用の補完スクリプトが同梱されています。

% ls -1 /Applications/Docker.app/Contents/Resources/etc/
docker-compose.bash-completion
docker-compose.zsh-completion
docker-machine.bash-completion
docker-machine.zsh-completion
docker.bash-completion
docker.fish-completion
docker.zsh-completion

適切に設定すれば下記のようにサブコマンドやイメージIDなどを補完できます。

zshの場合

下記のように補完スクリプトのリンクを作って ~/.zshrc で読み込むようにすると、 dockerコマンドとdocker-composeコマンドに補完が効くようになります。

$ mkdir ~/.zsh/completions
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker.zsh-completion ~/.zsh/completions/_docker
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-compose.zsh-completion ~/.zsh/completions/_docker-compose
# ~/.zshrc

if [ -e ~/.zsh/completions ]; then
  fpath=(~/.zsh/completions $fpath)
fi

autoload -U compinit
compinit

bashの場合

bash-completionが必要です。Homebrewでインストールできます。

$ brew install bash-completion

下記のように補完スクリプトのリンクを作って ~/.bash_profile で読み込むようにすると、 dockerコマンドとdocker-composeコマンドに補完が効くようになります。

$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-compose.bash-completion /usr/local/etc/bash_completion.d/
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker.bash-completion /usr/local/etc/bash_completion.d/
# ~/.bash_profile

if [ -f $(brew --prefix)/etc/bash_completion ]; then
  . $(brew --prefix)/etc/bash_completion
fi

fzfによる補完

fzfと組み合わせると、docker rmdocker rmiのようなコマンドで、 パラメータのコンテナやイメージをフィルタしたり複数選択したりできます。

fzfのインストール

Homebrewでインストールできます。

$ brew install fzf

fzfのインストールスクリプトを実行します。

$ /usr/local/opt/fzf/install

質問に答えると ~/.fzf.zsh~/.fzf.bashが作成されます。 ~/.zshrcに下記を追加してこれを有効にします。

# ~/.zshrc

[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
export FZF_COMPLETION_TRIGGER="," # default: '**'

FZF_COMPLETION_TRIGGERは、fzfによる補完を開始するトリガーです。 ここで指定した文字列の後にタブを入力するとfzfによる補完が始まります。 デフォルトでは ** ですが、zshのグロブ補完と重複していて気持ち悪いので、上記の例では,に変更しています。 この記事のスクリーンキャストでもこの設定を有効にしていて、docker rmi ,まで入力してからタブを押して補完を開始しています。

docker-fzf-completionのインストール

下記のリポジトリから docker-fzf.zsh を取得して、~/.zshrcで読み込みます。

https://github.com/kwhrtsk/docker-fzf-completion

git cloneでもコピペでもなんでもいいので、ローカルマシンのどこかに置いてsourceで読み込んでください。 bashの場合も docker-fzf.bash を取得して ~/.bash_profilesource すれば使えると思います。

自分の場合はzshで下記のようにしています。

$ ghq get https://github.com/kwhrtsk/docker-fzf-completion

# これと同じ
# mkdir -p mkdir ~/.ghq/github.com/kwhrtsk/
# cd ~/.ghq/github.com/kwhrtsk/
# git clone https://github.com/kwhrtsk/docker-fzf-completion
# ~/.zshrc

source ~/.ghq/github.com/kwhrtsk/docker-fzf-completion/docker-fzf.zsh

上記のスクリプトは下記のリポジトリをフォークして作った二次著作物です。(MITライセンス)

https://github.com/Mike-Now/docker-fzf-completion

オリジナルに対して下記の修正を行っています。

  • 補完対象のコマンドを追加
    • attach, kill, logs, stats, historyなどコンテナとイメージに関するものほぼ全部
    • Docker 1.13で追加されたcontainerimageのサブコマンド群ほぼ全部
  • コンテナの状態を考慮した補完
    • startには停止中のコンテナしか補完しないetc
  • イメージに対する操作でリポジトリ名:タグが空(<none>:<none>)の場合は代わりにIMAGE_IDを使うように修正

docker-fzf-completionの使い方

docker rundocker rmのようなコマンドの後、FZF_COMPLETION_TRIGGERで指定した文字列(下記の例では,)を入力してタブを押すと補完が始まります。

  • プロンプトに文字列を入力するとフィルタされます。
  • 矢印キーまたはCtrl+PCtrl+Nでカーソルを上下に移動します。
  • Enterを押すとカーソル位置のコンテナ名またはイメージIDがコマンドのパラメータとして入力されます。
  • 補完中にタブを押すとカーソル位置のアイテムを複数選択できます。
  • Ctrl+Aで全選択、Ctrl+Dで全選択解除、Ctrl+Tで全選択をトグルします。

参考

Command-line completion | Docker Documentation