Goで直感的に簡単にdockerを操作できるCUIツール[docui]を作りました

こんにちわ

最近dockerを使っていて、
ターミナル上で直感的にdockerを簡単に操作できるツールあったら便利だなと思い、
Goの勉強も兼ねてCUIツールを作りました。

![docui-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/66178/0ab95bd9-c209-8aa3-c6fd-45c2c7a0e426.gif)

ツール名はdocui(ドックユーアイ)で、docker cuiをの略です。
特に良い名前思いつかず、適当に決めましたが、今となっては気に入っています。

まだdockerコマンドほど機能は充実していないのですが、よく使うコマンドは実装したので公開しました。
興味ある方は使って見て頂ければと思います。

今後は少しずつ改善・機能を増やしていくので、
使ってみた感想などを頂けると助かります。

**2018/09/26 追記**
docuiの実装について[記事](https://qiita.com/gorilla0513/items/bf42d016e63a0aac4c02)を書きました。

# アジェンダ
- [コンセプト](#コンセプト)
- [導入方法](#導入方法)
- [各パネルの概要](#各パネルの概要)
- [各パネルの操作](#各パネルの操作)
    - [image list](#image-list)
    - [container list](#container-list)
    - [volume list](#volume-list)
    - [detail](#detail)
- [docui構成](#docui構成)
- [最後に](#最後に)

# コンセプト
- コマンドを打つのがめんどい
- コマンドを覚えるのがめんどくさい
- もっと高速で操作したい
- 初心者でも直感的に操作したい

これらを解決するためのツールです。

`docker start container`を`u`キーを押すだけでコンテナを起動するなど、
ショートカットを使って、より簡単かつ直感的に操作できる様にを目標にして作っています。

# 導入方法
導入する上で必要なツールは以下になります。
下記は動作済みのバージョンとなっています。

- Go Ver.1.11
- Docker Engine Ver.18.06.1-ce
- Git

すでに環境整っている方は以下の手順でインストールできます。

```
$ git clone https://github.com/skanehira/docui
$ cd docui
$ go install
```

各ツールを含めた具体的の導入手順は[こちら](https://github.com/skanehira/docui/wiki/docui)を見て頂ければと思います。
一つ注意点として、現時点docuiはunixドメインソケットにのみ対応しているため、tcpが動作しているdocker engineには接続できないです。
将来的にリモートでdocker engineの操作も対応していく予定です。

# 各パネルの概要
[README](https://github.com/skanehira/docui)と[wiki](https://github.com/skanehira/docui/wiki/docui)に使い方を書いてありますので、ここではdocuiの画面について説明していきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/be1b837b-12fb-fc01-c5fd-2e3bb0d80a46.png)

基本的以下のパネル構成と操作になります。

- `image list`
    - イメージ一覧(docker images)
    - イメージ検索(docker search)
    - 取得(pull)
    - コンテナ作成(docker create)
    - 削除(docker rmi)
    - 削除(docker rmi -f dangling=true)
    - インポート(docker import)
    - 保存(docker save)
    - ロード(docker load)
    - 詳細(docker inspect)
- `container list`
    - コンテナ一覧(docker ps --all)
    - 起動(docker start)
    - 停止(docker stop)
    - 削除(docker rm)
    - イメージに保存(docker commit)
    - エクスポート(docker export)
- `volume list`
    - ボリューム一覧(docker volume list)
    - ボリューム作成(docker volume create)
    - ボリューム削除(docker volume rm)
    - ボリューム削除(docker volume prune)
- `detail`
    - イメージ/コンテナ/ボリュームの詳細表示(docker inspect結果)
- `navigate`
    - 各パネルで使用できるキーマップの表示

# 各パネルの操作
各パネルでのどんな操作ができるかについて説明していきます。

## image list
- **イメージ取得**
`docker pull`と同等。
イメージ名を入力してpullする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/424f715d-be82-904a-b118-9928a70e86e5.png)

- **イメージ検索**
`docker search`と同等。
イメージ名を入力して検索する。
検索結果が表示されるので、一覧からイメージを選択して`Enter`でイメージをpullする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/dd8d78e2-1087-8b2b-da8a-95ed8917d614.png)

- **イメージ保存**
`docker save`と同等。
指定したイメージを保存する。
ファイルパスは相対パスか絶対パスでなければいけない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/c61c1800-edef-cade-1814-8d00d4d1d002.png)

- **イメージimport**
`docker import`と同等。
ファイルとイメージ名を指定してイメージをimportする。
ファイルパスは相対パスか絶対パスでなければいけない。
import時のtagを省略するとlatestになる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/e1b017dc-959b-4b8d-b958-90b099691a0a.png)

- **イメージload**
`docker load`と同等。
指定したファイルをloadする。
ファイルパスは相対パスか絶対パスでなければいけない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/49795724-d1a4-730e-5c6f-13c38f6a8a19.png)

- **コンテナの作成**
`docker create`と同等。
選択したイメージをもとにコンテナを作成する。
※*環境変数と起動コマンドを複数設定したい場合は`,`区切りで入力する。*
※*設定値に環境変数を使用した場合はOSの値を取得してセットする。*
　例：`PATH=$PATH:$GOPATH`
※*現時点でポートとボリュームの複数マッピングはできないが、今後それを可能にしていく。*
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/352e8192-e2c2-3e29-6dc1-8f5aa5f36aa7.png)

- **イメージ詳細**
`docker inspect`と同等。
イメージの詳細を`detail`パネルで確認することができる。
スクロールしたい場合は、`detail`パネルで操作する必要がある。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/6ec2f8c1-65ed-a920-e212-1b7a0a93ad34.png)

- **イメージ削除**
`docker rmi`と同様。
指定したイメージを削除する。
`n`で削除をキャンセル。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/5841a152-27dd-a31a-a9c5-a914ee5b086b.png)

- **イメージ削除(-f dangling=true)**
ビルド過程でできる`<none>`というようなイメージかつ使用されていないイメージを削除。
`n`で削除をキャンセル。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/6b002ad6-f805-5c19-289c-ddc99a8318a5.png)

## container list
- **コンテナの状態更新**
5秒間隔でコンテナの状態が更新される。

- **コンテナ起動**
`docker start`と同等。
指定したコンテナを起動する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/4693a43b-1c25-c3fe-102e-692a6d02efda.png)

- **コンテナ停止**
`docker stop`と同等。
指定したコンテナを停止する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/393921d6-8aaa-b42d-0ca4-9f17cc79e827.png)

- **コンテナexport**
`docker export`と同等。
指定したコンテナをexportする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/8e8c0c41-13bd-ee73-2c17-6b08b77b83e0.png)

- **コンテナcommit**
`docker commit`と同等。
指定したコンテナをイメージに保存する。
tagを省略すると`latest`になる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/3f278618-ea63-b683-2353-85e533666261.png)

- **コンテナ削除**
`docker rm `と同等。
指定したコンテナを削除する。
`n`で削除をキャンセル。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/975cadb7-8264-63f7-85fc-bd0aab9865d1.png)

- **コンテナ詳細**
`docker inspect`と同等。
コンテナの詳細を`detail`パネルで確認することができる。
スクロールしたい場合は、`detail`パネルで操作する必要がある。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/45f0a798-2993-d5e6-bc64-1055271e9886.png)

## volume list
- **ボリューム一覧**
`docker volume list`と同等。
5秒間隔で更新される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/c678bb31-a8b1-7c4d-5c97-e78652eb3628.png)

- **ボリューム作成**
`docker volume create`と同等。
※ラベルやオプションを複数追加したい場合はスペース区切りで入力する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/dd7aa04a-e360-0df4-e404-acceadbb65dd.png)

- **ボリューム削除**
`docker volume rm`と同等。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/ef6f831b-dc5f-5644-6be3-500e8d9414bb.png)

- **ボリューム削除（prune)**
`docker volume prune`と同等。
使用していないボリュームをすべて削除する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/bcf61af5-912c-f53d-cbc7-b9e8ea81bc8c.png)

## detail
- **イメージ/コンテナ/ボリュームの詳細表示**  
イメージ、コンテナ、ボリュームの中身によっては、画面に収まらない場合がある。  
その場合は`j`と`k`でカーソル移動もしくは`d`と`u`でページ移動して内容を確認できる。  
![detail.gif](https://qiita-image-store.s3.amazonaws.com/0/66178/19b3d966-71c1-d323-841f-f06c391e3487.gif)

# docui構成
ディレクトリ構成は以下になっています。

```
docui
├── LICENSE
├── README.md
├── build
│   ├── Dockerfile
│   └── build.sh
├── common
│   └── common.go
├── docker
│   └── docker.go
├── main.go
├── panel
│   ├── containerPanel.go
│   ├── detailPanel.go
│   ├── gui.go
│   ├── imagePanel.go
│   ├── infoPanel.go
│   ├── inputPanel.go
│   ├── navigatePanel.go
│   ├── searchImagePanel.go
│   ├── searchImageResultPanel.go
│   └── volumePanel.go
└── wiki.md
```

パッケージは`main`を除き、`docker`と`panel`と`common`の3つになっています。

- **docker**
dockerを操作の役割を持つ。

- **common**
全体で使用するような関数などを持つ。

- **panel**
画面描写・更新・キーバインドなど、画面に関する操作の役割を持つ。
そのため、メインの処理はこのパッケージに詰まっている。

ちなみに、docuiで使用しているライブラリは以下2つです。

- **[gocui](https://github.com/jroimartin/gocui)**
cuiライブラリです。
主に画面生成と描写・キーバインド設定を使っています。
非同期の描写更新もサポートしていますが、
プログレスバーといったリアルタイム更新はなぜかうまく動作しませんでした。
gocui自体はキーバインドライブラリとして[termbox-go](https://github.com/nsf/termbox-go)というのを使用していて、
キーイベント処理はtermbox-goが担っています。

- **[docker-client](https://github.com/fsouza/go-dockerclient)**
dockerクライアントライブラリです。
dockerに関する操作はこちらを通して行っています。
公式のmobyプロジェクトがあるので、将来的にmobyに移行しようと考えています。

ソースは[github](https://github.com/skanehira/docui)にあげてありますので、
興味ある方はぜひ見てみてください。

アドバイス頂けると喜びます。

# 最後に
今回はざっくりツールについて紹介しました。
dockerを使って開発を行っている方など、ぜひ使ってみてください。
フィードバックもお待ちしております。

次回は実際作った時に躓いた箇所について記事を書きます。
docui自体はシンプルなので、そんなに書くことはないのですが、
自分の備忘録も兼ねて記事にしようと考えています。