Docker部署Rails应用至Fly.io时无法复制node_modules至非目录
问题分析与解决方案
问题原因
- 本地与镜像依赖目录冲突:本地项目中
lib/javascript_runtime/node_modules/express是文件(或无效符号链接),而从javscripts构建阶段复制到镜像中的express是目录,执行COPY . .时,Docker尝试将本地文件覆盖镜像中的目录,触发"不能复制到非目录"错误。 - npm命令语法错误:
RUN npm install npm@latest -g. --no-bin-links中-g后多了一个点,导致npm安装异常,可能生成了结构错误的node_modules。 - 复制顺序不合理:先复制构建好的依赖,再复制项目文件,会导致本地文件覆盖镜像中的依赖文件/目录。
解决方案
1. 修复npm命令语法错误
修改javscripts阶段的npm升级命令,移除-g后的多余点:
# 原错误命令 # RUN npm install npm@latest -g. --no-bin-links # 修正后 RUN npm install npm@latest -g --no-bin-links
2. 添加.dockerignore排除本地依赖
在项目根目录创建或更新.dockerignore文件,避免本地依赖目录被复制到镜像中:
node_modules/ lib/javascript_runtime/node_modules/ vendor/bundle/
3. 调整Dockerfile复制顺序
将COPY . .提前到依赖复制之前,确保项目文件先被复制,再用构建阶段的依赖覆盖本地空目录:
# install deployment packages FROM base ARG DEPLOY_PACKAGES="postgresql-client file vim curl gzip libsqlite3-0 nodejs shared-mime-info" ENV DEPLOY_PACKAGES=${DEPLOY_PACKAGES} RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \ --mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \ apt-get update -qq && \ apt-get install --no-install-recommends -y \ ${DEPLOY_PACKAGES} \ && rm -rf /var/lib/apt/lists /var/cache/apt/archives # 先复制项目文件到镜像 COPY . . # 再复制构建好的依赖(精准复制避免覆盖项目文件) COPY --from=gems /app/vendor/bundle /app/vendor/bundle COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions COPY --from=gems /usr/local/bundle /usr/local/bundle COPY --from=gems /usr/share/mime/packages/freedesktop.org.xml /usr/share/mime/packages/freedesktop.org.xml COPY --from=javscripts /app/lib/javascript_runtime/node_modules /app/lib/javascript_runtime/node_modules
4. 清理本地异常文件
删除本地lib/javascript_runtime/node_modules目录,避免残留的无效文件干扰构建:
rm -rf lib/javascript_runtime/node_modules
验证构建
执行构建命令重新测试:
docker build -t rails-fly .
内容的提问来源于stack exchange,提问作者idbentley
相关产品推荐
相关产品推荐

