调试容器化的Go项目测试

前端开发 2026-07-11

我有一个用Go语言编写的项目,是一个用React构建的单页应用,其中Go语言充当静态文件服务器和API。该应用可以在web文件夹中通过 docker compose upnpm run 启动。

以下是 compose.yaml

services:

  server:
    container_name: hello-world-server
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - gomodcache:/go/pkg/mod
    ports:
      - 40531:8080
      - 40532:12345
    env_file: .env
    depends_on:
      - db

  db:
    container_name: hello-world-db
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: postgres
      PGUSER: postgres
    ports:
      - 40533:5432
    volumes:
      - ./initdb:/docker-entrypoint-initdb.d
      - dbdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready"]
      interval: 1s
      timeout: 10s
      retries: 10

  adminer:
    container_name: hello-world-adminer
    image: adminer:latest
    restart: always
    ports:
      - 40534:8080

volumes:
  gomodcache: null
  dbdata: null

以下是 Dockerfile

FROM golang:1.25-alpine AS base
WORKDIR /app

FROM base AS development
RUN apk add build-base
# Create external debugger
RUN go install github.com/go-delve/delve/cmd/dlv@latest
# Restart server on code change
RUN go install github.com/cespare/reflex@latest
COPY reflex.conf /
ENTRYPOINT ["reflex", "-c", "/reflex.conf"]

FROM node:25-alpine AS node-builder
WORKDIR /app
# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY web/package*.json ./
RUN npm ci
COPY web .
RUN npm run build

FROM base AS go-builder
# Retrieve application dependencies.
# This allows the container build to reuse cached dependencies.
# Expecting to copy go.mod and if present go.sum.
COPY go.* ./
RUN go mod download
# Copy local code to the container image.
COPY . .
COPY --from=node-builder /app/dist /app/web/dist
# Build the binary.
RUN go build -buildvcs=false -v -o server


FROM alpine:latest
# Copy the binary to the production image from the builder stage.
COPY --from=go-builder /app/server /app/server
# Run the web service on container startup.
CMD ["/app/server"]

使用 reflex.configlaunch.json 对HTTP调用进行调试,效果如预期。

我需要添加并调试一些测试。在YAML文件中我添加了一个服务:

  test:
    container_name: hello-world-test
    build:
      context: .
      target: test
    volumes:
      - .:/app
      - gomodcache:/go/pkg/mod
    env_file: .env
    depends_on:
      - db

在Dockerfile中添加了一个阶段:

FROM base AS test
# Copy Go modules
COPY go.* ./
RUN go mod download
# Copy full source code
COPY . .
# Default command to run tests
CMD ["go", "test", "./...", "-v"]

我可以使用命令 docker-compose run test 运行测试,但无法在调试模式下运行。

如何调试我的测试?如何附加调试器?我只使用VS Code。

解决方案

我已经搞定了,只要按F5就能完成所有操作。

  1. 在compose.yaml中定义服务

test: container_name: hello-world-test build: context: . target: test volumes: - .:/app - gomodcache:/go/pkg/mod env_file: .env depends_on: - db ports: - 40535:12345 security_opt: - seccomp:unconfined cap_add: - SYS_PTRACE profiles: - test 2. Dockerfile中的阶段

FROM base AS test RUN apk add build-base RUN go install github.com/go-delve/delve/cmd/dlv@latest COPY go.* ./ RUN go mod download 3.定义任务 (.vscode/task.json)

{ "version": "2.0.0", "tasks": [ { "label": "docker-test-up", "type": "shell", "command": "docker compose --profile test up test --build", "isBackground": true, "presentation": { "panel": "shared", "group": "test" }, "problemMatcher": { "pattern": { "regexp": "." }, "background": { "activeOnStart": true, "beginsPattern": "Attaching to", "endsPattern": "API server listening" } } }, { "label": "docker-test-down", "type": "shell", "command": "docker compose --profile test down", "presentation": { "panel": "shared", "group": "test", "close": true } } ] } 4.定义调试配置 (.vscode/launch.json)

{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Attach to container", "type": "go", "request": "attach", "mode": "remote", "debugAdapter": "dlv-dap", "port": 40532, "substitutePath": [{ "from": "${workspaceFolder}", "to": "/app" }] }, { "name": "Attach to tests", "type": "go", "request": "attach", "mode": "remote", "debugAdapter": "dlv-dap", "port": 40535, "substitutePath": [{ "from": "${workspaceFolder}", "to": "/app" }], "preLaunchTask": "docker-test-up", "postDebugTask": "docker-test-down" } ] }

按下F5时,VS Code会尝试将调试器附加到进程,preLaunchTask 会构建镜像并运行容器。测试将被执行,最后 postDebugTask 会停止并移除容器。多亏了任务中的 presentation 属性,所有输出都在同一个面板中显示。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章