Neovim Docker Integration: What It Is
Neovim Docker integration encompasses a set of practices and tools that bridge the power of Neovim and Docker. It can mean running Neovim itself inside a Docker container to create a portable, reproducible development environment, or it can mean using Neovim plugins and configurations to interact with Docker—editing Dockerfiles with smart completion and linting, managing containers, and even launching Docker-based services directly from your editor. In essence, it's about making Docker a seamless part of your Neovim workflow.
Why Neovim Docker Integration Matters
- Reproducible Environments: Package your entire Neovim setup—plugins, LSP servers, formatters, linters—inside a Docker image. Spin it up identically on any machine, avoiding "works on my machine" issues.
- Isolation and Safety: Run experiments, test untrusted code, or try new plugin configurations without polluting your host system. Docker provides a disposable sandbox.
- Cross-Platform Development: Use a Linux container on macOS or Windows to get native Linux tooling and file system behavior, while still enjoying your local Neovim UI.
- Project-Specific Toolchains: Create per-project Docker images with exactly the right compilers, language versions, and dependencies. No more cluttering your host with multiple versions of Node or Python.
- CI/CD Alignment: Develop in an environment that mirrors your CI pipeline, reducing surprises.
- Enhanced Docker Authoring: With smart syntax highlighting, completion, and linting, writing Dockerfiles and docker-compose.yml becomes faster and less error-prone.
How to Use Neovim Docker Integration
Running Neovim Inside a Docker Container
This approach gives you a fully containerized Neovim environment. You build an image containing Neovim, your configs, and all dependencies, then run it interactively with a volume mount for your project.
Step 1: Create a Dockerfile for your Neovim environment.
FROM ubuntu:22.04
# Install Neovim (via appimage or build from source)
RUN apt-get update && apt-get install -y \
curl \
fuse \
libfuse2 \
git \
&& rm -rf /var/lib/apt/lists/*
# Install Neovim appimage
RUN curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage \
&& chmod +x nvim.appimage \
&& ./nvim.appimage --appimage-extract \
&& mv squashfs-root /opt/nvim \
&& ln -s /opt/nvim/AppRun /usr/local/bin/nvim \
&& rm nvim.appimage
# Set up a non-root user
RUN useradd -m -s /bin/bash devuser
USER devuser
WORKDIR /home/devuser
# Clone your Neovim config (example using a starter config)
RUN git clone https://github.com/yourusername/nvim-config.git ~/.config/nvim
# Install plugins (lazy.nvim will handle this on first launch, but we can pre-install)
# Optionally pre-download language servers
Step 2: Build the image.
docker build -t neovim-dev:latest .
Step 3: Run the container, mounting your project and giving it a TTY for interactive use.
docker run -it --rm \
-v $(pwd):/home/devuser/project \
-w /home/devuser/project \
neovim-dev:latest \
nvim
This opens Neovim inside the container, editing the files from your mounted directory. Any changes are persisted on the host. You can also start a bash session and then launch Neovim manually.
For a more persistent setup, use a named volume for Neovim's cache and plugins, and run the container in the background with docker run -d -v ... neovim-dev tail -f /dev/null then attach with docker exec -it container_id nvim.
You can also use Docker Compose for multi-service environments:
version: '3'
services:
dev:
image: neovim-dev:latest
volumes:
- .:/home/devuser/project
- nvim-data:/home/devuser/.local/share/nvim
working_dir: /home/devuser/project
command: nvim
volumes:
nvim-data:
Using Neovim Plugins to Enhance Docker Workflow
Even if you run Neovim on the host, you can supercharge Dockerfile editing and container management with plugins. This is the "integration" where Neovim acts as an IDE for Docker projects.
Syntax Highlighting and Linting
Install ekalinin/Dockerfile.vim for proper Dockerfile syntax highlighting. For linting, use hadolint via ALE or null-ls.
-- Using lazy.nvim
{
"ekalinin/Dockerfile.vim",
ft = "dockerfile",
},
{
"nvimtools/none-ls.nvim", -- null-ls successor
dependencies = { "nvim-lua/plenary.nvim" },
config = function()
local null_ls = require("null-ls")
null_ls.setup({
sources = {
null_ls.builtins.diagnostics.hadolint, -- requires hadolint installed
},
})
end,
}
LSP for Dockerfile
Use dockerfile-language-server for completions, hover docs, and go-to-definition for Dockerfile instructions.
-- With nvim-lspconfig
require("lspconfig").dockerls.setup({
cmd = { "dockerfile-language-server" },
filetypes = { "dockerfile" },
root_dir = function(fname)
return vim.fn.getcwd()
end,
})
Docker Compose Integration
Use compose-nvim or similar plugins to start/stop services, view logs, and run docker-compose commands directly from Neovim. Alternatively, set up keybindings to execute :!docker-compose up -d and use :term to monitor logs.
Running Containers and Executing Commands
Map custom functions to run Docker commands. For example, rebuild and restart a container on save:
vim.api.nvim_create_autocmd("BufWritePost", {
pattern = "Dockerfile",
command = "!docker build -t myapp .",
})
-- Or a Lua function
vim.keymap.set("n", "dc", function()
vim.cmd("!docker-compose up -d --build")
end, { desc = "Start compose services" })
Remote Neovim in Docker via Terminal or SSH
You can run Neovim in a Docker container and connect to it from your host terminal using a standard SSH or docker exec. For a richer experience, use nvim --listen 0.0.0.0:8080 inside the container and attach remotely, but this is more complex. A simpler alternative: use docker exec -it container bash then start Neovim; all terminal UI is forwarded. For GUI-like experience, consider neovim-remote but it's beyond scope.
Best Practices for Neovim Docker Integration
- Keep Images Small: Use Alpine Linux or slim Debian variants to reduce image size. Install only what's needed. Use multi-stage builds to separate build dependencies from runtime.
- Volume Mounts for Speed: Mount your project directory rather than copying it into the image. This ensures live edits on host are reflected in the container and avoids rebuilding the image on every file change.
- Cache Plugin and LSP Data: Use a Docker volume or bind mount for
~/.local/share/nvimand~/.cache/nvim. This avoids re-downloading plugins and language servers each time you start a new container. - Non-Root User: Always switch to a non-root user inside the container to avoid permission issues with mounted files and for security.
- Version Your Dockerfiles: Keep Dockerfile and docker-compose.yml in your project repo. This documents the exact environment needed and allows others to replicate it instantly.
- Use docker-compose for Multi-Container Projects: When your app needs a database, cache, etc., define them in a compose file. Run the development container with Neovim as a service, and use
docker-compose exec dev nvimto start editing. - Automate Container Lifecycle: Create shell scripts or Makefile targets to build, start, stop, and exec into the dev container. Bind Neovim commands to these for quick access.
- Test Plugin Compatibility: Before containerizing, ensure all plugins work inside the container (some may rely on host-specific paths or GUIs). Use terminal-only Neovim features.
Conclusion
Neovim Docker integration blurs the line between editor and environment. Whether you choose to embed Neovim in a portable Docker sandbox, or enhance your local Neovim with Docker-aware tooling, the result is a more productive, reproducible, and enjoyable development experience. Start small: add Dockerfile linting to your setup, then experiment with a dev container. You'll quickly see why this combination is a favorite among modern developers who demand flexibility without sacrificing the power of a text editor like Neovim.