Docker-Compose部署Golang+Nginx+Postgres时找不到./main文件求助
部署包含Golang API、Postgres和Nginx的容器环境时,启动apigateway容器报错:
Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "./main": stat ./main: no such file or directory: unknown
推测是Dockerfile中RUN go build -o main .生成的二进制文件路径异常。尝试过本地编译(MacOS编译的二进制无法在Linux容器运行)、调整Dockerfile路径,均未解决。
项目配置文件
根目录下的docker-compose.yml
version: '3.8' services: apigateway: build: context: . dockerfile: .docker/go/Dockerfile ports: - "8080:8080" volumes: - ./apigateway:/apigateway depends_on: - postgres networks: - app-network nginx: image: nginx:1.26.0 ports: - "80:80" volumes: - ./.docker/nginx/conf.d:/etc/nginx/conf.d depends_on: - apigateway networks: - app-network postgres: image: postgres:16.2 ports: - "5210:5432" environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: mydb volumes: - postgres_data:/var/lib/postgresql/data networks: - app-network volumes: postgres_data: networks: app-network:
.docker/go/Dockerfile内容
FROM golang:1.22-alpine RUN apk update && apk upgrade && \ apk add --no-cache bash openssh WORKDIR /apigateway COPY ./apigateway/go.mod ./apigateway/go.sum ./ RUN go mod download COPY ./apigateway . RUN go build -o main . EXPOSE 8080 CMD ["./main"]
问题根源及修复方案
核心问题
docker-compose中给apigateway配置了- ./apigateway:/apigateway卷挂载,这会把本地的apigateway目录完全覆盖容器内的/apigateway目录——而Dockerfile里编译生成的main二进制文件存放在容器的/apigateway下,挂载后被本地无该二进制的目录覆盖,导致启动时找不到文件。
修复方案
方案一:移除不必要的卷挂载(生产环境推荐)
如果不需要在容器运行时同步本地代码,直接删除apigateway服务下的volumes配置项:
apigateway: build: context: . dockerfile: .docker/go/Dockerfile ports: - "8080:8080" # 移除以下卷挂载配置 # volumes: # - ./apigateway:/apigateway depends_on: - postgres networks: - app-network
重新构建镜像并启动:
docker-compose build apigateway docker-compose up
方案二:保留挂载但调整二进制路径(开发环境)
如果需要本地代码热加载,修改Dockerfile将二进制编译到容器内非挂载目录(比如/app):
FROM golang:1.22-alpine RUN apk update && apk upgrade && \ apk add --no-cache bash openssh # 切换到非挂载目录作为工作区 WORKDIR /app COPY ./apigateway/go.mod ./apigateway/go.sum ./ RUN go mod download COPY ./apigateway . RUN go build -o main . EXPOSE 8080 # 指定绝对路径执行二进制 CMD ["/app/main"]
保留卷挂载用于代码同步,本地代码修改后,可进入容器重新编译:
docker-compose exec apigateway go build -o /app/main .
额外优化:多阶段构建减小镜像体积(生产环境)
使用多阶段构建只保留二进制文件,大幅降低镜像大小:
# 构建阶段 FROM golang:1.22-alpine AS builder WORKDIR /app COPY ./apigateway/go.mod ./apigateway/go.sum ./ RUN go mod download COPY ./apigateway . # 编译静态链接二进制,避免依赖系统库 RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . # 运行阶段 FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ # 从构建阶段复制二进制文件 COPY --from=builder /app/main . EXPOSE 8080 CMD ["./main"]
内容的提问来源于stack exchange,提问作者Oussama

