- About the Template
- Features
- Who Is This For?
- Project Structure
- Tested with
- Prerequisites
- Quickstart
- Example Project Templates
- 🚀 Getting Started
- 1. Configure environment and Python settings and API tokens
- 2. Set up Python project dependencies
- 3. Build your Vim IDE image
- 4. Start developing inside the container
- 5. Update dependencies when needed
- Build and run your application
- Optional: Use
devfor checks and experiments - GitHub CI checks
- Optional: Run Codex or Gemini (see more examples below)
- Optional: Run code-server (VS Code in browser)
- Optional: Run JupyterLab
- 💻 AI-Powered CLI Workflow (Gemini & Codex)
- 🔒 Security notes
- 🧠 Vim IDE Features
vim-python-docker-template is a lightweight, flexible starting point for containerized Python development where the only required host dependency is Docker.
This template allows you to write and run code inside the same containerized environment using either:
- Vim configured as a full-featured IDE (
vim-ide) - VS Code in browser via code-server (
code-server)
Whether you're scripting pipelines, prototyping machine learning models, or
building production tools, this setup provides a consistent and reproducible
workflow for build, lint, test, and run operations through docker compose
commands.
✨ Designed to work with any Python project — just plug in your code and dependencies.
The configuration is intentionally minimal and easy to adapt. You’re free to:
- Add or update Python dependencies
- Swap in different OS packages
- Customize the Vim environment
- Change Python or Poetry versions
Use it as-is or tailor it to match your team's development workflow.
- Docker-first workflow: build, run, lint, and test inside containers
- Single host dependency: Docker Engine + Compose
- Two editor paths:
vim-ideandcode-server(VS Code in browser) - Built-in quality checks with
ruffandpytest - Reproducible Python environment with customizable Python and Poetry versions
- Optional tooling: JupyterLab, Codex CLI, Gemini CLI
- CI-ready template with a simple GitHub Actions workflow
- Teams that want Docker as the only required local dependency.
- Data science / ML projects that need notebooks, reproducible dependencies, and optional GPU/OS packages.
- Backend/API projects that need consistent lint/test/build behavior across machines.
- Developers who prefer either terminal-first editing (
vim-ide) or browser-based VS Code (code-server). - Repositories that need a simple CI baseline to extend over time.
.
├── .github/workflows/ci.yml # GitHub CI: build dev/app, run Ruff + pytest
├── .vscode/*.json.dist # VS Code / code-server editor defaults
├── src/sample/main.py # Example application module
├── tests/sample/test_main.py # Example pytest tests to extend in your project
├── Dockerfile # Multi-stage images (base, dev, vim-ide, code-server, app)
├── compose.yaml # Local service orchestration for template workflows
├── .env.dist # Default compose/build/runtime variables
├── pyproject.toml # Poetry dependencies and tool configuration
├── poetry.lock # Locked dependency graph
└── README.md # Setup and usage documentation
This layout is intentionally minimal so it can be extended for any project.
- Docker:
27.3.1–29.2.1 - buildx:
0.20.0–0.31.1 - Compose:
2.32.1–5.0.2
- Docker is the only required local runtime dependency.
- Docker Engine with
docker composev2.0+ (minimum). Tested versions are listed above. docker buildxis required only for cross-platform builds (whenDOCKER_PLATFORMdiffers from your host). For native builds, it’s optional.- A supported
DOCKER_PLATFORMfor your machine (for example, Apple Silicon users often setDOCKER_PLATFORM=linux/arm64) - Note: the
codex-web-loginservice usesnetwork_mode: host. This works on Linux, and on macOS with recent Docker Desktop or OrbStack. If it doesn’t work in your setup, authenticate on the host (outside Docker) and useOPENAI_API_KEY/GEMINI_API_KEYinside the containers.
cp .env.dist .env
cp .vimrc.dist .vimrc
cp .coc-settings.json.dist .coc-settings.json
docker compose build vim-ide
docker compose run --rm vim-ide
# Optional alternative editor:
# docker compose build code-server
# docker compose run --rm --service-ports code-server
# Open: http://127.0.0.1:${CODE_SERVER_PORT:-8443}To exit Vim: :q (or :qa to quit all).
If you just want a shell in the dev environment:
docker compose build dev
docker compose run --rm devUse this template when your project mixes notebooks, experiments, and Python modules.
.
├── src/<project_name>/...
├── notebooks/
├── data/
│ ├── raw/
│ └── processed/
├── tests/
├── pyproject.toml
└── README.md
Typical workflow:
docker compose build dev jupyterlab
docker compose run --rm --service-ports jupyterlab
docker compose run --rm dev ruff check .
docker compose run --rm dev pytest -qUse this template when your project is mostly application code, tests, and CI checks.
.
├── src/<service_name>/
│ ├── api.py
│ ├── main.py
│ └── settings.py
├── tests/
├── pyproject.toml
└── README.md
Typical workflow: keep app code in src/, run ruff + pytest in dev, and
package runtime execution through the app service.
Set the .env values used by compose.yaml and the Docker build. Common ones:
TZ— Container timezone (e.g.Europe/Berlin,Asia/Vladivostok).DOCKER_PLATFORM— Target architecture (e.g.linux/amd64,linux/arm64).DOCKER_HOST_UID/DOCKER_HOST_GID— Host user/group IDs for file ownership.DOCKER_USER/DOCKER_USER_HOME— Container user + home directory.MIRROR_LIST_COUNTRY— Arch mirror country code for pacman.BUILD_PACKAGES— System packages needed to build Python and runtime deps.VIM_PACKAGES— Extra tools installed in the dev/vim images.PYTHON_VERSION— Python version installed via pyenv.POETRY_VERSION— Poetry version installed in the image.POETRY_OPTIONS_APP— Poetry install flags for the app image.POETRY_OPTIONS_DEV— Poetry install flags for the dev image.PIP_DEFAULT_TIMEOUT— Pip network timeout (seconds).JUPYTER_TOKEN— Token for JupyterLab login.CODE_SERVER_EXTENSIONS— Space-separated extension IDs preinstalled in code-server.CODE_SERVER_HOST— Bind address for code-server (usually0.0.0.0).CODE_SERVER_PORT— Port for code-server.CODE_SERVER_AUTH— code-server auth mode (passwordornone).CODE_SERVER_PASSWORD— Password used by code-server when auth ispassword.OPENAI_API_KEY— API key for Codex.GEMINI_API_KEY— API key for Gemini.
Set DOCKER_HOST_UID / DOCKER_HOST_GID to match your host user so files
created in the container are editable on the host. On Unix-like systems, use
id -u and id -g to get the correct values.
cp .env.dist .env
vim .envvim pyproject.toml # Edit dependencies, metadata, etc.
docker compose build poetry
docker compose run --rm poetry lock # Generate or update poetry.lock
# git add poetry.lockcp .vimrc.dist .vimrc
cp .coc-settings.json.dist .coc-settings.json
git config --local user.name "Your Name"
git config --local user.email you@example.com
docker compose build vim-idedocker compose run --rm vim-idedocker compose run --rm poetry lock🔄 Note: If you've changed dependencies (e.g. updated pyproject.toml or poetry.lock), rebuild the image(s) that install Python dependencies:
vim-ide,dev,codex,gemini,code-server,jupyterlab, and/orappdepending on what you run.
docker compose build vim-ide
docker compose run --rm vim-idedocker compose build app
docker compose run --rm appℹ️
vim-ide,poetry,codex,gemini,jupyterlab, anddevbind-mount your working directory into the container for live editing.appis a “packaged” image (it copies your sources), so code changes require rebuildingapp.
dev is a general-purpose image for running tools, scripts, and ad-hoc checks
inside the same environment as your Vim IDE.
dev and vim-ide are built from the same base stage, so they share the same
tooling and system packages.
docker compose build dev
docker compose run --rm devExamples (quality checks): run tests with pytest, then run Ruff lint and format checks.
docker compose run --rm dev pytest -q
docker compose run --rm dev ruff check
docker compose run --rm dev ruff format --checkThis template includes a minimal GitHub Actions workflow in
.github/workflows/ci.yml that:
- builds
dev,app,vim-ide,codex,gemini,jupyterlab, andcode-server - checks
vim,codex,gemini,jupyter-lab, andcode-serverbinaries - runs
ruff check . - runs
ruff format --check . - runs
pytest -q
The same pattern can be easily extended for any other CI system.
If you’re running as the non-root user and want to try extra system packages
before baking them into the image, use sudo:
docker compose run --rm dev sudo pacman -S --noconfirm <package>🔄 Note:
codexandgeminiCLIs are installed during the image build via Arch packages (openai-codex,gemini-cli) configured inVIM_PACKAGESinside.env.
vim-idedoes not carry API keys or auth volumes, so run Codex/Gemini in a separate terminal via their own services.
docker compose build codex
docker compose run --rm codexdocker compose build gemini
docker compose run --rm geminiCreate the editor config files from dist templates (recommended):
mkdir -p .vscode
cp .vscode/settings.json.dist .vscode/settings.json
cp .vscode/extensions.json.dist .vscode/extensions.jsondocker compose build code-server
docker compose run --rm --service-ports code-server
# Open: http://127.0.0.1:${CODE_SERVER_PORT}compose.yaml controls port/auth via CODE_SERVER_HOST, CODE_SERVER_PORT,
CODE_SERVER_AUTH, and CODE_SERVER_PASSWORD.
docker compose build jupyterlab
docker compose run --rm --service-ports jupyterlab
# Open: http://127.0.0.1:8888/lab?token=<your .env token>This project template is designed to be easily integrated with powerful CLI
tools like Gemini and Codex, enhancing your development workflow with
intelligent assistance. Rather than replacing your editor, these tools
complement Vim by running alongside it in a separate terminal (via
docker compose run) so you can inspect, generate, and reason about code
without breaking flow.
NOTE: To use AI CLI tools such as Gemini or Codex, you must configure API keys according to each provider’s official documentation.
API keys for Codex and Gemini require separate billing. In some cases, you can use an OpenAI subscription (for example, ChatGPT Pro) or take advantage of the available limits of a personal Google account.
This type of access requires authentication via a browser. Run these from a
separate terminal via the codex / gemini services (not vim-ide). For
OpenAI, run the command:
docker compose run --rm codex-web-loginFor Gemini, there is no separate login command — just run:
docker compose run --rm geminiand choose “Login with Google.”
After completion, the authorization file will be saved to
${DOCKER_USER_HOME}/.codex or ${DOCKER_USER_HOME}/.gemini. In this
template, those directories are persisted between runs via the codex-auth and
gemini-auth Docker volumes, which allows the agent CLI tool to be restarted
without any additional authentication steps.
Run the CLIs in their own containers (recommended):
docker compose run --rm codex
docker compose run --rm geminivim-ide is for editing only; it does not mount the auth volumes or API keys.
The Gemini CLI provides a conversational interface to interact with your codebase, allowing you to ask questions, refactor code, fix bugs, and add new features.
Run all Gemini commands via Docker Compose so auth volumes and API keys are available:
docker compose run --rm geminiRead a file:
docker compose run --rm gemini read src/sample/main.pyList directory contents:
docker compose run --rm gemini list src/sampleExplain a code snippet (hypothetical):
docker compose run --rm gemini explain "def my_function():" --file src/sample/main.pyThe Codex CLI (or similar code generation/analysis tools) can be used for automating code generation, understanding project structure, and suggesting improvements.
Run all Codex commands via Docker Compose so auth volumes and API keys are available:
docker compose run --rm codexGenerate a new Python class (hypothetical):
docker compose run --rm codex generate class User --fields name:str,email:str --language python --file src/models.pyAnalyze dependencies (hypothetical):
docker compose run --rm codex analyze dependencies --project-root .Suggest tests for a file (hypothetical):
docker compose run --rm codex suggest tests --file src/sample/main.pyNever commit .env (it contains secrets like OPENAI_API_KEY,
CODE_SERVER_PASSWORD,
GEMINI_API_KEY, and JUPYTER_TOKEN).
If you need to share the resolved Compose config, use
docker compose config --no-interpolate to avoid printing secret values.
Browser-based auth persists under ${DOCKER_USER_HOME}/.codex and
${DOCKER_USER_HOME}/.gemini via the codex-auth and gemini-auth Docker
volumes.
This template comes with a thoughtfully configured Vim environment that replicates many features you'd expect from a modern IDE. It’s built for productivity and designed to work out of the box — but is fully customizable.
✨ Core Capabilities
- Syntax highlighting & intelligent folding
- Autocompletion and LSP features via
coc.nvim - Linting, formatting, and diagnostics
- Git integration and diff signs
- Markdown editing with ToC, folding, and preview support
- Snippets, code actions, and refactoring shortcuts
- Enhanced status line, file tree, and fuzzy finding
- Python-focused indentation, folding, and style enforcement
🧠 Code Intelligence
- coc.nvim – LSP engine with autocompletion, diagnostics, and more
- coc-pyright – Python LSP support
- ultisnips + vim-snippets – Powerful snippet expansion
📁 Navigation & UI
- NERDTree – File tree explorer
- fzf.vim – Fuzzy file and symbol search
- tagbar – Code structure sidebar
- vim-airline – Status/tab line enhancement
🔄 Git Integration
- vim-fugitive – Git commands from within Vim
- vim-gitgutter – Git diff signs in the gutter
📝 Markdown Support
- vim-markdown – Markdown editing enhancements
- vim-markdown-toc – Auto-generated table of contents
📊 Data Science & Python Dev
🎨 Theme & Aesthetics
- gruvbox-material – Color scheme (dark, high-contrast)
- Airline integrated with Gruvbox
⚙️ Python-Specific Tuning
- Smart indentation for Python, with 4-space formatting
textwidthandcolorcolumnset to PEP8 defaults- Spellcheck enabled for English and Russian
- LSP-based completion, hover docs, jump-to-definition, code actions
- To customize the LSP setup, see
.coc-settings.json - To update CoC extensions:
:CocUpdate - Snippets can be edited under
~/.vim/plugged/vim-snippets - Full configuration lives in
.vimrc.dist— tweak freely

