DockerでUbuntu＋zsh＋prezto環境をつくった～はじめてさわったsedとの格闘～

Dockerひさしぶりに触ってみるか、ということで仮想環境にUbuntu＋zsh＋preztoをぶっこんでみました。

**[環境]**
ホスト環境:
&nbsp;&nbsp;&nbsp;OS&nbsp;:&nbsp;Ubuntu 18.04
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;macOS Catalina 10.15.2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows10 Pro 1909
&nbsp;&nbsp;&nbsp;Docker&nbsp;:&nbsp;19.03.5

仮想環境
&nbsp;&nbsp;&nbsp;OS&nbsp;:&nbsp;Ubuntu18.04
&nbsp;&nbsp;&nbsp;zsh
&nbsp;&nbsp;&nbsp;prezto

Dockerの各OSへのインストールは情報があふれているので、必要に応じて検索してください。

公式のUbuntuイメージを引っ張ってきてzshとpreztoをインストールするだけでは面白くない、ということでDockerfileを作成してみました。(たいした処理は書いていませんが 汗)

***--追記--***
zshのシンタックスハイライトの有効化と`ls`の表示色を変更しています

***--修正(2020/01/12)--***
Dockerfileのコメント追加およびDockerコンテナの日本語対応と不要行のコメントアウト

```shell:Dockerfile
  1: # Ubuntu公式リポジトリよりイメージを取得
  2: FROM amd64/ubuntu:latest
  3:
  4: # メンテナーの設定
  5: MAINTAINER ponono-ponono
  6:
  7: # Docker環境下でのPATH設定
  8: ENV PATH /usr/local/bin:$PATH
  9:
 10: # apt-get installする際のフロントエンドエラー対策
 11: ENV DEBIAN_FRONTEND noninteractive
 12:
 13: # apt-get installする際に表示されるエラーメッセージ(次行)の抑止
 14: # debconf: delaying package configuration, since apt-utils is not installed
 15: ENV DEBCONF_NOWARNINGS yes
 16:
 17: # ロケールを日本語UTF-8に設定
 18: # これによりDocker環境下で日本語入力が可能となる 
 19: RUN apt-get update \
 20:     && apt-get install -y locales \
 21:     && locale-gen ja_JP.UTF-8
 22:
 23: # ロケール環境変数の設定
 24: ENV LANG ja_JP.UTF-8
 25: ENV LANGUAGE ja_JP:ja
 26: ENV LC_ALL ja_JP.UTF-8
 27: 
 28: # apt-getした際のmanパッケージインストールエラーの回避策と
 29: # manコマンドのインストール
 30: RUN rm /etc/dpkg/dpkg.cfg.d/excludes \
 31:     && apt-get update \
 32:     && apt-get install -y man;
 33:
 34: # zshのインストールと環境整備用パッケージのインストール
 35: RUN apt-get update \
 36:    && apt-get install -y zsh vim sed git
 37:
 38: # zshの実行
 39: RUN zsh
 40:
 41: # 環境変数の設定
 42: ENV SHELL /usr/bin/zsh
 43:
 44: # ログインシェルを指定(アカウント情報の作成) 
 45: RUN sed -i.bak "s|$HOME:|$HOME:$SHELL|" /etc/passwd
 46:
 47: # ユーザーとホームディレクトリの環境変数設定
 48: ENV USER ponono-ponono
 49: ENV HOME /home/$USER
 50:
 51: # 一般ユーザーアカウントを追加
 52: RUN useradd -m $USER
 53: # 一般ユーザーにsudo権限を付与
 54: RUN gpasswd -a $USER sudo
 55: # 一般ユーザーのパスワード設定
 56: RUN echo "$USER:ponono-ponono_pass" | chpasswd
 57:
 58: # 以降のRUN/CMDを実行するユーザー
 59: USER $USER
 60:
 61: # 以降の作業ディレクトリを指定
 62: WORKDIR $HOME
 63:
 64: # preztoをクローンしてくる
 65: RUN git clone --recursive \
 66:         https://github.com/sorin-ionescu/prezto.git \
 67:         $HOME/.zprezto
 68:
 69: # preztoの設定ファイルのシンボリックリンクを
 70: # ホームディレクトリに張る
 71: RUN ln -s $HOME/.zprezto/runcoms/zlogin    $HOME/.zlogin \
 72:     && ln -s $HOME/.zprezto/runcoms/zlogout   $HOME/.zlogout \
 73:     && ln -s $HOME/.zprezto/runcoms/zpreztorc $HOME/.zpreztorc \
 74:     && ln -s $HOME/.zprezto/runcoms/zprofile  $HOME/.zprofile \
 75:     && ln -s $HOME/.zprezto/runcoms/zshenv    $HOME/.zshenv \
 76:     && ln -s $HOME/.zprezto/runcoms/zshrc     $HOME/.zshrc
 77:
 78: # LANG環境変数のエクスポートコマンドを.zshrcに出力
 79: RUN echo "export LANG=ja_JP.UTF-8" >> $HOME/.zshrc
 80:
 81: # dockerでは不要のためコメントアウト
 82: # RUN chsh -s /usr/bin/zsh
 83:
 84: # lsコマンドの色指定用設定をファイルに出力
 85: RUN dircolors -p > $HOME/.dircolors
 86:
 87: # lsコマンドのファイル属性
 88: # "ディレクトリ", "シンボリックリンク", "実行ファイル"の表示色を指定
 89: RUN sed -i "s|DIR 01;34|DIR 01;36|" $HOME/.dircolors \
 90:     && sed -i "s|LINK 01;36|LINK 01;33|" $HOME/.dircolors \
 91:     && sed -i "s|EXEC 01;32|EXEC 01;34|" $HOME/.dircolors
 92:
 93: # preztoのprompt(表示テーマ)をzshrcで指定
 94: # lsコマンドの色指定ファイルの読み込みとlsコマンドのエイリアスを設定
 95: # sedで-iオプションを使いシンボリックリンクを編集するとリンクが切れてしまうため
 96: # リンク元ファイルを直接編集している
 97: RUN echo "\nprompt fade red\n" >> $HOME/.zprezto/runcoms/zshrc \
 98:     && echo "eval \`dircolors --sh $HOME/.dircolors\`" >> $HOME/.zprezto/runcoms/zshrc \
 99:     && sed -i "/^eval LS_COLORS='';/d" $HOME/.zprezto/runcoms/zshrc \
100:     && sed -i "/^export LS_COLORS/d" $HOME/.zprezto/runcoms/zshrc \
101:     && echo "alias ls='ls --color=auto'\n" >> $HOME/.zprezto/runcoms/zshrc
102:
103: # preztoのシンタックスハイライトを有効にするため設定をzpreztorcに出力
104: # sedで-iオプションを使いシンボリックリンクを編集するとリンクが切れてしまうため
105: # リンク元ファイルを直接編集している
106: RUN sed -i "s|'completion' \\\\|'completion' \\\\\n  'syntax-highlighting' \\\\|" $HOME/.zprezto/runcoms/zpreztorc \
107:     && sed -i "s|Syntax Highlighting\n#\n|Syntax Highlighting\n#\nzstyle ':prezto:module:syntax-highlighting' color 'yes'\n|" $HOME/.zprezto/runcoms/zpreztorc
```

イメージ一覧の表示

```
$ docker images
```

結果

```
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu18.04         zsh-prezto          2b1ab8382e84        2 hours ago         358MB
amd64/ubuntu        latest              549b9b86cb8d        2 weeks ago         64.2MB
```

イメージファイルのビルド

```
$ docker build -t [リポジトリ名(REPOSITORY)][:[タグ(TAG)]] .
```

タグを指定しない場合、":"以降を入力しなくても大丈夫です。
その時はデフォルトでタグが"latest"になります。

コンテナの状態を確認

```
$ docker ps -a
```

結果

```
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS               NAMES
8433091d059c        ubuntu18.04:zsh-prezto   "/bin/bash"         5 seconds ago       Up 4 seconds                            my_ubuntu
```

コンテナの実行

```
$ docker run -it --name [コンテナ名(NAMES)] -d [リポジトリ名]:[タグ]
```

コンテナのSTATUSが`Exited (0)`になっている場合、コンテナを再起動する

```
$ docker restart [コンテナ名]
```

仮想環境へ入る

```
$ docker exec -it [コンテナ名] zsh
```

`docker ps -a`で`STATUS`が`Up`になっていないと`docker exec`がエラーになります。

仮想環境を抜け、ホストOSに戻る

```
$ exit
```


コンテナを停止する

```
$ docker stop [コンテナ名]
```

コンテナを削除する

```
$ docker rm [コンテナ名]
```

イメージを削除する

```
$ docker rmi [リポジトリ名]:[タグ]
```

~~注)イメージを削除する場合、タグは省略できません。~~

苦労したところといえば、"~/.zprezto/runcoms"配下の設定ファイルにシンボリックリンクを張るところです。(14〜19行)
本来なら、以下のスクリプトでループ回しながらシンボリックリンクを張れるんですが、あれこれ格闘するもうまくいかず。結局、試行錯誤している時間が勿体なくベタ書きしてしまいました(汗)

```shell:
$ setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
```

ほかには、いままでsedを使ったことがなく、文字のエスケープや改行文字について調べたりするのに時間を食ってしまいました。

~~あと、apt-getしている最中にapt-utuilsがインストールされていないよとお叱りを受けますが、apt-utilsをインストールしてもメッセージが消えなかったのでほったらかしにしています。(動作上、影響がないので)~~&nbsp;&nbsp;&nbsp;<font color="red">解決 (Dockerfile 13〜15行目)</font>

Dockerのコンテナはできるだけシンプルにというのがあると思うので、zsh+preztoをインストールするのが正しいことなのか甚だ疑問が残りますが、Docker上でzsh+preztoをインストールできるのかといった興味とDockerの仮想環境上で開発をすることを前提として環境構築してみました。

もし、Dockerで開発したいけどデフォルトの環境だと見づらい方がいらっしゃいましたら、↑のDockerfileからコピペして使ってみてください。


**[参考]**
[Zsh + Prezto で快適コマンド環境を構築する](https://dev.classmethod.jp/tool/zsh-prezto/)
[lsコマンドの色を変更する](https://qiita.com/PinkPhayate/items/a670e7e7935baea988f2)
[Dockerで開発環境を仮想化する](https://qiita.com/Riliumph/items/3b09e0804d7a04dff85b)
[【Docker】ubuntuの環境で日本語入力を可能にする](https://qiita.com/n_oshiumi/items/cfe91c60730f602b38eb)
[Docker: コンテナのlocaleを設定したい](https://qiita.com/suin/items/856bf782d0d295352e51)
[コンテナ内でmanを読みたい](https://qiita.com/hiromitsu7/items/0788f2e2212224ac6825)
[Docker で apt-get install するときに TERM 系のエラーが出る](https://maku77.github.io/docker/term-error.html)
["debconf: delaying package configuration, since apt-utils is not installed"を表示しないようにする](https://qiita.com/haessal/items/0a83fe9fa1ac00ed5ee9)