You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker运行Go API镜像遇权限拒绝错误,求排查原因

问题描述

我有一个基础Go API想要部署到服务器上运行,编写了如下Dockerfile:

FROM golang
#COPY FILES
ADD ./user_server /app
WORKDIR /app
#BUILD BIN
RUN go build
#DEBUG
RUN ls
RUN pwd
RUN stat /app
RUN chmod 700 /app
RUN stat /app
ENTRYPOINT /app/app
#Build Final Stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=0 /app .
#DEBUG
RUN ls
RUN pwd
RUN stat /app
#RUN APP
ENTRYPOINT [ "/app" ]

使用以下命令构建镜像用于调试:

docker build --no-cache --progress=plain -t go-image . -f Dockerfile.new

构建日志如下:

#0 building with "default" instance using docker driver

#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile.new
#2 transferring dockerfile: 348B 0.0s done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/golang:latest
#3 DONE 0.4s

#4 [internal] load metadata for docker.io/library/alpine:latest
#4 DONE 0.3s

#5 [stage-1 1/7] FROM docker.io/library/alpine:latest@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
#5 CACHED

#6 [stage-0 1/9] FROM docker.io/library/golang@sha256:bc5f0b5e43282627279fe5262ae275fecb3d2eae3b33977a7fd200c7a760d6f1
#6 CACHED

#7 [internal] load build context
#7 transferring context: 270B 0.0s done
#7 DONE 0.0s

#8 [stage-0 2/9] ADD ./user_server /app
#8 DONE 0.2s

#9 [stage-0 3/9] WORKDIR /app
#9 DONE 0.0s

#10 [stage-0 4/9] RUN go build
#10 0.422 go: downloading github.com/go-sql-driver/mysql v1.7.1
#10 0.569 go: downloading github.com/gorilla/mux v1.8.0
#10 ...

#11 [stage-1 2/7] RUN apk --no-cache add ca-certificates
#11 0.572 fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/main/x86_64/APKINDEX.tar.gz
#11 0.723 fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/community/x86_64/APKINDEX.tar.gz
#11 1.111 (1/1) Installing ca-certificates (20230506-r0)
#11 1.152 Executing busybox-1.36.1-r2.trigger
#11 1.161 Executing ca-certificates-20230506-r0.trigger
#11 1.238 OK: 8 MiB in 16 packages
#11 DONE 1.4s

#12 [stage-1 3/7] WORKDIR /app
#12 DONE 0.0s

#10 [stage-0 4/9] RUN go build
#10 DONE 24.7s

#13 [stage-0 5/9] RUN ls
#13 0.405 api.go
#13 0.405 go.mod
#13 0.405 go.sum
#13 0.405 main.go
#13 0.405 types.go
#13 0.405 user_server
#13 DONE 0.4s

#14 [stage-0 6/9] RUN pwd
#14 0.281 /app
#14 DONE 0.3s

#15 [stage-0 7/9] RUN stat /app
#15 0.246   File: /app
#15 0.246   Size: 4096          Blocks: 8          IO Block: 4096   directory
#15 0.246 Device: 0,48  Inode: 660401      Links: 1
#15 0.246 Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
#15 0.246 Access: 2023-08-08 00:12:50.128698095 +0000
#15 0.246 Modify: 2023-08-08 11:59:33.949349423 +0000
#15 0.246 Change: 2023-08-08 11:59:33.949349423 +0000
#15 0.246  Birth: 2023-08-08 11:59:33.949349423 +0000
#15 DONE 0.3s

#16 [stage-0 8/9] RUN chmod 700 /app
#16 DONE 0.4s

#17 [stage-0 9/9] RUN stat /app
#17 0.267   File: /app
#17 0.267   Size: 4096          Blocks: 8          IO Block: 4096   directory
#17 0.267 Device: 0,48  Inode: 659193      Links: 1
#17 0.267 Access: (0700/drwx------)  Uid: (    0/    root)   Gid: (    0/    root)
#17 0.267 Access: 2023-08-08 00:12:50.128698095 +0000
#17 0.267 Modify: 2023-08-08 11:59:33.949349423 +0000
#17 0.267 Change: 2023-08-08 11:59:35.401375022 +0000
#17 0.267  Birth: 2023-08-08 11:59:35.401375022 +0000
#17 DONE 0.3s

#18 [stage-1 4/7] COPY --from=0 /app .
#18 DONE 0.0s

#19 [stage-1 5/7] RUN ls
#19 0.214 api.go
#19 0.214 go.mod
#19 0.214 go.sum
#19 0.214 main.go
#19 0.214 types.go
#19 0.214 user_server
#19 DONE 0.2s

#20 [stage-1 6/7] RUN pwd
#20 0.291 /app
#20 DONE 0.3s

#21 [stage-1 7/7] RUN stat /app
#21 0.244   File: /app
#21 0.245   Size: 4096          Blocks: 8          IO Block: 4096   directory
#21 0.245 Device: 30h/48d   Inode: 659237      Links: 1
#21 0.245 Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
#21 0.245 Access: 2023-08-08 00:12:50.128698095 +0000
#21 0.245 Modify: 2023-08-08 11:59:33.949349423 +0000
#21 0.245 Change: 2023-08-08 11:59:37.813416735 +0000
#21 DONE 0.3s

#22 exporting to image
#22 exporting layers
#22 exporting layers 0.4s done
#22 writing image sha256:e5744ed45915fba087eac04720b83208c5bbf0f3ea82887cd2416dcd77dc403f
#22 writing image sha256:e5744ed45915fba087eac04720b83208c5bbf0f3ea82887cd2416dcd77dc403f done
#22 naming to docker.io/library/go-image done
#22 DONE 0.4s

之后使用以下命令创建容器:

docker run go-image -t go-container -d

但出现了如下错误:

docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/app": permission denied: unknown.

已检查目录权限,确认文件夹具备可执行权限,但仍提示权限拒绝,请问原因是什么?


问题分析与解决

核心问题

你犯了两个关键错误:

  1. ENTRYPOINT指向了目录而非可执行文件:最终阶段的ENTRYPOINT [ "/app" ]中,/app是一个目录,Docker尝试执行目录自然会报权限拒绝——目录本身不能被直接运行。
  2. 编译后的二进制文件未被正确复制到最终镜像:从构建日志的#13和#19阶段的ls输出可以看到,没有Go编译生成的可执行文件。原因是你在构建阶段执行go build后,没有确保二进制文件被正确复制到最终阶段,且多阶段构建中前面阶段的ENTRYPOINT会被后面阶段覆盖,所以ENTRYPOINT /app/app完全无效。

修正后的Dockerfile

# 第一阶段:编译Go程序
FROM golang:latest AS builder

WORKDIR /build

# 先复制依赖文件,利用Docker缓存加速构建
COPY ./user_server/go.mod ./user_server/go.sum ./
RUN go mod download

# 复制所有源代码
COPY ./user_server/ .

# 编译成静态二进制,适配alpine的musl库
RUN CGO_ENABLED=0 GOOS=linux go build -o api-server .

# 第二阶段:生成运行镜像
FROM alpine:latest

# 添加证书,解决HTTPS请求问题
RUN apk --no-cache add ca-certificates

WORKDIR /app

# 只复制编译好的二进制文件,减小镜像体积
COPY --from=builder /build/api-server .

# 赋予执行权限
RUN chmod +x api-server

# 设置启动命令,指向正确的二进制文件
ENTRYPOINT ["./api-server"]

额外修正

你运行容器的命令参数顺序错误,正确的命令应该是:

docker run -d -t --name go-container go-image

参数(-d、-t、--name)要放在镜像名前面,否则Docker会把后面的参数当成容器内执行的命令,导致错误。

内容的提问来源于stack exchange,提问作者M6Gpower

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 17:57:02