feat(lsp): add Python language server support
- Add pyright-langserver for Python LSP support - Add environment variable overrides for Python LSP configuration - Install git in Docker image (required for gopls dependency resolution) - Optimize Go binary build with -s -w linker flags for smaller image - Add GOPROXY configuration for faster dependency downloads - Update Node.js installation method with GPG key verification - Add entrypoint script to auto-create go.mod in workspace - Add /app/logs volume for log persistence
This commit is contained in:
@@ -1,10 +1,4 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
###############################################################################
|
|
||||||
# All-in-one LSP Gateway Image
|
|
||||||
# - Go → gopls
|
|
||||||
# - JS / TS → typescript-language-server
|
|
||||||
# - Java → Eclipse JDT Language Server (jdtls) + JDK 22
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
# ── Stage 1: Build Go gateway binary ────────────────────────────────────────
|
# ── Stage 1: Build Go gateway binary ────────────────────────────────────────
|
||||||
FROM golang:1.25-bookworm AS builder
|
FROM golang:1.25-bookworm AS builder
|
||||||
@@ -12,46 +6,64 @@ WORKDIR /src
|
|||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
COPY . .
|
COPY . .
|
||||||
|
# 优化:去除符号表(-s -w)减小体积,CGO_ENABLED=0 确保静态链接
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/server ./cmd/server
|
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/server ./cmd/server
|
||||||
|
|
||||||
# ── Stage 2: Build gopls ────────────────────────────────────────────────────
|
# ── Stage 2: Build gopls ────────────────────────────────────────────────────
|
||||||
FROM golang:1.25-bookworm AS gopls-builder
|
FROM golang:1.25-bookworm AS gopls-builder
|
||||||
RUN go install golang.org/x/tools/gopls@latest
|
# 优化:静态编译 gopls,避免 GLIBC 版本依赖问题
|
||||||
|
RUN CGO_ENABLED=0 go install golang.org/x/tools/gopls@latest
|
||||||
|
|
||||||
# ── Stage 3: Runtime ────────────────────────────────────────────────────────
|
# ── Stage 3: Runtime ────────────────────────────────────────────────────────
|
||||||
FROM eclipse-temurin:22-jdk-noble
|
FROM eclipse-temurin:22-jdk-noble
|
||||||
|
|
||||||
ARG NODE_MAJOR=22
|
ARG NODE_MAJOR=22
|
||||||
|
|
||||||
# ---- System deps: Node.js, python3 (jdtls launcher) ----
|
# ---- System deps ----
|
||||||
|
# 🔴 关键修复:必须安装 git,否则 gopls 无法拉取依赖
|
||||||
|
# python3: JDTLS 需要
|
||||||
|
# nodejs: TS Server 需要
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends ca-certificates curl python3 && \
|
apt-get install -y --no-install-recommends \
|
||||||
curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - && \
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
python3 \
|
||||||
|
git \
|
||||||
|
gnupg && \
|
||||||
|
mkdir -p /etc/apt/keyrings && \
|
||||||
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
|
||||||
|
apt-get update && \
|
||||||
apt-get install -y --no-install-recommends nodejs && \
|
apt-get install -y --no-install-recommends nodejs && \
|
||||||
|
apt-get clean && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# ---- typescript-language-server (covers JavaScript + TypeScript) ----
|
# ---- typescript-language-server + pyright (Python LSP) ----
|
||||||
RUN npm install -g typescript-language-server typescript && \
|
RUN npm install -g typescript-language-server typescript pyright && \
|
||||||
npm cache clean --force
|
npm cache clean --force
|
||||||
|
|
||||||
# ---- Go toolchain (gopls needs it at runtime for analysis) ----
|
# ---- Go toolchain (Optimized) ----
|
||||||
COPY --from=golang:1.25-bookworm /usr/local/go /usr/local/go
|
COPY --from=golang:1.25-bookworm /usr/local/go /usr/local/go
|
||||||
|
|
||||||
|
|
||||||
|
# 🟡 建议:设置 GOPROXY 加速依赖下载 (gopls 需要)
|
||||||
ENV PATH="/usr/local/go/bin:/go/bin:${PATH}" \
|
ENV PATH="/usr/local/go/bin:/go/bin:${PATH}" \
|
||||||
GOPATH="/go"
|
GOPATH="/go" \
|
||||||
|
GOPROXY="https://goproxy.io,direct"
|
||||||
|
|
||||||
# ---- gopls ----
|
# ---- gopls ----
|
||||||
COPY --from=gopls-builder /go/bin/gopls /go/bin/gopls
|
COPY --from=gopls-builder /go/bin/gopls /go/bin/gopls
|
||||||
|
|
||||||
# ---- Eclipse JDT Language Server ----
|
# ---- Eclipse JDT Language Server ----
|
||||||
|
# !!! 请确保当前目录下有这个文件夹 !!!
|
||||||
COPY jdt-language-server-1.57.0-202602111032 /opt/jdtls
|
COPY jdt-language-server-1.57.0-202602111032 /opt/jdtls
|
||||||
RUN chmod +x /opt/jdtls/bin/jdtls /opt/jdtls/bin/jdtls.py
|
RUN chmod +x /opt/jdtls/bin/jdtls /opt/jdtls/bin/jdtls.py
|
||||||
|
|
||||||
# ---- Gateway binary ----
|
# ---- Gateway Setup ----
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /out/server /app/server
|
COPY --from=builder /out/server /app/server
|
||||||
COPY config.example.json /app/config.example.json
|
|
||||||
|
|
||||||
# ---- Default config: all 4 LSP servers, Redis/Nacos off by default ----
|
# ---- 默认配置 ----
|
||||||
COPY <<'EOF' /app/config.json
|
COPY <<'EOF' /app/config.json
|
||||||
{
|
{
|
||||||
"port": "8080",
|
"port": "8080",
|
||||||
@@ -62,28 +74,35 @@ COPY <<'EOF' /app/config.json
|
|||||||
"cleanupInterval": "2m",
|
"cleanupInterval": "2m",
|
||||||
"maxSessions": 256,
|
"maxSessions": 256,
|
||||||
"enableRedis": false,
|
"enableRedis": false,
|
||||||
"enableNacosRegister": false,
|
|
||||||
"appEnv": "prod",
|
"appEnv": "prod",
|
||||||
"logLevel": "info",
|
"logLevel": "info",
|
||||||
"logConsoleEnabled": true,
|
"logConsoleEnabled": true,
|
||||||
|
"logDir": "/app/logs",
|
||||||
"servers": [
|
"servers": [
|
||||||
{ "language": "go", "languageId": "go", "command": "gopls", "args": [] },
|
{ "language": "go", "languageId": "go", "command": "gopls", "args": [] },
|
||||||
{ "language": "javascript", "languageId": "javascript", "command": "typescript-language-server", "args": ["--stdio"] },
|
{ "language": "javascript", "languageId": "javascript", "command": "typescript-language-server", "args": ["--stdio"] },
|
||||||
{ "language": "typescript", "languageId": "typescript", "command": "typescript-language-server", "args": ["--stdio"] },
|
{ "language": "typescript", "languageId": "typescript", "command": "typescript-language-server", "args": ["--stdio"] },
|
||||||
{ "language": "java", "languageId": "java", "command": "/opt/jdtls/bin/jdtls", "args": [] }
|
{ "language": "java", "languageId": "java", "command": "/opt/jdtls/bin/jdtls", "args": [] },
|
||||||
|
{ "language": "python", "languageId": "python", "command": "pyright-langserver", "args": ["--stdio"] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# ---- Directories & non-root user ----
|
# ---- 权限与目录 ----
|
||||||
RUN mkdir -p /workspace /go && \
|
RUN mkdir -p /workspace /go /app/logs && \
|
||||||
groupadd --system app && \
|
groupadd --system app && \
|
||||||
useradd --system --gid app --home-dir /home/app --create-home app && \
|
useradd --system --gid app --home-dir /home/app --create-home app && \
|
||||||
chown -R app:app /app /workspace /go /home/app
|
chown -R app:app /app /workspace /go /home/app /app/logs
|
||||||
|
|
||||||
ENV PORT=8080 \
|
ENV PORT=8080 \
|
||||||
WORKSPACE_DIR=/workspace
|
WORKSPACE_DIR=/workspace
|
||||||
|
|
||||||
|
VOLUME ["/app/logs"]
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
USER app
|
USER app
|
||||||
ENTRYPOINT ["/app/server"]
|
|
||||||
|
# 🔴 关键:用 entrypoint 脚本在启动时写 go.mod,避免被 volume 挂载覆盖
|
||||||
|
# 如果 /workspace 下还没有 go.mod,自动创建一个最小的
|
||||||
|
ENTRYPOINT ["sh", "-c", "test -f /workspace/go.mod || printf 'module workspace\n\ngo 1.25\n' > /workspace/go.mod; exec /app/server"]
|
||||||
@@ -735,6 +735,12 @@ func defaultLanguageServers() []completion.LanguageServerSpec {
|
|||||||
Command: "typescript-language-server",
|
Command: "typescript-language-server",
|
||||||
Args: []string{"--stdio"},
|
Args: []string{"--stdio"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Language: "python",
|
||||||
|
LanguageID: "python",
|
||||||
|
Command: "pyright-langserver",
|
||||||
|
Args: []string{"--stdio"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,6 +760,7 @@ func applyLanguageServerEnvOverrides(servers []completion.LanguageServerSpec) []
|
|||||||
overridden = applySingleLanguageServerEnv(overridden, "go", "go", "GO_LSP_COMMAND", "GO_LSP_ARGS", "gopls", "")
|
overridden = applySingleLanguageServerEnv(overridden, "go", "go", "GO_LSP_COMMAND", "GO_LSP_ARGS", "gopls", "")
|
||||||
overridden = applySingleLanguageServerEnv(overridden, "javascript", "javascript", "JAVASCRIPT_LSP_COMMAND", "JAVASCRIPT_LSP_ARGS", "typescript-language-server", "--stdio")
|
overridden = applySingleLanguageServerEnv(overridden, "javascript", "javascript", "JAVASCRIPT_LSP_COMMAND", "JAVASCRIPT_LSP_ARGS", "typescript-language-server", "--stdio")
|
||||||
overridden = applySingleLanguageServerEnv(overridden, "typescript", "typescript", "TYPESCRIPT_LSP_COMMAND", "TYPESCRIPT_LSP_ARGS", "typescript-language-server", "--stdio")
|
overridden = applySingleLanguageServerEnv(overridden, "typescript", "typescript", "TYPESCRIPT_LSP_COMMAND", "TYPESCRIPT_LSP_ARGS", "typescript-language-server", "--stdio")
|
||||||
|
overridden = applySingleLanguageServerEnv(overridden, "python", "python", "PYTHON_LSP_COMMAND", "PYTHON_LSP_ARGS", "pyright-langserver", "--stdio")
|
||||||
return overridden
|
return overridden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,14 @@
|
|||||||
"languageId": "java",
|
"languageId": "java",
|
||||||
"command": "/opt/jdtls/bin/jdtls",
|
"command": "/opt/jdtls/bin/jdtls",
|
||||||
"args": []
|
"args": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "python",
|
||||||
|
"languageId": "python",
|
||||||
|
"command": "pyright-langserver",
|
||||||
|
"args": [
|
||||||
|
"--stdio"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,14 @@
|
|||||||
"languageId": "java",
|
"languageId": "java",
|
||||||
"command": "jdt-language-server-1.57.0-202602111032/jdtls.bat",
|
"command": "jdt-language-server-1.57.0-202602111032/jdtls.bat",
|
||||||
"args": []
|
"args": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "python",
|
||||||
|
"languageId": "python",
|
||||||
|
"command": "pyright-langserver",
|
||||||
|
"args": [
|
||||||
|
"--stdio"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user