- 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

