Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
name: Push LSP Docker Images
name: build-and-push

on:
pull_request:
push:
branches: [main]
schedule:
- cron: '0 3 * * *'

jobs:
build_and_push:
Expand Down Expand Up @@ -110,6 +108,8 @@ jobs:

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64

- name: Login to Docker Hub
uses: docker/login-action@v3
Expand All @@ -118,9 +118,33 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }}
if: ${{ github.ref == 'refs/heads/main' }}

- name: Extract version from Dockerfile
id: version
run: |
VERSION=$(grep "ARG VERSION=" servers/${{ matrix.context }}/Dockerfile | cut -d'=' -f2 || echo "unknown")
echo "version=$VERSION" >> $GITHUB_OUTPUT
if [ "$VERSION" != "unknown" ]; then
TAGS="lspcontainers/${{ matrix.tag }}:latest,lspcontainers/${{ matrix.tag }}:$VERSION"
echo "tags=$TAGS" >> $GITHUB_OUTPUT
else
TAGS="lspcontainers/${{ matrix.tag }}:latest"
echo "tags=$TAGS" >> $GITHUB_OUTPUT
fi
echo "🏷️ Tags that will be used: $TAGS"

# Set platforms based on container compatibility
if [ "${{ matrix.context }}" = "powershell_es" ]; then
echo "platforms=linux/amd64" >> $GITHUB_OUTPUT
echo "🏗️ PowerShell ES: Building for amd64 only (ARM64 not supported by Microsoft PowerShell base image)"
else
echo "platforms=linux/amd64,linux/arm64" >> $GITHUB_OUTPUT
echo "🏗️ Building for platforms: linux/amd64,linux/arm64"
fi

- name: Build and push to Docker Hub
uses: docker/build-push-action@v5
with:
context: servers/${{ matrix.context }}
platforms: ${{ steps.version.outputs.platforms }}
push: ${{ github.ref == 'refs/heads/main' }}
tags: lspcontainers/${{ matrix.tag }}:latest
tags: ${{ steps.version.outputs.tags }}
99 changes: 99 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This repository contains Dockerfiles for Language Server Protocol (LSP) servers used with `lspcontainers`. Each language server is containerized to provide consistent development environments across different platforms.

## Build Commands

### Building Docker Images
- `docker-compose build <server>` - Build a specific server (e.g., `docker-compose build tsserver`)
- `docker-compose build` - Build all servers
- `docker-compose build --parallel` - Build all servers in parallel (faster)

### Available Servers
The docker-compose.yaml defines 24 language servers:
- `bashls` - Bash Language Server
- `clangd` - C/C++ Language Server
- `denols` - Deno Language Server
- `dockerls` - Docker Language Server
- `eslintls` - ESLint Language Server
- `gopls` - Go Language Server
- `graphql-lsp` - GraphQL Language Service
- `html` - HTML Language Server
- `intelephense` - PHP Language Server
- `jsonls` - JSON Language Server
- `lemminx` - XML Language Server
- `omnisharp` - C# Language Server
- `powershell_es` - PowerShell Language Server
- `prisma` - Prisma Language Server
- `pylsp` - Python LSP Server
- `pyright` - Python Language Server
- `rust_analyzer` - Rust Language Server
- `solargraph` - Ruby Language Server
- `sumneko_lua` - Lua Language Server
- `svelteserver` - Svelte Language Server
- `tailwindcss` - Tailwind CSS Language Server
- `terraformls` - Terraform Language Server
- `tsserver` - TypeScript Language Server
- `volar` - Vue Language Server (Volar)
- `vuels` - Vue Language Server (legacy)
- `yamlls` - YAML Language Server

### Linting
The CI workflow uses hadolint to lint Dockerfiles:
```bash
docker run --rm -v $(pwd):/code -w /code hadolint/hadolint:latest-alpine servers/<server>/Dockerfile
```

## Architecture

### Repository Structure
```
servers/
├── <server-name>/
│ ├── Dockerfile # Container definition
│ └── docker_entrypoint.sh # Optional entrypoint script (e.g., gopls)
├── docker-compose.yaml # Service definitions
└── .github/workflows/ # CI/CD automation
```

### Container Patterns
1. **Alpine-based**: All containers use Alpine Linux as the base image for minimal size
2. **Package managers**: Different servers use appropriate package managers:
- Node.js servers: `npm` or `yarn`
- Go servers: `go install`
- Python servers: `pip`
- Ruby servers: `gem`
3. **User management**: Some containers (like gopls) create dedicated users with sudo access
4. **Entrypoint scripts**: Complex setups use shell scripts for runtime configuration

### Special Cases
- **gopls**: Uses a custom entrypoint script to handle user/group ID mapping
- **volar**: Pinned to specific version (1.8.11) in environment variable
- **tsserver**: Includes Vue TypeScript plugin for Vue.js support

### CI/CD Pipeline
The GitHub Actions workflow:
1. Runs hadolint on each Dockerfile
2. Builds images using Docker Buildx
3. Pushes to Docker Hub on main branch
4. Runs daily builds via cron schedule
5. Uses matrix strategy to build all servers in parallel

### Container Tagging
Each container has two tags:
- `latest`: Points to the most recent build
- Pinned version: Latest version of the language server

## Development Guidelines

When adding new language servers:
1. Create a new directory under `servers/`
2. Write a Dockerfile following Alpine Linux pattern
3. Add the service to `docker-compose.yaml`
4. Update the CI workflow matrix in `.github/workflows/build-image.yml`
5. Test locally with `docker-compose build <server>`
6. Verify with hadolint: `docker run --rm -v $(pwd):/code -w /code hadolint/hadolint:latest-alpine servers/<server>/Dockerfile`
213 changes: 197 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,208 @@
# dockerfiles
# lspcontainers/dockerfiles

Dockerfiles for all LSPs used with `lspcontainers`.
🚀 **Dockerfiles for Language Server Protocol (LSP) servers** - Containerized language servers for use with [lspcontainers.nvim](https://github.com/lspcontainers/lspcontainers.nvim).

## Installation
[![Docker Hub](https://img.shields.io/badge/Docker%20Hub-lspcontainers-blue?logo=docker)](https://hub.docker.com/u/lspcontainers)
[![Build Status](https://img.shields.io/github/actions/workflow/status/lspcontainers/dockerfiles/build-image.yml?branch=main)](https://github.com/lspcontainers/dockerfiles/actions)
[![License](https://img.shields.io/github/license/lspcontainers/dockerfiles)](LICENSE)

This repository requires the latest:
## 🌟 What is this?

- [Docker Engine](https://docs.docker.com/engine/install/)
- [Docker Compose](https://docs.docker.com/compose/install)
This repository provides **production-ready Docker containers** for 25+ Language Server Protocol (LSP) servers, designed to work seamlessly with the **[lspcontainers.nvim](https://github.com/lspcontainers/lspcontainers.nvim)** Neovim plugin.

## Build
### 🎯 **How it works:**
1. **Docker containers** provide isolated, reproducible LSP server environments
2. **[lspcontainers.nvim](https://github.com/lspcontainers/lspcontainers.nvim)** plugin automatically manages these containers in Neovim
3. **Zero local installation** - no need to install language servers on your system

To build images locally run:
Perfect for:
- **Consistent development environments** across teams and machines
- **Clean system** - no language server pollution on your host
- **Reproducible builds** with pinned package versions
- **Easy switching** between language server versions

- `docker-compose build <server>` to build a specific server (see `docker-compose.yaml`)
- `docker-compose build` to build all servers
- `docker-compose build --parallel` to build all servers in parallel
## 🛠️ Supported Language Servers

## Versions
| Language | Server | Container | Version |
|----------|--------|-----------|---------|
| **Bash** | bash-language-server | `lspcontainers/bash-language-server` | ![Version](https://img.shields.io/badge/version-5.6.0-blue) |
| **C/C++** | clangd | `lspcontainers/clangd-language-server` | ![Version](https://img.shields.io/badge/version-20.1.8-blue) |
| **C#** | omnisharp | `lspcontainers/omnisharp-language-server` | ![Version](https://img.shields.io/badge/version-1.39.12-blue) |
| **CSS/SCSS/Less** | vscode-css-languageserver | `lspcontainers/css-language-server` | ![Version](https://img.shields.io/badge/version-4.10.0-blue) |
| **Deno** | deno-lsp | `lspcontainers/deno-language-server` | ![Version](https://img.shields.io/badge/version-2.4.2-blue) |
| **Docker** | dockerfile-ls | `lspcontainers/docker-language-server` | ![Version](https://img.shields.io/badge/version-0.14.0-blue) |
| **ESLint** | eslint-languageserver | `lspcontainers/eslint-language-server` | ![Version](https://img.shields.io/badge/version-latest-blue) |
| **Go** | gopls | `lspcontainers/gopls` | ![Version](https://img.shields.io/badge/version-0.19.1-blue) |
| **GraphQL** | graphql-language-service | `lspcontainers/graphql-language-server` | ![Version](https://img.shields.io/badge/version-3.5.0-blue) |
| **HTML** | html-languageserver | `lspcontainers/html-language-server` | ![Version](https://img.shields.io/badge/version-1.4.0-blue) |
| **JavaScript/TypeScript** | typescript-language-server | `lspcontainers/typescript-language-server` | ![Version](https://img.shields.io/badge/version-4.3.4-blue) |
| **JSON** | vscode-json-languageserver | `lspcontainers/json-language-server` | ![Version](https://img.shields.io/badge/version-4.10.0-blue) |
| **Lua** | lua-language-server | `lspcontainers/lua-language-server` | ![Version](https://img.shields.io/badge/version-3.14.0-blue) |
| **PHP** | intelephense | `lspcontainers/php-language-server` | ![Version](https://img.shields.io/badge/version-1.14.4-blue) |
| **PowerShell** | powershell-es | `lspcontainers/powershell-language-server` | ![Version](https://img.shields.io/badge/version-4.3.0-blue) |
| **Prisma** | prisma-language-server | `lspcontainers/prisma-language-server` | ![Version](https://img.shields.io/badge/version-6.9.1-blue) |
| **Python** | pylsp | `lspcontainers/python-lsp-server` | ![Version](https://img.shields.io/badge/version-1.12.0-blue) |
| **Python** | pyright | `lspcontainers/pyright-language-server` | ![Version](https://img.shields.io/badge/version-1.1.377-blue) |
| **Ruby** | solargraph | `lspcontainers/ruby-language-server` | ![Version](https://img.shields.io/badge/version-0.55.1-blue) |
| **Rust** | rust-analyzer | `lspcontainers/rust-analyzer` | ![Version](https://img.shields.io/badge/version-1.88.0-blue) |
| **Svelte** | svelte-language-server | `lspcontainers/svelte-language-server` | ![Version](https://img.shields.io/badge/version-0.17.16-blue) |
| **Tailwind CSS** | tailwindcss-language-server | `lspcontainers/tailwindcss-language-server` | ![Version](https://img.shields.io/badge/version-0.14.25-blue) |
| **Terraform** | terraform-ls | `lspcontainers/terraform-ls` | ![Version](https://img.shields.io/badge/version-0.36.5-blue) |
| **Vue** | volar | `lspcontainers/volar-language-server` | ![Version](https://img.shields.io/badge/version-1.8.11-blue) |
| **Vue** | vuels (legacy) | `lspcontainers/vue-language-server` | ![Version](https://img.shields.io/badge/version-0.8.5-blue) |
| **XML** | lemminx | `lspcontainers/xml-language-server` | ![Version](https://img.shields.io/badge/version-0.27.0-blue) |
| **YAML** | yaml-language-server | `lspcontainers/yaml-language-server` | ![Version](https://img.shields.io/badge/version-1.18.0-blue) |

Every container has two tags available:
## 🚀 Quick Start

- The `latest` tag, which points to the latest container build
### Using with lspcontainers.nvim (Recommended)

- A pinned version. The pinned version will be the latest
version of the language server.
These containers are designed to work with the **[lspcontainers.nvim](https://github.com/lspcontainers/lspcontainers.nvim)** plugin.

👉 **[See the plugin documentation](https://github.com/lspcontainers/lspcontainers.nvim)** for installation and setup instructions.

### Building Containers Locally

```bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pedantic: Use sh here: the following script is regular shell script and doesn't require bash:

Suggested change
```bash
```sh

# Clone the repository
git clone https://github.com/lspcontainers/dockerfiles.git
cd dockerfiles

# Build a specific server
docker-compose build gopls

# Build all servers
docker-compose build

# Build all servers in parallel (faster!)
docker-compose build --parallel
```

## 📋 Prerequisites

- [Docker Engine](https://docs.docker.com/engine/install/) (20.10+)
- [Docker Compose](https://docs.docker.com/compose/install) (2.0+)

## 🏗️ Architecture & Design

### 🔒 **Reproducible Builds**
All containers use **pinned package versions** for complete reproducibility:
- **Base images**: Specific Alpine/Debian versions
- **System packages**: Exact apk/apt package versions
- **Language packages**: Pinned npm, gem, pip, go module versions

### 🏔️ **Minimal & Secure**
- **Alpine Linux base** for minimal attack surface
- **Multi-stage builds** where applicable
- **Non-root users** for security
- **Distroless principles** - only essential components

### 🔄 **Automated Updates**
- **Daily builds** via GitHub Actions
- **Dependency scanning** and security updates
- **Version tracking** of upstream language servers

## 🤝 Contributing

We're actively looking for contributors! Here's how you can help:

### 🐛 **Report Issues**
Found a bug or have a feature request? [Open an issue](https://github.com/lspcontainers/dockerfiles/issues/new)!

### 🔧 **Add New Language Servers**
Want to add support for a new language? We'd love your contribution!

1. **Fork the repository**
2. **Create a new directory** under `servers/your-language-server/`
3. **Write a Dockerfile** following our patterns:
```dockerfile
FROM alpine:3.22.1

ARG VERSION=1.2.3
LABEL version="${VERSION}"

RUN apk add --no-cache \
nodejs=22.16.0-r2 \
npm=11.3.0-r0 \
&& npm install -g \
your-language-server@${VERSION}

CMD [ "your-language-server", "--stdio" ]
```
4. **Add to docker-compose.yaml**
5. **Test your build**: `docker-compose build your-server`
6. **Submit a pull request**

### 🛠️ **Improve Existing Containers**
- Update language server versions
- Improve Dockerfile efficiency
- Add missing tools or dependencies
- Enhance security

### 📚 **Documentation**
- Improve README files
- Add usage examples
- Write integration guides
- Create tutorials

## 🏷️ Container Versioning

Every container provides two tags:

- **`latest`** - Latest build from main branch
- **`vX.Y.Z`** - Pinned version of the language server

```bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto:

Suggested change
```bash
```sh

# Always latest
docker pull lspcontainers/gopls:latest

# Specific version for production
docker pull lspcontainers/gopls:v0.19.1
```

### 🔄 **Updating Dockerfile Versions**

Each Dockerfile includes version information that controls both the language server version and container tagging:

```dockerfile
# Version is declared at the top
ARG VERSION=1.2.3
LABEL version="${VERSION}"

# Version variable is used in installation
RUN npm install -g your-language-server@${VERSION}
```

**To update a language server version:**

1. **Edit the Dockerfile** in `servers/your-server/Dockerfile`
2. **Update the VERSION argument** to the new version
3. **Test the build** locally: `docker-compose build your-server`
4. **Submit a pull request** with your changes

The CI/CD pipeline automatically:
- Extracts the version from the `LABEL version` directive
- Tags the image with both `latest` and the specific version
- Pushes to Docker Hub with proper versioning

**Example version update:**
```dockerfile
# Before
ARG VERSION=1.2.3

# After
ARG VERSION=1.3.0
```

This ensures reproducible builds and allows users to pin to specific language server versions.

### 📊 Project Stats

- **25+ Language Servers** supported
- **100% reproducible builds** with pinned versions
- **Multi-architecture support** (amd64, arm64)
- **Active community** with regular contributions

---

**Ready to contribute?** Check out our [Contributing Guide](CONTRIBUTING.md) and join our community of developers making language servers more accessible!
2 changes: 0 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.8"

services:
bashls:
image: lspcontainers/bash-language-server
Expand Down
Loading