3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ひとり開発Advent Calendar 2019

Day 8

オレオレ開発環境2017〜2019年版

Last updated at Posted at 2019-12-08

この記事はひとり開発 アドベントカレンダー 2019年の8日目の記事です。
開発環境の紹介 (VM->Docker with tmux, vim)と題して、ここ3年に渡る私のターミナル周りの開発環境の推移をまとめていく記事です。

2017年 dotfiles + git

github - u1and0/dotfiles

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で管理しています。

.gitmodules
[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の設定をオーバーライドしています。

.zshrc
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で管理されるプラグインをインストールしてくれます。

.zshrc
# 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も入れています。

.gitmodules
[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コンテナをワンコマンドで立ち上げようという試みです。

docker-compose.yml
# 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-/にデタッチキーを変更しています。

.docker/config.json
{
    "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
  1. docker-compose.ymlがある場所で
  2. docker-compose startするだけで、docker-compose.ymlに記載している全環境をワンコマンドで立ち上げます。
    ハマりどころとしては、DinDをするためにホストマシンの/var/run/docker.sockをボリュームにマウントすること。そして、tty:trueとしておかないとcommandがzshなどのshellを指定しているimageが一瞬で落ちてしまうことです。
  3. 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は自分で書いたものです。

.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かなんかに戻ろうと思います。

今注目しているのがkvmmultipass
multipassはこの記事「仮想環境multipassを試す」で少しいじってみた。VirtualBoxでやったところで、結局CUI環境はDockerで構築するわけなので、間に挟むイメージはなんでもいい、ということで安直にUbuntu一択になってしまうわけです。multipassは選べるイメージがUbuntuのみでシンプルに作られているので気に入りました。
しかしながら、ポートフォワーディングが今のところできないみたいなので、サーバー・ブラウザ・web使う系の開発に使えないのでまだ様子見です。
kvmはインストールがうまくいかないので、試行錯誤中です。
時間かかるようだったらvagrant+VirtualBoxで良いかなと思います。慣れているし。

まとめ

開発環境構築は永遠に終わらない開発の一つです。僕のdotfilesは一人でコミット数が719件になりました。
今後も快適な開発のための開発環境作りに勤しんで参りたいと思います。
今年もアドベントカレンダーに多くのCUIツールが紹介されていたので、試したくてウズウズしているところです。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?