この記事はひとり開発 アドベントカレンダー 2019年の8日目の記事です。
開発環境の紹介 (VM->Docker with tmux, vim)と題して、ここ3年に渡る私のターミナル周りの開発環境の推移をまとめていく記事です。
2017年 dotfiles + git
dotfilesとはなんぞやについては今年のアドベントカレンダー1発目に詳しく書かれているので参照してみてください。
ようこそdotfilesの世界へ
インストール方法
$ bash -c "$(curl -fsSL git.io/dotu1)"
ワンコマンドでインストールできます。ただし、インストール時に表示される注意書きにもあるように、インストール先のホームディレクトリ上のファイルを上書きするので、上書きされたくないファイルがあったら予めリネームするなどして退避してください。あくまで自分用にしか作っていないので、インストールするときはファイルを上書きするし、アンインストール方法は用意されていません。ファイルが損失しても責任を取りかねます。
ジョブ内容
- dotfilesをクローンしてファイルを上書きします。
- bacpacを使ってArchlinuxで使っていたのパッケージをインストールします。
- pyenvを使用してpython 環境を構築します -> 今はdockerでpython環境を構築しているので基本的に使いません。
- デフォルトのshellをzshに変更します。
bacpac
元はこれAUR - bacpac
フォークしたのが自分のGist Gist - u1and0/.bacpac.md Secret
パッケージマネージャにpacmanを使っているOSなら使えます。
インストールしたパッケージをgitで管理するshell script。古いのかもしれないです。
元のソースと比べてbacpac cat
, bacpac diff
のサブコマンドと、zshの補完機能_bacpac
を追加しています。
submoduleで管理しています。
[submodule "bacpac"]
path = bacpac
url = https://gist.github.com/u1and0/8bd32ade8d95988b52b03a1b08297b96
ignore = dirty # dotfilesには関係ないパッケージの追加・削除による差分を感知しない
zsh
- .bash_aliases
- .bash_functions
- .bashrc
- .zsh_aliases
- .zsh_functions
- .zsh_keybinds
- .zshrc
- .zplug.zsh
この辺で管理しています。
.zshrc呼び出すときに.bashrc
をsourceしているので、bashの設定をオーバーライドしています。
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
if [ -f ~/.zsh_aliases ]; then
. ~/.zsh_aliases
fi
if [ -f ~/.zsh_functions ]; then
. ~/.zsh_functions
fi
zplug
zplugはzshに入れるプラグインマネージャです。
以下の設定を.zshrcに書いておくことでzplugをgithubからクローンしてzplug及びzplugで管理されるプラグインをインストールしてくれます。
# 2回目以降は.zplug/init.zshを読み込んでロード
if [[ -f ${HOME}/.zplug/init.zsh ]]; then
export ZPLUG_LOADFILE=${HOME}/.zplug.zsh
source ~/.zplug/init.zsh
# Auto installer
if ! zplug check --verbose; then
printf "Install? [y/N]: "
if read -q; then
echo; zplug install
fi
fi
# コマンドをリンクして、PATH に追加し、プラグインを読み込む
zplug load
# 初回はzplugをcurlでインストール
else; printf "Install zplug? [y/N]: "
if read -q; then
curl -sL --proto-redir -all, https\
https://raw.githubusercontent.com/zplug/installer/master/installer.zsh |
zsh && source $0 # .zshrc再リロード
fi
fi
tmux
- .tmux.conf
- .tmux/plugins/tpm
この辺で管理しています。
submoduleも入れています。
[submodule ".tmux/plugins/tpm"]
path = .tmux/plugins/tpm
url = https://github.com/tmux-plugins/tpm
主な使い方
- セッション切り替え
- C-Space J
- C-Space K
- セッションデタッチ
- C-Space d
- ウィンドウの新規作成
- C-Space c
- ウィンドウの削除
- C-Space x
- ウィンドウ切り替え
- C-Space L
- C-Space H
- ペイン切り替え
- C-Space j
- C-Space k
- C-Space l
- C-Space h
- ペインの新規作成(横分割)
- C-Space "
- ペインの新規作成(縦分割)
- C-Space %
- コピー(ヤンク)
- C-Space SpaceでコピーモードにはいってからSpaceと移動キーで選択してy
- ペースト
- C-Space p
nvim
エディタはneovimです。
dotfilesでは以下のファイルで管理しています。
プラグインマネージャはShougo/dein.vim
- .config/nvim/init.vim: neovimが呼び出されるときに
source
する。これが親 - .config/nvim/keymap.rc.vim :neovimのキーバインド
- .config/nvim/options.rc.vim: neovimのオプション
set
で設定するもの - .config/nvim/autocmd.rc.vim:
autocmd
で設定するもの - .config/nvim/ftplugin/arduino.vim: arduino使うときに入れてたけど今使ってない
- .config/nvim/ftplugin/html.vim: htmlファイル開いたときのタブ設定など
- .config/nvim/ftplugin/javascript.vim: jsファイル開いたときのタブ設定など
- .config/dein/plugins.toml: 常に呼び出されるdein管理のプラグイン
- .config/dein/lazy.toml: 特定の条件下で呼び出されるdein管理のプラグイン
- .config/dein/lightline.toml: UIかっこよくする
- .config/dein/vim-airline.toml: UIかっこよくする。今は使っていない
- .config/dein/python.toml: python3+としてコンパイルされているneovimでないと使えないプラグイン
python環境
python環境を使い分ける〜pyenvとcondaのメモ〜
pyenv+condaを使ってpython環境の構築をする記事です。
2018年 vagrant + Virtual Box
Archlinux on Vagrant 日本語/GUI/docker セットアップスクリプト
この辺からドットファイルとパッケージだけではなくinfrastructure as code, 環境周りを一括して管理するようになりました。
これまでWindows機でCmder上でやっていたところ、watchコマンドが使えなかったりで本格的なLinuxを使いたいと思い、Windows10上にvagrant+VirtualBoxを使ってオレオレArchlinuxイメージを作って色々いじっていました。
Linuxマシンになってなるべく困難は調べものして解決するつもりでしたが、どうしてもうまく行かなくなったときは仮想マシンのスナップショット機能で過去に戻ればいいし、最悪新しい環境をもう一つ作ればいいやという軽い気持ちで使い始めました。
2019年 docker
この辺からWindows10を捨ててUbuntu18.04に移行しました。
VirtualBoxではパフォーマンス面でリソースを100%活かしきれていないことが気になったので、CPUやメモリをホストと共有できるコンテナ仮想環境dockerに開発環境を移行しました。ポータブルなので、一度イメージ構築してしまえば新しいマシンに移ってもイメージをpullするだけなので、引っ越しに抵抗がありませんね。
オレオレdocker開発環境を作ってみたにも自分用docker環境構築を書きました。
この記事ではさらにその続きで、docker-composeを使って各dockerコンテナをワンコマンドで立ち上げようという試みです。
# maintainer: u1and0 <e01.ando60@gmail.com>
# version 3.7 for docker version 18.06+
# see https://docs.docker.com/compose/compose-file/
# What for:
# docker in docker dev.env
# master: zsh & zplug env. Pairents for all docker image.
# python: python env. It can use ipython & jupyter
#
# Usage:
# $ cd /path/to/composeset
# $ docker-compose start master
# Starting master ... done
# Starting jupyter ... done
# Starting vimgo ... done
# $ docker exec -it composeset_master_1 zsh -l
#
version: '3'
services:
master:
image: "u1and0/myenv:latest"
tty: "true"
volumes:
- "${HOME}:/home/vagrant"
- "${HOME}/.zsh_history:/root/.zsh_history"
- "${HOME}/yankring_history_v2.txt:/root/yankring_history_v2.txt"
- "/mnt/e/Users/U1and0:/mnt"
- "/var/run/docker.sock:/var/run/docker.sock"
working_dir: "/home/vagrant"
environment:
- "HOST=master"
command: "zsh"
jupyter:
# jupyter tagはpasswordを設定したイメージ
# [Jupyter on Dockerでパスワードの設定方法が分からないあなたへ](https://qiita.com/Yusuke-Shimizu/items/731ca71b3c4c3649ec7f)
image: "u1and0/pyenv:jupyter"
volumes:
- "${HOME}:/home/vagrant"
- "/mnt/e/Users/U1and0:/mnt"
working_dir: "/home/vagrant/Dropbox/Program/python"
environment:
- "PYTHONPATH=/home/vagrant/Dropbox/Program/python"
command: "bash -c 'source /root/.pyenvrc && source activate && jupyter notebook --allow-root'"
ports:
- "8888:8888"
vimgo:
image: "u1and0/vim-go:zplug1.2.0-r1"
tty: "true"
working_dir: "/root/go/src"
volumes:
- "${HOME}:/home/vagrant"
- "${HOME}/.zsh_history:/root/.zsh_history"
- "${HOME}/yankring_history_v2.txt:/root/yankring_history_v2.txt"
- "/mnt/e/Users/U1and0:/mnt"
environment:
- "GO111MODULE=on"
- "HOST=go"
ports:
- "8080:8080"
cap_add:
- "SYS_PTRACE" # for golang debugger
dotfilesでは .docker/config.json でC-/ C-PからC-\ C-/にデタッチキーを変更しています。
{
"detachKeys": "ctrl-\\,/"
}
イメージ名 | 使用用途 |
---|---|
image: "u1and0/myenv:latest" | DinD |
image: "u1and0/pyenv:jupyter" | Python環境 |
image: "u1and0/vim-go:zplug1.2.0-r1" | Go環境 |
使い方
$ cd /path/to/composeset # 1
$ docker-compose start master # 2
Starting master ... done
Starting jupyter ... done
Starting vimgo ... done
$ docker exec -it composeset_master_1 zsh -l # 3
- docker-compose.ymlがある場所で
-
docker-compose start
するだけで、docker-compose.ymlに記載している全環境をワンコマンドで立ち上げます。
ハマりどころとしては、DinDをするためにホストマシンの/var/run/docker.sock
をボリュームにマウントすること。そして、tty:true
としておかないとcommand
がzshなどのshellを指定しているimageが一瞬で落ちてしまうことです。 -
docker exec ...
で各環境にattachします。
とりあえずDinD(Docker in Docker)用のimage: masterにいつもログインして、tmuxを起動し、作業に入ります。
Goで開発するなら
$ docker exec -it composeset_vimgo_1 zsh -l
Pythonで開発するなら
$ docker exec -it composeset_jupyter_1 bash -c "source ~/.pyenvrc && source activate && ipython"
$ docker exec -it composeset_jupyter_1 bash -c "source ~/.pyenvrc && source activate && nvim +PyenvActivate"
commandにjupyter notebookを指定しているのでlocalhost:8888
をブラウザのURL欄に打てばJupyter Notebookに接続できます。
Pythonパッケージマネジャにpyenv+condaを使っているのでログイン時必ずsource activate
しないといけません。
source activate
するためのパスが通っていないためにsource ~/.pyenvrc
しないといけません。
.pyenvrcは自分で書いたものです。
#!/bin/sh
# pyenv config file
# pyenvのあるpath
export PYENV_ROOT="$HOME/pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
# pyenv実行
eval "$(pyenv init -)"
# bin/activate bin/deactivateを使うため
PATH="$PYENV_ROOT/versions/miniconda3-latest/bin:$PATH"
PATH="/usr/bin:$PATH"
export PATH
PYTHONPATH="${HOME}/Dropbox/Program/python/:$PYTHONPATH"
PYTHONPATH="${HOME}/home/python/:$PYTHONPATH"
export PYTHONPATH
このへんまだまだベストな状態ではありません。Dockerでパッケージ管理するなら、condaなんて使わずにpipだけでいいのでわー?condaが依存パッケージ集めてくれるから楽なのか?今は「今までcondaで管理してきたから」という理由だけでcondaを使い続けています。
その他の開発するなら
masterイメージでshell scriptとかやったりします。qiita記事もこのイメージ内のneovimで作成しています。
2020年以降は
またVT-x系仮想環境に戻ろうと思います。
その上でDocker立ち上げようかと。
なぜなら、ホストマシンの電源を切ると開発の流れが途切れるからです。
常用ではホストマシンは就寝前にスリープモードにするのですが、ホストマシンのアップデートとかはいったりなんか調子おかしくなったときはリブートせざるを得ないときが必ずあります。
上で説明したdotfilesにはターミナルの復元ツールが多数含まれています。
- すべてのファイルはDropboxに保存して、万一ロールバックしたいときでも簡単に復元できる。
- そもそもgitが使えばコードの差分を見ながら過去に戻れたり別バージョンを残しておいたりできる。
- tmux-plugins/tmux-resurrectでtmuxのセッションを復元できる。Space C-rに割り当てています。
-
tpope/vim-obsessionでneovim/vimのセッションを復元できる。立ち上げるときに
nvim -S
というSオプションをつける。 - docker-composeもdocker-compose.ymlのディレクトリに飛んで
docker-compose start
するだけでコンテナ郡は一発復元する。
このように復元方法には困らないのですが、しかしながら一回途切れるものは途切れる。そのへんやっぱり仮想マシン用意してセッションを保存しておけばホストの電源落としてもかならずセッション復元するし、スナップショットも取れる。そしてDockerに移住したもののそんなにリソースを食う処理って滅多にやらない。
そんなわけでまたVirtualBoxかなんかに戻ろうと思います。
今注目しているのがkvmとmultipass。
multipassはこの記事「仮想環境multipassを試す」で少しいじってみた。VirtualBoxでやったところで、結局CUI環境はDockerで構築するわけなので、間に挟むイメージはなんでもいい、ということで安直にUbuntu一択になってしまうわけです。multipassは選べるイメージがUbuntuのみでシンプルに作られているので気に入りました。
しかしながら、ポートフォワーディングが今のところできないみたいなので、サーバー・ブラウザ・web使う系の開発に使えないのでまだ様子見です。
kvmはインストールがうまくいかないので、試行錯誤中です。
時間かかるようだったらvagrant+VirtualBoxで良いかなと思います。慣れているし。
まとめ
開発環境構築は永遠に終わらない開発の一つです。僕のdotfilesは一人でコミット数が719件になりました。
今後も快適な開発のための開発環境作りに勤しんで参りたいと思います。
今年もアドベントカレンダーに多くのCUIツールが紹介されていたので、試したくてウズウズしているところです。