🐳

Docker コンテナーで Powerline を試してみた

2023/01/29に公開

Powerline とは

Powerline とはプロンプトの表示をわかりやすく綺麗にするためのソフトウェアです。Rust 実装の starship、Go 実装の powerline-go、Python 実装の powerline-shell といったものがあります。Linux 系の OS を使っているとすでに導入している人も多いと思いますが、そうでないと知らない人も多いと思います。

自分は Linux をメインで使っていますが、最近は Docker コンテナーへアタッチして作業をすることも増えてきています。そういった環境の中で、Docker コンテナーでも Powerline を使えるといいかもしれないと思って試してみました。

Powlerline がどういうものか知らない人でも、Docker で試してみるなら手軽にできるので、やってみてください。

Docker コンテナーで Powerline を使う方法

Docker コンテナーで Powerline を使いたい場合は、コンテナー起動時にインストールして使えるようにする方法と、カスタムの Docker イメージを作って使えるようにする方法があります。カスタムの Docker イメージを作るのは少し大袈裟な感じがします。

コンテナー起動時にインストールする場合は、使用する Docker イメージを Ubuntu 系に限定して、利用する Powerline の実行ファイルは Docker ボリュームへ用意しておくのが良さそうです。この方法だと、ネットワークが必要になるのは Powerline の実行ファイルを Docker ボリュームへダウンロードしておく時だけになるので、ネットワークが有効になっていないとコンテナーが起動できないといったことが起きません。

ということで、開発用コンテナーで starship を使えるようにしてみました。実装は下記にあります。コードを見たほうがわかる人は、実装を直接見たほうが良いと思います。

https://github.com/hiro345g/devnode-starship

必要なもの

devnode-starship を動作をさせるには、次のものが必要です。

  • Doker Engine
  • Docker Compose Plugin

これらは Docker Desktop をインストールしてあれば使えるようになっているはずです。

ディレクトリー構成

作成するファイルのディレクトリーは次の通りです。

devnode-starship/
├── admin/
│   └── docker-compose.yml
├── docker-compose.yml
└── script/
    ├── download_starship.sh
    └── install_starship.sh

docker-compose.yml が starship が使える Docker コンテナーになります。admin/docker-compose.yml は準備時に使う作業用コンテナーの起動・停止などで使います。

script/download_starship.sh は starship の実行ファイルをダウンロードするためのスクリプトで、script/install_starship.sh は Docker コンテナー内の node ユーザーがstarship を使えるようにするスクリプトです。

準備

開発用コンテナーには Debian bullseye をベースとしたものを基本的には使うことにして、これに合わせてイメージを選択します。ここでは node:18.13.0-bullseye にしました。このイメージには最初から git、ssh、curl といったコマンドが含まれていて使いやすいです。

ちなみに、Debian と Ubuntu のバージョン対応は次の表のようになります。使用する Docker イメージの選定時には、ベースとなっている Docker イメージの確認をしておくと作成する Docker 関連のファイルの再利用性が高くなります。

表 Debian と Ubuntu のバージョン対応

Debian バージョン名 Debian バージョン Ubuntu バージョン名 Ubuntu バージョン
bookworm 12 jammy 22.04
bullseye 11 focal 20.04
bionic 10 buster 18.04

開発コンテナーが使う starship を Docker ボリュームへダウンロードするために、作業用コンテナーを先に用意します。また、この作業用コンテナーを使って starship を Docker ボリュームへインストールするスクリプトの作成や動作確認をします。

作業用コンテナーは root ユーザーで動作させるので admin/docker-compose.yml として用意します。

admin/docker-compose.yml
name: devnode-starship-admin
services:
  devnode-starship-admin:
    image: node:18.13.0-bullseye
    container_name: devnode-starship-admin
    hostname: devnode-starship-admin
    init: true
    tty: true
    volumes:
      - download-data:/home/node/Download
      - ../script:/script:ro

volumes:
  download-data:
    name: devnode-download-data

script/download_starship.sh は次のようになります。GitHub のリリースから最新のものをダウンロードして devnode-starship-admin:/home/node/Download と対応する devnode-download-data ボリュームへ保存しています。

script/download_starship.sh
#!/bin/sh

STARSHIP_CMD=starship
STARSHIP_CMD_FILE=/home/node/Download/${STARSHIP_CMD}

if [ ! -e ${STARSHIP_CMD_FILE} ]; then
  cd /home/node/Download
  wget https://github.com/starship/starship/releases/latest/download/starship-x86_64-unknown-linux-musl.tar.gz
  tar xf starship-x86_64-unknown-linux-musl.tar.gz
  if [ "x$(id -u)" = "x0" ]; then
    chown node:node starship-x86_64-unknown-linux-musl.tar.gz ${STARSHIP_CMD}
  fi
fi

これらを使って devnode-starship 用の devnode-download-data ボリュームを用意します。
次のように実行します。

docker compose run --rm devnode-starship-admin sh /script/download_starship.sh
docker compose run --rm devnode-starship-admin chown node:node /home/node/Download
docker compose down

これで使用するボリュームが用意されます。
なお、後で devnode-starship コンテナーを起動したときに、コンテナー内の /home/node/Download の所有者が root となっている場合は、chown を含むコマンドの行をもう一度実行します。

利用

devnode-starship 用のコンテナーは node ユーザーで利用します。docker-compose.yml は次のようになります。

docker-compose.yml
name: devnode-starship
services:
  devnode-starship:
    image: node:18.13.0-bullseye
    container_name: devnode-starship
    hostname: devnode-starship
    init: true
    tty: true
    user: ${USER_UID:-1000}:${USER_GID:-1000}
    command: sh -c "sh /script/install_starship.sh && sleep infinity"
    working_dir: /home/node
    volumes:
      - download-data:/home/node/Download
      - ./script:/script:ro

volumes:
  download-data:
    name: devnode-download-data
    external: true

command: でインストール用のスクリプトを実行してから、sleep コマンドで待機するようにしています。このコンテナーでも devnode-download-data ボリュームを /home/node/Download へマウントしています。

インストール用のスクリプト script/install_starship.sh は次のようになります。

script/install_starship.sh
#!/bin/sh
STARSHIP_CMD=starship
STARSHIP_CMD_FILE=/home/node/Download/${STARSHIP_CMD}
SCRIPT_DIR=$(cd $(dirname $0);pwd)

sh ${SCRIPT_DIR}/download_starship.sh

if [ ! -e /home/node/.local/bin ]; then
  mkdir -p /home/node/.local/bin
  if [ "x$(id -u)" = "x0" ]; then
    chown node:node /home/node/.local/bin
  fi
fi

if [ ! -e /home/node/.local/bin/${STARSHIP_CMD} ]; then
  cp ${STARSHIP_CMD_FILE} /home/node/.local/bin/
  if [ "x$(id -u)" = "x0" ]; then
    chown node:node /home/node/.local/bin/${STARSHIP_CMD}
  fi
  echo 'eval "$(${HOME}/.local/bin/starship init bash)"' >> /home/node/.bashrc
fi

if [ ! -e /home/node/.config ]; then
  mkdir /home/node/.config
  if [ "x$(id -u)" = "x0" ]; then
    chown node:node /home/node/.config
  fi
fi

if [ ! -e /home/node/.config/starship.toml ]; then
  /home/node/.local/bin/${STARSHIP_CMD} preset plain-text-symbols \
    | sed 's/success_symbol = "/success_symbol = "🐳/' \
    | sed 's/error_symbol = "/error_symbol = "🐳/' \
    | sed 's/vimcmd_symbol = "/vimcmd_symbol = "🐳/' \
    > /home/node/.config/starship.toml
  if [ "x$(id -u)" = "x0" ]; then
    chown node:node /home/node/.config/starship.toml
  fi
fi

簡単なスクリプトなので、なにをしているかはコードを見ればわかるでしょう。
starship preset plain-text-symbols というコマンドを実行して starship の plain-text-symbols というプリセットで starship.toml 用データを生成しています。
これを、sed コマンドで置換して少しカスタマイズしてあります。

必要なファイルを用意したら、次のようにして devnode-starship コンテナーを起動した後に、コンテナーへアタッチします。

docker compose up -d
docker compose exec devnode-starship bash

実行例は次のようになります。

$ docker compose exec devnode-starship bash

~ 
⬢ [Docker] 🐳> cd Download/

~/Download 
⬢ [Docker] 🐳> ls
starship  starship-x86_64-unknown-linux-musl.tar.gz

~/Download 
⬢ [Docker] 🐳> 

この表示だと少し寂しいですが、Git リポジトリーや Node.js アプリ開発用のディレクトリーなどに cd で移動すると、結構綺麗な表示になります。

興味を持たれたら、是非、試してみてください。

Discussion