@@ -1,10 +1,4 @@
# 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 ────────────────────────────────────────
FROM golang:1.25-bookworm AS builder
@@ -12,46 +6,64 @@ WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 优化:去除符号表(-s -w)减小体积, CGO_ENABLED=0 确保静态链接
RUN CGO_ENABLED = 0 GOOS = linux go build -trimpath -ldflags= "-s -w" -o /out/server ./cmd/server
# ── Stage 2: Build gopls ────────────────────────────────────────────────────
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 ────────────────────────────────────────────────────────
FROM eclipse-temurin:22-jdk-noble
ARG NODE_MAJOR = 22
# ---- System deps: Node.js, python3 (jdtls launcher) ----
# ---- System deps ----
# 🔴 关键修复:必须安装 git, 否则 gopls 无法拉取依赖
# python3: JDTLS 需要
# nodejs: TS Server 需要
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates curl python3 && \
curl -fsSL https://deb.nodesource.com/setup_${ NODE_MAJOR } .x | bash - && \
apt-get install -y --no-install-recommends \
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 clean && \
rm -rf /var/lib/apt/lists/*
# ---- typescript-language-server (covers JavaScript + TypeScript ) ----
RUN npm install -g typescript-language-server typescript && \
# ---- typescript-language-server + pyright (Python LSP ) ----
RUN npm install -g typescript-language-server typescript pyright && \
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
# 🟡 建议:设置 GOPROXY 加速依赖下载 (gopls 需要)
ENV PATH = " /usr/local/go/bin:/go/bin: ${ PATH } " \
GOPATH = "/go"
GOPATH = "/go" \
GOPROXY = "https://goproxy.io,direct"
# ---- gopls ----
COPY --from= gopls-builder /go/bin/gopls /go/bin/gopls
# ---- Eclipse JDT Language Server ----
# !!! 请确保当前目录下有这个文件夹 !!!
COPY jdt-language-server-1.57.0-202602111032 /opt/jdtls
RUN chmod +x /opt/jdtls/bin/jdtls /opt/jdtls/bin/jdtls.py
# ---- Gateway binary ----
# ---- Gateway Setup ----
WORKDIR /app
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
{
"port" : "8080" ,
@@ -62,28 +74,35 @@ COPY <<'EOF' /app/config.json
"cleanupInterval" : "2m" ,
"maxSessions" : 256,
"enableRedis" : false,
"enableNacosRegister" : false,
"appEnv" : "prod" ,
"logLevel" : "info" ,
"logConsoleEnabled" : true,
"logDir" : "/app/logs" ,
"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" : "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
# ---- Directories & non-root user ----
RUN mkdir -p /workspace /go && \
# ---- 权限与目录 ----
RUN mkdir -p /workspace /go /app/logs && \
groupadd --system 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 \
WORKSPACE_DIR = /workspace
VOLUME [ "/app/logs" ]
EXPOSE 8080
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" ]