Fix Dockerfile: use mcr.microsoft.com/dotnet/runtime:8.0 as base, add Makefile
Dockerfile: - Final stage now FROM mcr.microsoft.com/dotnet/runtime:8.0 instead of python:3.12-slim + MS apt repo. Reason: packages.microsoft.com GPG key uses SHA1 which Debian trixie rejects since 2026-02-01. The official MS container image has no signing issue. - Add python3 + pip3 + wget on top of dotnet base (bookworm) - pip3 install --break-system-packages for debian bookworm compatibility Makefile targets: make build - build image locally make rebuild - force no-cache build make run - build + start container with port mappings make run-quick - start without rebuilding make stop/restart - container lifecycle make logs - follow logs make shell - bash into running container make health - curl health endpoint make smoke - end-to-end TCP + health test (scripts/smoke_test.sh) make test - unit tests (pytest, no Docker) make ps/ports - status helpers make clean - stop + remove image
This commit is contained in:
14
Dockerfile
14
Dockerfile
@@ -25,16 +25,14 @@ RUN pip install --upgrade pip build \
|
|||||||
|
|
||||||
|
|
||||||
# ── Stage 3: final runtime ────────────────────────────────────────────────────
|
# ── Stage 3: final runtime ────────────────────────────────────────────────────
|
||||||
FROM python:3.12-slim
|
# Use Microsoft's official .NET runtime image — avoids the SHA1-signed APT key
|
||||||
|
# issue on newer Debian hosts (trixie+ rejects packages.microsoft.com GPG since 2026-02-01).
|
||||||
|
FROM mcr.microsoft.com/dotnet/runtime:8.0
|
||||||
|
|
||||||
# Install .NET runtime (needed by Bicep.LangServer.dll)
|
# Install Python 3 + pip (the dotnet base image is Debian bookworm)
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends \
|
&& apt-get install -y --no-install-recommends \
|
||||||
wget apt-transport-https ca-certificates \
|
python3 python3-pip wget \
|
||||||
&& wget -q https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb \
|
|
||||||
&& dpkg -i packages-microsoft-prod.deb && rm packages-microsoft-prod.deb \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends dotnet-runtime-8.0 \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy Bicep Language Server (baked in at build time — no volume needed)
|
# Copy Bicep Language Server (baked in at build time — no volume needed)
|
||||||
@@ -42,7 +40,7 @@ COPY --from=bicep-downloader /opt/bicep-langserver /opt/bicep-langserver
|
|||||||
|
|
||||||
# Install Python package and dependencies
|
# Install Python package and dependencies
|
||||||
COPY --from=builder /dist/*.whl /tmp/
|
COPY --from=builder /dist/*.whl /tmp/
|
||||||
RUN pip install --no-cache-dir /tmp/*.whl && rm /tmp/*.whl
|
RUN pip3 install --no-cache-dir --break-system-packages /tmp/*.whl && rm /tmp/*.whl
|
||||||
|
|
||||||
# Configuration defaults (override via Nomad env)
|
# Configuration defaults (override via Nomad env)
|
||||||
ENV PYTHON_LSP_PORT=2087 \
|
ENV PYTHON_LSP_PORT=2087 \
|
||||||
|
|||||||
109
Makefile
Normal file
109
Makefile
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
IMAGE := ilsp-local
|
||||||
|
TAG := dev
|
||||||
|
CONTAINER := ilsp-dev
|
||||||
|
|
||||||
|
PYTHON_PORT := 2087
|
||||||
|
BICEP_PORT := 2088
|
||||||
|
HEALTH_PORT := 2089
|
||||||
|
|
||||||
|
# External services (used at container startup for catalog fetching)
|
||||||
|
DEVOPS_MCP_URL ?= https://devops-mcp.i80.dk
|
||||||
|
|
||||||
|
.PHONY: build run stop restart logs shell test smoke clean help
|
||||||
|
|
||||||
|
## ── Build ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
build: ## Build Docker image locally (no push)
|
||||||
|
docker build -t $(IMAGE):$(TAG) .
|
||||||
|
|
||||||
|
rebuild: ## Force rebuild (no cache)
|
||||||
|
docker build --no-cache -t $(IMAGE):$(TAG) .
|
||||||
|
|
||||||
|
## ── Run ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
run: stop ## Build and start container (rebuilds image)
|
||||||
|
$(MAKE) build
|
||||||
|
docker run -d \
|
||||||
|
--name $(CONTAINER) \
|
||||||
|
-p $(PYTHON_PORT):$(PYTHON_PORT) \
|
||||||
|
-p $(BICEP_PORT):$(BICEP_PORT) \
|
||||||
|
-p $(HEALTH_PORT):$(HEALTH_PORT) \
|
||||||
|
-e DEVOPS_MCP_URL=$(DEVOPS_MCP_URL) \
|
||||||
|
-e PYTHONUNBUFFERED=1 \
|
||||||
|
$(IMAGE):$(TAG)
|
||||||
|
@echo ""
|
||||||
|
@echo " Container started — waiting for health check..."
|
||||||
|
@sleep 5
|
||||||
|
@$(MAKE) health
|
||||||
|
|
||||||
|
run-quick: ## Start container without rebuilding image
|
||||||
|
$(MAKE) stop
|
||||||
|
docker run -d \
|
||||||
|
--name $(CONTAINER) \
|
||||||
|
-p $(PYTHON_PORT):$(PYTHON_PORT) \
|
||||||
|
-p $(BICEP_PORT):$(BICEP_PORT) \
|
||||||
|
-p $(HEALTH_PORT):$(HEALTH_PORT) \
|
||||||
|
-e DEVOPS_MCP_URL=$(DEVOPS_MCP_URL) \
|
||||||
|
-e PYTHONUNBUFFERED=1 \
|
||||||
|
$(IMAGE):$(TAG)
|
||||||
|
@sleep 5
|
||||||
|
@$(MAKE) health
|
||||||
|
|
||||||
|
stop: ## Stop and remove container (if running)
|
||||||
|
-docker stop $(CONTAINER) 2>/dev/null
|
||||||
|
-docker rm $(CONTAINER) 2>/dev/null
|
||||||
|
|
||||||
|
restart: stop run-quick ## Restart container without rebuilding
|
||||||
|
|
||||||
|
logs: ## Follow container logs
|
||||||
|
docker logs -f $(CONTAINER)
|
||||||
|
|
||||||
|
logs-tail: ## Show last 50 lines of logs
|
||||||
|
docker logs --tail 50 $(CONTAINER)
|
||||||
|
|
||||||
|
shell: ## Open bash inside running container
|
||||||
|
docker exec -it $(CONTAINER) bash
|
||||||
|
|
||||||
|
## ── Health & Testing ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
health: ## Check health endpoint
|
||||||
|
@curl -sf http://localhost:$(HEALTH_PORT)/health | python3 -m json.tool \
|
||||||
|
|| echo " ✗ Health endpoint not reachable — is the container running? (make run)"
|
||||||
|
|
||||||
|
smoke: ## Run end-to-end smoke test against local container
|
||||||
|
bash scripts/smoke_test.sh localhost
|
||||||
|
|
||||||
|
test: ## Run unit tests (local Python, no Docker needed)
|
||||||
|
python3 -m pytest tests/ -v
|
||||||
|
|
||||||
|
## ── Status ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
ps: ## Show running container status
|
||||||
|
@docker ps --filter name=$(CONTAINER) --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||||||
|
|
||||||
|
ports: ## Show port mappings
|
||||||
|
@echo " Python LSP : localhost:$(PYTHON_PORT) (TCP)"
|
||||||
|
@echo " Bicep LSP : localhost:$(BICEP_PORT) (TCP)"
|
||||||
|
@echo " Health : http://localhost:$(HEALTH_PORT)/health"
|
||||||
|
|
||||||
|
## ── Cleanup ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
clean: stop ## Stop container and remove local image
|
||||||
|
-docker rmi $(IMAGE):$(TAG) 2>/dev/null
|
||||||
|
|
||||||
|
## ── Help ─────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
help: ## Show this help
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' Makefile \
|
||||||
|
| awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
|
||||||
|
@echo ""
|
||||||
|
@echo " Env vars:"
|
||||||
|
@echo " DEVOPS_MCP_URL (default: $(DEVOPS_MCP_URL))"
|
||||||
|
@echo ""
|
||||||
|
@echo " Examples:"
|
||||||
|
@echo " make run # build + start"
|
||||||
|
@echo " make logs # follow logs"
|
||||||
|
@echo " make smoke # end-to-end test"
|
||||||
|
@echo " DEVOPS_MCP_URL=http://localhost:8000 make run # point at local MCP"
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
Reference in New Issue
Block a user