当前位置: 首页 > 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()当前时间戳…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...