Skip to content

Docker 运行 "permission denied" 错误的解决方法

问题描述

当使用 Docker 运行容器时,遇到如下错误:

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

该问题通常出现在自定义 Dockerfile 构建的镜像中,当容器尝试启动时,入口点脚本或可执行文件因权限不足无法执行而导致容器启动失败。

根本原因

错误信息中的 permission denied 明确指出权限问题。原因包括:

  • 可执行文件缺少 x(执行)权限
  • 文件属主或权限配置不当
  • 基础镜像缺少必要的运行时环境(如 Alpine 缺少 bash

解决方案

1. 添加文件执行权限(推荐)

在 Dockerfile 中为可执行文件添加执行权限:

dockerfile
FROM golang:1.19.2-alpine as builder

# ... 构建步骤 ...

RUN go build -o deployment-service cmd/deployment-service/main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/

# 复制构建产物
COPY --from=builder /workspace .

# 🔧 关键修复:添加执行权限
RUN chmod +x deployment-service

ARG DEFAULT_PORT=8080
ENV PORT $DEFAULT_PORT
EXPOSE $PORT

CMD ["./deployment-service"]

为什么需要这一步?

通过 COPY 复制的文件默认会保留原始权限。如果构建阶段(builder)生成的文件缺少执行权限,会导致运行时权限错误。

2. 显式使用 Shell 作为入口

如果权限已配置仍报错,尝试通过 shell 执行程序:

dockerfile
CMD ["sh", "-c", "./deployment-service"]

Alpine 镜像的特殊性

Alpine 镜像默认不包含 bash,以下写法会报错:

dockerfile
# 错误示例:Alpine 中没有 bash
CMD ["bash", "-c", "./deployment-service"]

使用 sh(所有 Alpine 镜像自带)替代 bash

3. 规范使用 ENTRYPOINT

当需要指定解释器时,推荐使用 ENTRYPOINTCMD 组合:

dockerfile
FROM alpine:latest
# ...
ENTRYPOINT ["/deployment-service"]  # 作为主执行程序
# 或
ENTRYPOINT ["sh", "-c"]   # 定义基础解释器
CMD ["./deployment-service"]  # 作为参数传递

附加排查方法

检查本地文件权限

在宿主机构建前确保源文件可执行:

sh
# 在项目目录执行
chmod a+x ./deployment-service

清理 Docker 缓存

在修改 Dockerfile 后清理构建缓存:

sh
docker system prune -a
docker build --no-cache -t server:latest .

验证容器配置

在运行容器时可通过 --entrypoint 测试命令:

sh
docker run -it --entrypoint /bin/sh server:latest
/root # ls -l deployment-service  # 检查文件权限
/root # ./deployment-service     # 手动测试运行

最佳实践总结

  1. 显式设置权限:在 Dockerfile 中为所有可执行文件添加 RUN chmod +x
  2. 适应基础镜像:Alpine 环境优先使用 /bin/sh 而非 /bin/bash
  3. 分层构建注意:多阶段构建时,复制文件可能导致权限变动(使用 --chmod 选项)
  4. 构建后验证:在容器内手动执行命令确认权限状态

通过为可执行文件配置正确权限并选择兼容的执行方式,即可彻底解决 permission denied 错误,确保容器正常启动。