Neovimをコンテナ化して配布する
本記事は Vim Advent Calendar 2025 6日目の記事です。表題の通り、Neovimをコンテナ化して利用しているのでやり方を紹介します。
dotfilesの構成
私のdotfilesは3つのモジュールで構成されています。MacOSの設定ファイル (asagi)、NixOSの設定ファイル (azuma)、Neovimのコンテナ (akatsuki) です。

このうち、OSの設定ファイル達は次のハードウェアで起動しています。
- MacOS: Mac mini, Macbook Pro
- NixOS: ThinkPad x1

そして、Neovimは全てのハードウェアで起動しています。Nix経由で設定することも可能でしたが、dockerがあればどこでも動くという点が魅力に感じたので使っています。
Neovimをコンテナ化
コンテナの作り方自体は普通のウェブサーバーやCLIと同じです。次の設定はdefaultで起動するNeovimコンテナのDockerfileです。
# ======================================
# Builder Stage
# ======================================
FROM ubuntu:24.04 AS builder
# 引数の定義
ARG ARCH=arm64
ARG NEOVIM_VERSION=v0.11.1
ARG NODE_VERSION=24.x
# 環境変数の設定
ENV DEBIAN_FRONTEND=noninteractive
ENV DOTNET_VERSION=8.0
# 基本パッケージのインストール
RUN apt-get update && apt-get install -y \
build-essential (その他必要なパッケージ) \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Neovimのインストール
RUN curl -LO "https://github.com/neovim/neovim/releases/download/${NEOVIM_VERSION}/nvim-linux-${ARCH}.tar.gz" \
&& tar xzvf "nvim-linux-${ARCH}.tar.gz" \
&& cp "nvim-linux-${ARCH}/bin/nvim" /usr/local/bin/ \
&& cp -r "nvim-linux-${ARCH}/share/nvim" /usr/local/share/ \
&& rm -rf "nvim-linux-${ARCH}" "nvim-linux-${ARCH}.tar.gz"
# Node.jsのインストール
RUN curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}" | bash - \
&& apt-get update \
&& apt-get install -y nodejs \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# .NET SDKのインストール(Marksman用)
RUN wget "https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb" -O packages-microsoft-prod.deb \
&& dpkg -i packages-microsoft-prod.deb \
&& rm packages-microsoft-prod.deb \
&& apt-get update \
&& apt-get install -y "dotnet-runtime-${DOTNET_VERSION}"\
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# ======================================
# Runtime Stage
# ======================================
FROM ubuntu:24.04
# 環境変数の設定
ENV DEBIAN_FRONTEND=noninteractive
# 必要なパッケージのインストール
RUN apt-get update && apt-get install -y \
apt-transport-https (その他必要なパッケージ) \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 必要なディレクトリの作成とNvim設定のコピー
RUN mkdir -p /root/.config/nvim /root/.local/share/nvim/mason
COPY config/ /root/.config/nvim/
# builderステージからバイナリと必要なツールをコピー
COPY /usr/local/bin/nvim /usr/local/bin/
COPY /usr/local/share/nvim /usr/local/share/nvim
COPY /usr/bin/node /usr/bin/
COPY /usr/bin/npm /usr/bin/
COPY /usr/bin/dotnet /usr/bin/
ENTRYPOINT ["/usr/local/bin/nvim"]
補足:
- イメージの軽量化のためマルチステージングビルドをしています
デプロイ
コンテナができたらデプロイします。どこでも良いですが、私はDockerHubを利用しています。

ちなみにtagが、defaultとpythonで分かれているのは、軽量化のためです。色々な言語の言語サーバーを入れると簡単に1GB越えます。今は、defaultが200MBぐらいです。
自分はデプロイコマンドを覚えられないのでTaskfileを使ってデプロイしています。
tasks:
push:default:arm:
desc: "build and push akatsuki-default"
dir: akatsuki-default-arm
cmds:
- docker build -t akatsuki-default-arm .
- docker tag akatsuki-default-arm tsuchiya55docker/akatsuki:default-arm-{{.VERSION}}
- docker push "tsuchiya55docker/akatsuki:default-arm-{{.VERSION}}"
silent: true
ハードウェアから呼び出す
高速化のためにキャッシュをホストOS側に置いている関係上、起動コマンドが長いです。当然覚えられないので、シェルのaliasを貼っています。(この設定は shunsock/dotfiles/(asagi|azuma)/configs/zsh/ に書いてあります)
alias v='docker run -it --rm \
-v "$PWD":/workspace \
-v "$HOME/.akatsuki-default/share":/root/.local/share/nvim \
-v "$HOME/.akatsuki-default/cache":/root/.cache/nvim \
-v "$HOME/.akatsuki-default/state":/root/.local/state/nvim \
-w /workspace \
tsuchiya55docker/akatsuki:default-arm-0.0.2'
alias vpy='docker run -it --rm \
-v "$PWD":/workspace \
-v "$HOME/.akatsuki-python/share":/root/.local/share/nvim \
-v "$HOME/.akatsuki-python/cache":/root/.cache/nvim \
-v "$HOME/.akatsuki-python/state":/root/.local/state/nvim \
-w /workspace \
tsuchiya55docker/akatsuki:python-0.0.2'
このようにaliasを貼っておけば煩わしさもありません。
$ docker login
$ v # vpy
ホストOSとのコピー & ヤンクをシームレスにする
ここまで来て起動すると分かると思うのですが、Dockerコンテナ内のNeovimがヤンクしてもクリップボードに反映されません。
そこでOSC 52 (Operating System Command 52)を有効化します。これを有効化すると、ホスト側のOSのクリップボードにDockerコンテナ内のyankした情報が保持できます。WezTermの場合次のコードを設定ファイルに記述すると有効化できます。
-- OSC52を有効化する
config.enable_csi_u_key_encoding = true
やってみた感想
楽です。とりあえずDockerさえあれば動くという安心感は私の心に平穏を与えてくれることが分かりました。
これからやること
継続的インテグレーション・デプロイ
Taskfileで管理しているためそこまで負担にはなっていないですが、これから管理するものが増えるのでGitHub Actionsに載せようと考えています。
デプロイもそうですし、DockerのLinterとかも入れる予定です。
当日追記:
- Dockerのビルドテストを昨日入れました
設定の共通化
共通の設定が多いのでビルドプロセス時に、共通と固有設定をマージするような仕組みを作ろうと考えています。また、Dockerfileも共通部分が多いので、そのうちマージしたいですね。
言語を増やす
RustとGo, C#を書くのでコンテナの拡充をしたいです。
Discussion