多阶段构建无法排除.dockerignore指定文件的技术问询
嘿,这个问题我太熟了!你遇到的核心坑在于:.dockerignore只在从本地文件系统往Docker镜像复制文件的时候生效,而多阶段构建里的COPY --from=0这种跨阶段复制,是直接在镜像之间拷贝内容,根本不会搭理你本地的.dockerignore规则。
咱们来拆解下你的Dockerfile:第一阶段你把本地文件拷进去时,node_modules还不存在,所以.dockerignore确实起了作用;但你跑了yarn之后,第一阶段的/app目录里就生成了node_modules。第二阶段直接把第一阶段的整个/app拷过来,自然就把这个文件夹也带过来了,这可不是你想要的结果对吧?
给你几个实用的解决办法,按需选:
方法一:精准复制,只拿需要的文件
别图省事复制整个/app,只挑生产环境必须的文件/目录,这样既避开了冗余内容,还能把镜像体积压到最小。比如:
FROM node:alpine WORKDIR /app # 先拷依赖文件,利用Docker缓存优化构建速度 COPY package.json yarn.lock ./ RUN yarn install --production # 加--production只装生产依赖,进一步瘦身 # 再拷业务代码 COPY index.js ./ FROM node:alpine WORKDIR /app # 只复制第一阶段的生产依赖和必要文件 COPY --from=0 /app/node_modules ./node_modules COPY --from=0 /app/index.js ./ COPY --from=0 /app/package.json ./
方法二:在源阶段先清理冗余文件
如果不想一个个列文件,也可以在第一阶段的末尾,手动删掉.dockerignore里指定的那些内容,再复制到第二阶段:
FROM node:alpine WORKDIR /app COPY . . RUN yarn install --production \ && rm -rf node_modules/.cache .git .gitignore .dockerignore Dockerfile # 删掉不需要的文件/目录 FROM node:alpine WORKDIR /app COPY --from=0 /app .
不过这个方法要注意,你得手动对应.dockerignore里的所有规则,容易漏,不如方法一靠谱。
方法三:用构建阶段分离产物(最推荐)
如果你的项目需要构建(比如TS转JS、打包静态资源),可以把构建和运行分成两个阶段,生产镜像只拿构建好的产物和生产依赖,这是最标准的精简镜像做法:
# 第一步:构建阶段(只负责生成产物) FROM node:alpine AS builder WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install # 这里装全量依赖,因为要跑构建命令 COPY . . RUN yarn build # 假设你的构建命令是yarn build,生成dist目录 # 第二步:生产阶段(只保留运行必需的内容) FROM node:alpine WORKDIR /app COPY --from=builder /app/package.json ./ COPY --from=builder /app/yarn.lock ./ RUN yarn install --production # 只复制构建好的产物 COPY --from=builder /app/dist ./dist # 如果不需要构建,就复制你的业务源码 # COPY --from=builder /app/index.js ./
总的来说,核心就是:跨阶段复制不受.dockerignore约束,所以要么精准拷贝需要的内容,要么在源阶段提前清理掉冗余文件。这样既能解决你的问题,还能让镜像体积更小巧。
内容的提问来源于stack exchange,提问作者Yingray Lu
相关产品推荐
相关产品推荐

