Skip to content

Docker容器启动失败:"failed to create shim task: OCI runtime create failed: runc create failed"

问题描述

在Ubuntu系统中使用Docker Compose启动容器时遇到以下错误:

ERROR: for backend Cannot start service backend: failed to create shim task:
OCI runtime create failed: runc create failed: unable to start container process: 
error during container init: error mounting "/var/lib/docker/volumes/.../_data" 
to rootfs at "/app/node_modules": mkdir /var/lib/docker/overlay2/.../merged/app/node_modules:
read-only file system: unknown

这个错误表明Docker在尝试挂载卷到容器内的/app/node_modules目录时遇到了只读文件系统的限制,无法创建所需的目录结构。

错误分析

从提供的Docker Compose配置可以看出问题所在:

yaml
# docker-compose.dev.yml
volumes:
  - ./:/app:ro           # 主机目录以只读方式挂载
  - /app/node_modules    # 匿名卷

这里存在两个问题:

  1. 主项目目录(./)以只读(ro)模式挂载到容器内的/app目录
  2. 同时尝试在容器内创建/app/node_modules目录,但这在只读文件系统上不允许

解决方案

方案1:修改文件权限(推荐)

在Dockerfile中添加权限设置,确保容器内进程有足够的权限访问所需目录:

dockerfile
FROM node:16-alpine
ENV NODE_ENV="development"
WORKDIR /app
COPY package.json .
COPY package-lock.json .
ARG NODE_ENV
RUN apk add g++ make py3-pip
RUN npm install
# 关键步骤:为node_modules目录设置正确的所有权
RUN chown -R node /app/node_modules
RUN npm install -g ts-node nodemon
COPY . ./
ENV PORT 8000
EXPOSE $PORT
CMD ["ts-node", "./src/server.ts"]

添加RUN chown -R node /app/node_modules确保Node.js进程有权限写入node_modules目录。

方案2:调整Compose文件挂载方式

修改docker-compose.dev.yml中的卷配置,移除只读限制:

yaml
volumes:
  - ./:/app           # 移除:ro只读标志
  - /app/node_modules

或者使用更精确的挂载方式:

yaml
volumes:
  - ./src:/app/src    # 仅挂载源代码目录
  - ./package.json:/app/package.json
  - /app/node_modules # node_modules保持容器内独立

方案3:清理和重建容器

有时候Docker环境可能处于损坏状态,需要清理后重新构建:

bash
# 停止并移除容器
docker-compose down

# 清理无用资源
docker system prune

# 重新构建并启动
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build

方案4:检查资源限制

如果使用的是Kubernetes或资源受限环境,确保资源配置合理:

yaml
# deployment.yml - 调整资源请求和限制
resources:
  limits:
    cpu: "600m"
    memory: "1024Mi"
  requests:
    cpu: "100m"
    memory: "500Mi"

过度请求资源可能导致容器无法启动。

预防措施

  1. 避免全局只读挂载:除非确有必要,不要将开发目录以只读方式挂载
  2. 正确设置文件权限:在Dockerfile中确保进程用户有适当的文件访问权限
  3. 使用合适的Base Image:根据技术栈选择正确的基镜像,如Node.js应用使用node官方镜像
  4. 定期清理Docker环境:防止陈旧的镜像和容器导致冲突

常见相关问题

注意路径和命令正确性

确保Dockerfile中的CMD或ENTRYPOINT命令使用容器内存在的可执行文件:

yaml
# 错误:python可能不存在
command: python manage.py runserver 0.0.0.0:8000

# 正确:使用python3
command: python3 manage.py runserver 0.0.0.0:8000

Alpine镜像的特殊处理

使用Alpine等轻量级镜像时,可能需要显式指定shell:

dockerfile
ENTRYPOINT ["/bin/sh", "/my-script.sh"]

总结

"Docker failed to create shim task"错误通常与文件系统权限、挂载配置或资源限制有关。通过合理配置卷挂载方式、设置正确的文件权限以及定期维护Docker环境,可以有效解决和预防这类问题。对于开发环境,建议避免使用全局只读挂载,确保容器内进程有足够的权限访问所需资源。