当前位置: 首页 > news >正文

Dockerfile COPY的奇怪行为:自动解包一级目录

记录一下今天遇到的坑:Dockerfile

这两天在部署项目的时候,新加进去了一个驱动,需要将2个文件夹以及1个文件COPY进镜像,大刀阔斧一个Dockerfile就写完了,结果COPY进去的文件有问题,Dockerfile的内容如下(因涉及到商用项目,只复现,正好本地有tomcat9的镜像,就用这个啦)。



😈 复现

FROM tomcat:9
RUN mkdir -p /home/jim/
COPY ./a /home/jim      # COPY 文件夹
COPY ./1.txt /home/jim  # COPY 文件

其中a文件夹下包含a.txt、b.txt两个文件。

可以看出来我是想将a文件夹及其下面的两个文件以及1.txt文件COPY进镜像,但是执行之后却发现了问题,容器中/home/jim下并没有a文件夹,只放着三个文件,目录结构如下:

我想要的:

/home/jim├── a|   ├── a.txt|   └── b.txt└── 1.txt

我得到的

/home/jim├── a.txt├── b.txt└── 1.txt

搜索一番才了解到Docker有个迷之操作:若是COPY的对象是文件夹,则只会COPY里面的文件,忽略文件夹
就这么个问题,找了好久,其实我一开始猜到了,甚至怀疑是不是也有-r这样的参数,但是没去尝试(所以实践出真知,真的要多操作操作)。



👾 修正

将Dockerfile改到这面这样,就可以实现上面的需求:

FROM tomcat:9
RUN mkdir -p /home/jim/a
COPY ./a /home/jim/a
COPY ./1.txt /home/jim
  1. FROM镜像这个不必要解释
  2. 第二步不再是只创建/home/jim,而是/home/jim/a,这样一来的话,/home/jim文件也有了,/home/jim/a文件夹也有了。
  3. COPY ./a文件夹到/home/jim/a,由于COPY是拷贝的文件夹里的文件们,所以这一步是把a.txt和b.txt放进/home/jim/a目录下
  4. COPY 1.txt/home/jim文件夹下

这样一来,容器里面的/home/jim文件夹下就是:

.
├── a
|   ├── a.txt
|   └── b.txt
└── 1.txt


🥥 验证

# 打包
docker build -f Dockerfile -t test:v1 .
# 启动
docker run -d --name test --restart always -p 8080:8080 test:v1
# 进入
docker exec -it test bash


📎 求实

后面又去搜了一下资料,根据资料有偿试了一下,发现只是第一层目录会被「解包」,二级目录及其子文件还是会正常Copy进去的。

通过测试可以发现 COPY/ADD 命令有这么几个规则:

  • ADD 命令和 COPY 命令在复制文件时行为一致
  • 使用 * 作为 COPY/ADD 命令的源时候表示的是 ./*
  • COPY/ADD 命令的源如果是文件夹,复制的是文件夹的内容而不是其本身
  • COPY ./* target 中的 * 会被翻译成如下的逻辑:
COPY ./sub_dir1 target
COPY ./sub_dir2 target
COPY ./file1 target
COPY ./file2 target

文件系统里的文件夹和文件,本质上都是文件,我们熟悉的操作系统的 cp 命令在执行 cp * target 时会把文件夹当成文件一股脑的复制到目标路径下,可以认为复制了文件本身,而 docker 的 COPY/ADD 在复制文件夹时复制的是其内容。

docker 的这种「奇怪」的逻辑已经被诟病许久了,但是似乎还没有要改变的意思,最新的进展可以参考下面两个 issue,在 docker 做出修改之前,只能在写 dockerfile 时候注意一下了。



🖋️ 参考文章

参考文章:「简书:Docker COPY 复制文件夹的诡异行为」

相关文章:

Dockerfile COPY的奇怪行为:自动解包一级目录

记录一下今天遇到的坑:Dockerfile 这两天在部署项目的时候,新加进去了一个驱动,需要将2个文件夹以及1个文件COPY进镜像,大刀阔斧一个Dockerfile就写完了,结果COPY进去的文件有问题,Dockerfile的内容如下&am…...

【每日一题Day311】LC1761一个图中连通三元组的最小度数 | 枚举

一个图中连通三元组的最小度数【LC1761】 给你一个无向图,整数 n 表示图中节点的数目,edges 数组表示图中的边,其中 edges[i] [ui, vi] ,表示 ui 和 vi 之间有一条无向边。 一个 连通三元组 指的是 三个 节点组成的集合且这三个点…...

前端日期减一天的笑话

vue日期减一天 给大家讲一个真实的笑话。最近做的一个项目,要统计不同年月日期的关联交易数量,由于和银行内数据对接取得数据都是T-1的,所以在首页根据日期统计一些交易数据量时默认是统计昨日的数据量。所以当时和前端约定好的让前端的妹子做…...

高效能,一键批量剪辑,AI智剪让创作更轻松

在今天的数字化时代,视频制作已经成为各种行业和领域的必备技能。然而,视频剪辑过程往往繁琐且耗时,大大降低了我们的工作效率。幸运的是,随着人工智能技术的发展,我们有了新的解决方案——AI智剪软件。 AI智剪软件&am…...

手写Mybatis:第15章-返回Insert操作自增索引值

文章目录 一、目标:Insert自增索引值二、设计:Insert自增索引值三、实现:Insert自增索引值3.1 工程结构3.2 Insert自增索引值类图3.3 修改执行器3.3.1 修改执行器接口3.3.2 抽象执行器基类 3.4 键值生成器3.4.1 键值生成器接口3.4.2 不用键值…...

【数据结构】动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释:

这段C代码实现了一个动态数组&#xff08;vector&#xff09;的基本操作&#xff0c;包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释&#xff1a; // 引入标准输入输出库和标准库函数&#xff0c;用于后续的内存分配和打印输出等操作 #include <stdio.…...

[unity]三角形顶点顺序

序 详见官方文档&#xff1a;Unity - Manual: Mesh data (unity3d.com) Topology&#xff1a;拓扑结构 翻译&#xff1a; 拓扑描述网格具有的面类型。 网格的拓扑定义了索引缓冲区的结构&#xff0c;索引缓冲区又描述了顶点位置如何组合成面。每种类型的拓扑都使用索引数组中…...

【python爬虫】14.Scrapy框架讲解

文章目录 前言Scrapy是什么Scrapy的结构Scrapy的工作原理 Scrapy的用法明确目标与分析过程代码实现——创建项目代码实现——编辑爬虫代码实现——定义数据代码实操——设置代码实操——运行 复习 前言 前两关&#xff0c;我们学习了能提升爬虫速度的进阶知识——协程&#xf…...

功率放大器主要作用是什么呢

功率放大器是一种电子设备&#xff0c;主要作用是将输入信号的功率增加到更高的水平&#xff0c;以便能够驱动高功率负载。在许多应用中&#xff0c;信号源产生的信号往往具有较低的功率&#xff0c;无法直接满足一些要求较高的设备或系统的需求。而功率放大器则可以增强信号的…...

SpringBoot ApplicationEvent详解

ApplicationStartingEvent 阶段 LoggingApplicationListener#onApplicationStartingEvent 初始化日志工厂,LoggingSystemFactory接口&#xff0c;可以通过spring.factories进行定制 可以通过System.setProperty("org.springframework.boot.logging.LoggingSystem",&q…...

WebSocket 报java.io.IOException: 远程主机强迫关闭了一个现有的连接。

在客户端强制关闭时&#xff0c;或者窗口强制关闭时&#xff0c;后端session没有关闭。 有时还会报&#xff1a;java.io.EOFException: 这个异常 前端心跳没有收到信息&#xff0c;还在心跳。 CloseReason close new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, &…...

关于git约定式提交IDEA

背景 因为git提交的消息不规范导致被乱喷&#xff0c;所以领导统一规定了约定式提交 官话 约定式提交官网地址 约定式提交规范是一种基于提交信息的轻量级约定。 它提供了一组简单规则来创建清晰的提交历史&#xff1b; 这更有利于编写自动化工具。 通过在提交信息中描述功能…...

【计算机网络】http协议

目录 前言 认识URL URLEncode和URLDecode http协议格式 http方法 GET POST GET与POST的区别 http状态码 http常见header 简易的http服务器 前言 我们在序列化和反序列化这一章中&#xff0c;实现了一个网络版的计算器。这个里面设计到了对协议的分析与处…...

仓库太大,clone 后,git pull 老分支成功,最新分支失败

由于 git 仓库太大&#xff0c;新加入的小伙伴在拉取时&#xff0c;无法切换到最新的分支&#xff0c;报错如下&#xff1a; fetch-pack: unexpected disconnect while reading sideband packet fatal: early EOF fatal: fetch-pack: invalid index-pack output在此记录解决步…...

javafx Dialog无法关闭

// 生成二维码图片String qrCodeText "https://example.com";DialogPane grid new DialogPane();grid.setPadding(new Insets(5));VBox vBox new VBox();vBox.setAlignment(Pos.CENTER);Image qrCodeImage generateQRCodeImage(qrCodeText);ImageView customImag…...

vue3中TCplayer应用

环境win10:vitevue3elementUI 1 安装 npm install tcplayer.js2 使用 <template><div><video id"player-container-id" width"414" height"270" preload"auto" playsinline webkit-playsinline></video>&l…...

算法通关村14关 | 数据流中位数问题

1. 数据流中位数问题 题目 LeetCode295: 中位数是有序列表中间的数&#xff0c;如果列表长度是偶数&#xff0c;中位数是中间两个数的平均值&#xff0c; 例如:[2,3,4]的中位数是3&#xff0c; [2,3]中位数是&#xff08;23&#xff09;/ 2 2.5 设计一个数据结构&#xff1a; …...

工厂模式 与 抽象工厂模式 的区别

工厂模式&#xff1a; // 抽象产品接口 interface Product {void showInfo(); }// 具体产品A class ConcreteProductA implements Product {Overridepublic void showInfo() {System.out.println("This is Product A");} }// 具体产品B class ConcreteProductB impl…...

安装虚拟机+安装/删除镜像

安装虚拟机 注意&#xff0c;官网可能无法登录&#xff0c;导致无法从官网下载&#xff0c;就自己去网上搜靠谱的下载&#xff0c;我用的16.2.3 删除镜像 Vm虚拟机怎么删除已经创建的系统&#xff1f;Vm虚拟机创建好之后iso删除方法 - 系统之家 (xitongzhijia.net) 安装镜像…...

MySQL的内置函数复合查询内外连接

文章目录 内置函数时间函数字符串函数数学函数其他函数 复合查询多表笛卡尔积自连接在where中使用子查询多列子查询在from中使用子查询 内连接外连接左外连接右外连接 内置函数 时间函数 函数描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...