コンテナに入るのに docker ps してから docker start して docker exec するのめんどくさいから一度にできるコマンド作った

結論

作った。Goで。 github.com

経緯

パソコン起動してから、dockerのコンテナに入るのにコマンドをいくつも叩かないといけないのがめんどくさかったから。 叩くコマンドは以下の3つ * docker ps -a * docker start <コンテナ名> * docker exec -it -e <デフォルト環境変数> <コンテナ名> bash

コマンドの内容としては、単純で docker ps -a --format "{{.Name}}" で出力されたコンテナ名を cho で選択して、それを docker start に渡して実行した後、docker exec をコンテナ名とともに起動しているだけ。

cho に関しては、以下のリンクを参照。パイプで渡された文字列に対して行単位で選択ができるコマンド。今回作ったコマンドを実行するには必要なので、別途 go get https://github.com/mattn/cho でインストールしておく必要がある。 mattn.kaoriya.net

知見

docker ps の書式指定

docker ps--format というのがあり、表示するフォーマットをGoのtemplate書式で指定できる。 docker ps --format "{{.Name}}" とすれば、コンテナ名のみ表示され docker ps --format "table {{.ID}}\t{{.Labels}}"とすれば、ヘッダ行を追加した状態でIDLabel`が表示されるので便利。

go-pipeline の Output で返される文字列

docker pscho を繋ぐために、今回は go-pipeline (GitHub - mattn/go-pipeline) を使用したが、返される文字列をそのまま exec.Command() の引数として使うとエラーとなる。理由としては文字列の最後に改行文字が入っており、コンテナ名が存在しない。となるからだ。解決方法としては、最後の1バイトを取り除いた部分文字列を渡すことで解決した。

docker exec が動かない

上記問題を解決したうえで docker exec が実行時にエラーとなっていた。原因は exec.Command で作成した Cmd 構造体の Stdin と Stdout にちゃんと標準入力と標準出力をセットしていなかったことが原因だった。nil のままだと NULLデバイス(os.DevNull)にアクセスするようだ。(https://golang.org/pkg/os/exec/#Cmd)

今後の課題

  • 今は 環境変数を固定で指定しているが、コマンドを実行するタイミングで指定できるようにもしたい
  • また、デフォルトの環境変数を rcファイルに設定しておいて、それをデフォルトで読み込めるようにもしたい
  • 現状の名前が goto_docker_container と長いので、何か良い名前を付けてやりたい