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

Docker部署Haskell Yesod API时Stack报父目录权限错误排查

解决Docker部署Yesod Haskell API时Stack的权限问题

问题重现

部署Yesod后端API时,执行docker-compose up --build api触发权限错误:

Preventing creation of stack root '/.stack/'. Parent directory '/' is owned by someone else.

问题根源

  1. Docker Compose指定普通用户1000:1000运行容器,但容器根目录/属于root,Stack默认尝试在/.stack创建根目录,普通用户无写入权限。
  2. Dockerfile构建阶段以root执行Stack操作,生成的文件权限与运行阶段的普通用户不匹配。
  3. 挂载的.stack-root卷未指定正确路径,导致Stack仍试图访问无权限的系统目录。

解决方案

1. 修改Dockerfile,统一用户与Stack根目录

调整Dockerfile,创建专用非root用户,指定Stack根目录到工作目录内,并确保文件权限匹配:

FROM haskell:9

# 创建非root用户并配置环境
RUN useradd -m haskelluser
WORKDIR /app

# 切换到非root用户
USER haskelluser

# 指定Stack根目录到当前工作目录,避免访问系统根目录
ENV STACK_ROOT=/app/.stack-root

# 复制项目文件并设置正确权限
COPY --chown=haskelluser:haskelluser . .

# 执行Stack构建步骤
RUN stack setup
RUN stack install yesod-bin --install-ghc
RUN stack build

EXPOSE 8000

CMD ["stack", "exec", "--", "yesod", "devel"]

2. 调整Docker Compose配置

修改卷挂载路径,确保与Dockerfile中指定的Stack根目录一致,并使用创建的专用用户:

api:
  build:
    context: ./api
    dockerfile: Dockerfile
  user: haskelluser:haskelluser
  stdin_open: true
  tty: true
  volumes:
    - ./api:/app
    - ./api/.stack-work:/app/.stack-work
    - ./api/.stack-root:/app/.stack-root
  ports:
    - 8000:3000
  env_file: ./env/yesod.env
  depends_on:
    - database

关键说明

  • 通过ENV STACK_ROOT=/app/.stack-root强制Stack将根目录放在工作目录内,普通用户拥有该目录的写入权限。
  • COPY --chown确保复制到容器内的项目文件属于运行用户,避免挂载后出现权限冲突。
  • 卷挂载明确指定到项目目录下的.stack-work和.stack-root,既保留构建缓存,又保证权限一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:35:19