COPY指令不支持shell通配符主动展开,仅在构建上下文内由Go的filepath.Glob进行有限匹配(如.js),不支持*递归模式;无匹配时构建失败;推荐显式列出文件或预整理目录结构以保障可重现性。

COPY 指令在 Dockerfile 中不支持 shell 通配符(如 *、?、[abc])的**主动展开**,但某些情况下看似“生效”,其实是底层文件系统或构建上下文准备阶段的行为,而非 Docker 引擎解析通配符的结果。
COPY 对通配符的真实行为
Docker 的 COPY 本身不做 glob 展开 —— 它只做字面路径匹配。但当源路径是相对路径且包含 * 时,Docker 构建器会委托宿主机的 Go runtime 使用 filepath.Glob 进行匹配(仅限于构建上下文内存在的文件)。这意味着:
-
COPY *.js /app/会复制构建上下文根目录下所有以.js结尾的文件(不递归) -
COPY src/**/*.ts /app/src/不会生效,因为**不被 Go 的Glob支持(只支持单层*和?) -
COPY config/*.json /app/config/可用,前提是config/目录存在于构建上下文且其中有.json文件 - 如果通配符无匹配,构建会失败(Docker 20.10+ 默认行为),可用
--no-cache或检查上下文内容确认
复制多个不连续目录或文件的正确写法
COPY 不支持单条指令跨多级无关路径批量复制,但可通过多条指令或合理组织上下文实现:
- 逐条写明:
COPY src/ /app/src/COPY public/ /app/public/COPY package.json /app/ - 利用目录结构提前整理:把需复制的资源统一移到临时子目录(如
dist/),再用一条COPY dist/ /app/ - 避免使用
COPY . /app/后删减 —— 会污染镜像层且无法跳过 node_modules 等大目录,应配合.dockerignore
安全与可重现性的关键提醒
通配符易引入隐式依赖,降低构建稳定性:
- 若新增
test.helper.js,COPY *.js会自动包含它 —— 可能意外带入测试代码到生产镜像 - 建议显式列出关键文件(如
COPY package.json package-lock.json ./),再RUN npm ci,比COPY node_modules/更可靠 - 对配置类文件,优先用
ARG+ENV或挂载方式注入,而非全量 COPY
替代方案:需要递归或复杂模式时怎么办
当确实需要类似 **/*.log 的行为,标准 COPY 无法满足,可考虑:
- 构建前用脚本预处理:在
docker build前运行find src -name "*.ts" -exec cp --parents {} ../staging/ \;,再COPY staging/ /app/ - 多阶段构建中用
RUN+cp -r:在 builder 阶段用 shell 命令完成复杂筛选,再COPY --from=builder复制结果 - 避免过度设计:多数应用只需复制明确的源码、配置、构建产物三类路径,通配符反而增加维护成本










