ども!最近は一日中 Claude Code を回している龍ちゃんです。
コンテナの中で作業していると、ターミナルを分けたくなる場面があります。片方で Claude Code を走らせて、もう片方でログを見たりコマンドを叩いたり。VS Code のターミナルでも分割はできるんですが、増えてくるとタブがどれも同じ見た目で並ぶので、どれで何を動かしていたか分からなくなるんですよね。あと、閉じると中で動いていたプロセスも一緒に死にます。
tmux を入れるとこの2つが解決します。名前を付けたセッションの中で画面を割って並べられるのと、セッションから抜けても中のプロセスが動き続けるやつですね。
ただ、コンテナに入れるとなると素の環境とは少し勝手が違います。~/.tmux.conf に設定を書いても、リビルドしたら消えるんですよ。なので設定の実体はリポジトリ側に置いて、コンテナを作るときに配る形にします。
今回の内容です。
Dockerfileに tmux を足す- 設定をリポジトリに置いて
postCreateCommandで配る - 実際に使っている
.tmux.confの全文と、各設定の理由
なお、この記事はコンテナの中の話に絞ります。WSL のセットアップとか、ターミナルエミュレータをどれにするかは扱いません。セッション・ウィンドウ・ペインといった tmux の概念も、公式 Wiki の Getting Started に任せます(「Sessions, windows and panes」の節が図つきで分かりやすいです)。
何をいまさらですけど、汎用的に使えるものなので記録として置いておきます!
Dockerfile に tmux を足す
まずはインストールから。うちのベースイメージは python:3.12-slim(Debian bookworm ベース)なので、apt-get install に1行足すだけです。
FROM python:3.12-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
tmux \
&& rm -rf /var/lib/apt/lists/*
すでに apt-get install している行があるなら、そこに tmux \ を1行差し込めば大丈夫です。これで tmux 3.5a が入りました。この記事の検証環境もこれです。
ここはベースイメージによって書き方が変わるところなので、FROM を確認してから足してください。Debian / Ubuntu 系なら上のとおりですが、Alpine 系(FROM node:22-alpine など)なら RUN apk add --no-cache tmux になります。DevContainer の公式イメージ(mcr.microsoft.com/devcontainers/*)は Debian ベースなので apt-get で大丈夫です。
設定の実体はリポジトリに置く
ここがコンテナならではの部分です。
tmux を入れたあと、普通は ~/.tmux.conf に設定を書きます。素の Linux ならそれでいいんですが、コンテナの中のホームディレクトリって、ボリュームでもバインドマウントでもない、ただのコンテナ内のファイルなんですよね。
実際に見てみるとこうなります。
$ findmnt -T ~/.tmux.conf -o TARGET,SOURCE,FSTYPE
TARGET SOURCE FSTYPE
/ overlay overlay
overlay が返ってきました。イメージのレイヤの上に乗っているだけなので、コンテナを作り直したら当然消えます。
なので、設定の実体は .devcontainer/ の中に置きます。書いた設定を .devcontainer/.tmux.conf として保存するだけです(中身は後述します)。
リポジトリの中に置くと、設定を変えた履歴が Git に残りますし、他のメンバーがクローンした時点で同じ設定が入ってきます。「あのキーどうやるんだっけ」と聞かれても、リポジトリの中を見てくれで済むのが地味に助かってます。
ちなみに DevContainer には dotfiles を取り込む機能もあって、そっちを使う手もあります。ただあれは「個人の設定を自分のコンテナに持ち込む」仕組みなんですよね。今回やりたいのは「このリポジトリで作業する人全員に同じ設定を渡す」ほうなので、リポジトリに実体を置く形にしています。個人の好みはそのまま dotfiles 側に置けばいいので、両立もできます。
postCreateCommand で配る
.devcontainer/ に置いた conf を、コンテナ作成時にホームへコピーします。devcontainer.json の postCreateCommand の末尾に1つ足すだけです。
{
"postCreateCommand": "... && cp .devcontainer/.tmux.conf ~/"
}
postCreateCommand をまだ書いていなければ、頭の ... && は要りません。"postCreateCommand": "cp .devcontainer/.tmux.conf ~/" だけで動きます。
これでコンテナを作るたびに ~/.tmux.conf へ配置されます。リビルドしても、新しいメンバーが初めて開いても、同じ状態から始まる。
ここまでで触ったファイルを1枚にするとこうなります。

実際に使っている .tmux.conf
うちで動いている全文です。そのままコピーして使えます。
# ============================================================
# プレフィックスキー: Ctrl+a(片手で押しやすい)
# ============================================================
unbind C-b
set -g prefix C-a
bind C-a send-prefix
# ============================================================
# 基本設定
# ============================================================
set -g default-terminal "tmux-256color"
set -as terminal-features ",xterm-256color:RGB"
set -sg escape-time 0
set -g history-limit 50000
set -g base-index 1
setw -g pane-base-index 1
set -g renumber-windows on
set -g mouse on
# ============================================================
# ペイン操作(直感的なキーバインド)
# ============================================================
# 分割: \ で左右、- で上下
bind \\ split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
unbind '"'
unbind %
# ペイン移動: Shift+矢印キー(プレフィックス不要)
bind -n S-Left select-pane -L
bind -n S-Right select-pane -R
bind -n S-Up select-pane -U
bind -n S-Down select-pane -D
# 新しいウィンドウも現在のパスで開く
bind c new-window -c "#{pane_current_path}"
# 設定リロード
bind r source-file ~/.tmux.conf \; display "Reloaded!"
# ============================================================
# ステータスバー
# ============================================================
set -g status-bg colour234
set -g status-fg colour137
set -g status-left-length 40
set -g status-right-length 60
set -g status-left "#[fg=colour229,bold] #S "
set -g status-right "#[fg=colour233,bg=colour241] %Y-%m-%d %H:%M "
デフォルトから変えたところを表にしておきます。デフォルト値は tmux 3.5a を隔離ソケット(tmux -L 別名 -f /dev/null)で起動して実際に確認したものです。
| 設定 | デフォルト | うちの値 | 変えた理由 |
|---|---|---|---|
| プレフィックス | Ctrl+b | Ctrl+a | ホームポジションから指を動かさずに押せる。GNU Screen 由来の定番 |
| 左右分割 | % | \ | \ は |(縦棒)と同じキー。縦の仕切りが入る=左右、と対応する |
| 上下分割 | " | - | - が横線そのもの。どちらも Shift 不要になる |
| ペイン移動 | prefix → 矢印 | Shift+矢印 | -n を付けるとプレフィックス無しで直接反応する。一番回数の多い操作なので |
escape-time | 10 | 0 | Esc キーの反応が一瞬遅れるのを消す |
history-limit | 2000 | 50000 | Claude Code の出力が長いので、2000行だとすぐ流れる |
base-index | 0 | 1 | ウィンドウ番号を1始まりに。キーボードの並び順と揃う |
pane-base-index | 0 | 1 | 同上。ペイン番号も1始まり |
mouse | off | on | ペインの境界をドラッグしてリサイズできる。スクロールもホイールでそのまま |
いくつか補足です。
Ctrl+a はシェルの行頭移動とぶつかります。なので bind C-a send-prefix をセットで入れていて、Ctrl+a を2回押すとシェル側に本物の Ctrl+a が届くようにしてあります。
分割の -h / -v は名前と結果が逆に見えるので注意です。split-window -h(horizontal)が左右分割で、仕切り線は縦に入ります。
$ tmux -L dc2 -f /dev/null list-keys | grep split-window
bind-key -T prefix \" split-window
bind-key -T prefix \% split-window -h
-c "#{pane_current_path}" は「分割したペインを、今いるディレクトリで開く」指定です。これが無いとホームディレクトリで開くので、毎回 cd する羽目になります。
デフォルトの - には delete-buffer(コピーバッファの削除)が割り当たっているので、上書きすることになります。僕は使ったことがなかったので割り切りました。
あと default-terminal を tmux-256color にする設定、これ tmux 3.5a だともうデフォルト値になってたんですよね。古いバージョン向けに書かれた記述が残っていただけでした。バージョンによっては要るので消してはいませんが、新しく書くなら不要です。
プラグインマネージャ(tpm)は入れていません。ここまでの設定で困っていないので、増やしていないだけです。
ここまでの設定が効いているかは、コンテナをリビルドしてから tmux を立ち上げて Ctrl+a → \ を押すのが手っ取り早いです。左右に割れたら、conf がコピーされていて中身も読まれています。割れなかったら ~/.tmux.conf があるかを見てみてください。
入れるとこうなる
僕は今、こういう置き方で使っています。

左をメインにして Claude Code を回し、右はサブとして上下に割って調べものと確認用。Ctrl+a → \ で左右に割って、右側にカーソルを移してから Ctrl+a → - で上下に割る、という手順です。
あともう1つ、コンテナで効くのがデタッチです。Ctrl+a → d でセッションから抜けても、中のプロセスは動き続けます。Claude Code に長い作業を投げたまま抜けて、あとから tmux attach で戻れる。VS Code のターミナルを閉じたら死ぬのとは全然違いますね。
この記事で変えたのはペイン操作まわりだけなので、それ以外のキーはデフォルトのままです。何ができるのか一度眺めておくと拾いものがあるので、man page の DEFAULT KEY BINDINGS を貼っておきます。足したい設定が出てきたら .devcontainer/.tmux.conf に書き足せば、それも消えずに残ります。
ここから先、たとえば「スマホから指示を出して、その場でペインを増やして新しい Claude Code を立ち上げる」みたいな使い方もできるんですが、それは話が長くなるので「Claude Codeをスマホでリモート、その場でペインが増える」に分けました。tmux send-keys で隣のペインの Claude Code にコマンドを送る話も、そちらに入っています。
まとめ
- コンテナの中で tmux を使うと、画面を割って並べられるのと、抜けてもプロセスが残るのが効く
~/.tmux.confは overlay 上のただのファイルなのでリビルドで消えるDockerfileにtmux、.devcontainer/.tmux.confに設定の実体、postCreateCommandでcpの3つで解決する- リポジトリに入るので、クローンした時点でチーム全員に同じ設定が渡る
コンテナの環境って、作り直すたびに素の状態に戻るのが利点でもあるんですが、育てた設定まで戻ってしまうと使い物になりません。実体をリポジトリ側に置くだけで、その両方が成立します。
もし他にも「この設定は入れとけ」ってのがあったら、ぜひ教えてほしいです。
ほなまた〜


