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.
已检查目录权限,确认文件夹具备可执行权限,但仍提示权限拒绝,请问原因是什么?
问题分析与解决
核心问题
你犯了两个关键错误:
- ENTRYPOINT指向了目录而非可执行文件:最终阶段的
ENTRYPOINT [ "/app" ]中,/app是一个目录,Docker尝试执行目录自然会报权限拒绝——目录本身不能被直接运行。 - 编译后的二进制文件未被正确复制到最终镜像:从构建日志的
#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
相关产品推荐
相关产品推荐

