Docker容器exited(1)状态求助:挂载本地目录后启动失败
我是Docker新手,执行第一条命令docker run -d -p 3000:3000 -v "$(pwd)":/app/data react-app时能正常访问应用;但执行第二条命令docker run -d -p 3000:3000 -v "$(pwd)":/app react-app后,容器进入exited(1)状态,无法访问应用。
容器日志信息
npm ERR! A complete log of this run can be found in: npm ERR! /home/app/.npm/_logs/2023-03-07T15_34_40_347Z-debug.log sh: react-scripts: not found npm ERR! code ELIFECYCLE npm ERR! syscall spawn npm ERR! file sh npm ERR! errno ENOENT npm ERR! react-app@0.1.0 start: `react-scripts start` npm ERR! spawn ENOENT npm ERR! npm ERR! Failed at the react-app@0.1.0 start script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm WARN Local package.json exists, but node_modules missing, did you mean to install? npm ERR! A complete log of this run can be found in: npm ERR! /home/app/.npm/_logs/2023-03-07T15_37_46_136Z-debug.log
我尝试改用命令docker run -d -p 3000:5000 --mount type=bind,source="$(pwd)",target=/app react-app,挂载成功但容器仍处于exited(1)状态,挂载信息如下:
"Mounts": [ { "Type": "bind", "Source": "/Users/hamid/Docker/Mosh_Docker/docker_files/Section 5- Containers/section5-react-app", "Destination": "/app", "Mode": "", "RW": true, "Propagation": "rprivate" } ],
Dockerfile内容
FROM node:14.16.0-alpine3.13 RUN addgroup app && adduser -S -G app app USER app WORKDIR /app RUN mkdir data COPY package*.json . RUN npm install COPY . . ENV API_URL=http://api.myapp.com/ EXPOSE 3000 CMD ["npm", "start"]
问题原因与解决方案
核心原因
把本地目录挂载到容器/app时,会完全覆盖容器内原有的/app目录内容。Dockerfile中RUN npm install是在容器/app下安装依赖,生成了node_modules文件夹;但挂载本地目录后,容器内/app被替换成你本地的目录,而本地目录没有node_modules,导致执行npm start时找不到react-scripts(依赖包存放在node_modules中),最终容器启动失败。
第一条命令挂载到/app/data正常,是因为仅替换/app/data目录,容器内/app下的node_modules等关键文件未被覆盖。
可行解决方案
方案1:挂载单个文件/目录(推荐开发环境)
不要挂载整个/app,只挂载需要同步的源码目录或文件,保留容器内的node_modules:
# 挂载本地src目录到容器 docker run -d -p 3000:3000 -v "$(pwd)/src:/app/src" react-app # 挂载本地public目录到容器 docker run -d -p 3000:3000 -v "$(pwd)/public:/app/public" react-app
方案2:使用Docker卷隔离node_modules
创建独立卷存储node_modules,避免挂载目录时被覆盖:
# 创建存储依赖的卷 docker volume create react-app-node-modules # 同时挂载本地目录和依赖卷运行容器 docker run -d -p 3000:3000 \ -v "$(pwd)":/app \ -v react-app-node-modules:/app/node_modules \ react-app
容器启动时会自动将原有node_modules复制到卷中,后续挂载本地目录时不会覆盖依赖。
方案3:启动时重新安装依赖(临时方案)
修改启动命令,在启动前执行npm install,但每次启动都会重新安装依赖,速度较慢:
docker run -d -p 3000:3000 -v "$(pwd)":/app react-app sh -c "npm install && npm start"
内容的提问来源于stack exchange,提问作者bizimunda

