Minio(官方docker版)容器部署时区问题研究记录

文章目录

  • 感慨&概述
    • 补充:MINIO_REGION和容器时间的关系
  • 问题一:minio容器和本地容器时间不一致
    • 问题说明
    • 原因探究
    • 解决方法
    • 结果验证
  • 问题二:minio修改时间和本地查询结果不一致
    • 具体问题
    • 原因探究
    • 解决办法
    • 时间转化工具类
    • 调用测试和验证
    • 上传文件说明

感慨&概述

  • 在使用minio(容器部署方式)的过程中,由于使用容器时间和本地时间不同,然后寻求解决方法,花费了很多时间,然后才有以下的收获和整理。整个过程耗费不少时间。
  • 本文章对于bitnami/minio:latestminio/minio问题二:minio修改时间和本地查询结果不一致上均适用。在问题一:minio容器和本地容器时间不一致bitnami/minio:latest在部署时,使用TZ=Asia/Shanghai即可解决问题。

补充:MINIO_REGION和容器时间的关系

  • region描述的是服务器的物理位置,默认是us-east-1(美国东区1),也是亚马逊S3的默认区域。可以通过MINIO_REGION环境变量进行修改
  • 修改MINIO_REGION并不能解决,容器时间和本地时间问题,也不能解决文件最后修改时间在web控制台和java查询时间不一致的问题。这个可能是为了minio容器部署时,划分机器用的(如果错误,请大佬指导)
  • 当然,注意如果设置了MINIO_REGION请在java代码中配置同样的时区设置,否则导致代码运行失败,因为时区相差太大无法正常连接到minio
  • 当启动MinIO Docker容器时,可以通过设置环境变量MINIO_REGION来指定区域(如无需要,建议不要配置)
docker run -p 9000:9000 --name minio1 \-e "MINIO_ROOT_USER=minioadmin" \-e "MINIO_ROOT_PASSWORD=minioadmin" \-e "MINIO_REGION=cn-north-1" \-e "TZ=Asia/Shanghai" \minio/minio server /data
  • java minioclient配置
@Configuration
public class Config {//链式编程 构建MinioClient对象@Beanpublic MinioClient minioClient(){return MinioClient.builder().region("cn-north-1") //注意一致.endpoint("http://192.168.1.18:9000").credentials("minioadmin","minioadmin").build();}
}

问题一:minio容器和本地容器时间不一致

问题说明

  • 使用的Minio容器版本为1Panel中应用商店提供的minio官方镜像版本minio/minio:RELEASE.2024-04-06T05-26-02Z
  • minio容器内查看时间,刚好和本机相差八小时
    bash-5.1# date 
    Sat May  4 15:58:36 CST 2024
    bash-5.1# exit
    exit
    [root@yang ~]# date
    2024年 05月 04日 星期六 23:58:43 CST
    

原因探究

  • 这里不再详述探究的过程,简略地给出研究思路、方法。
  • 研究思路:查看容器中使用的时区,将其修改为东八区。
  • 研究过程和结果:在该版本容器内查看没有常见的linux时区设置的目录和文件,不过通过复制本地的文件到,minio容器中重新设置时区,可以成功解决容器时区和本地时区不一致的问题。

解决方法

  1. 查看容器信息
    # 查看运行中minio容器的名称
    docker ps
    
    • 例如:运行中的MInio容器ID为 826ab07a0a42,名称为 minio
    [root@yang ~]# docker ps
    CONTAINER ID   IMAGE                                      COMMAND                   CREATED          STATUS          PORTS                                                                                  NAMES
    826ab07a0a42   minio/minio:RELEASE.2024-04-06T05-26-02Z   "/usr/bin/docker-ent…"   14 minutes ago   Up 14 minutes   0.0.0.0:9001->9000/tcp, :::9001->9000/tcp, 0.0.0.0:9000->9001/tcp, :::9000->9001/tcp   minio
    
  2. 进入容器创建时区文件目录
    # 进入容器 下面的两个命令任选其一即可
    # 命令一
    docker exec -it  docker_Minio_name bash # 上一步查询的信息 minio
    # 命令二
    docker exec -it  docker_Minio_ID bash # 上一步查询的信息 826ab07a0a42
    # 在容器内执行命令:创建时区文件目录
    mkdir -p  /usr/share/zoneinfo/Asia/
    # 推出容器命令
    exit
    
  3. 复制本地时区文件到容器
    # 复制本地的时区配置文件到容器中
    [root@localhost ~]# docker cp /usr/share/zoneinfo/Asia/Shanghai docker_Minio_name:/usr/share/zoneinfo/Asia/
    # 操作成功演示
    [root@yang ~]# docker cp /usr/share/zoneinfo/Asia/Shanghai minio:/usr/share/zoneinfo/Asia/
    Successfully copied 2.56kB to minio:/usr/share/zoneinfo/Asia/
    
  4. 再次进入容器内部,修改本地时间
    # 再次进入容器 下面的两个命令任选其一即可
    # 命令一
    docker exec -it  docker_Minio_name bash # 上一步查询的信息 minio
    # 命令二
    docker exec -it  docker_Minio_ID bash # 上一步查询的信息 826ab07a0a42# 定义本地的时区配置文件
    ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime  
    # 演示
    bash-5.1# ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    

结果验证

  1. 使用命令查看容器和本机时间是否一致
    # 验证解决结果
    bash-5.1# date 
    Sat May  4 23:58:36 CST 2024
    bash-5.1# exit
    exit
    [root@yang ~]# date
    2024年 05月 04日 星期六 23:58:43 CST
    

  • Minio上传文件测试时间是否生效
  • 在观察页面显示正常,但是遗憾的是,如果使用java minio客户端查询还是显示相差八小时。(这是第二个问题)
    在这里插入图片描述

问题二:minio修改时间和本地查询结果不一致

具体问题

  • minio在web管理显示的文件最后修改时间和本地一致,然后使用java代码查询出来的时间和本地时间差八个小时
    在这里插入图片描述
  • 查询代码和结果
//查询代码
@Test
void testObjectExists() throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {StatObjectResponse response = minioClient.statObject(StatObjectArgs.builder().bucket("test02").object("image.jpg").build());System.out.println(response);
}		
//查询结果
ObjectStat{bucket=test02, object=image.jpg, last-modified=2024-05-04T06:53:55Z, size=563102}

原因探究

  • MinIO存储文件的元数据时,通常会使用UTC(协调世界时间)来记录时间戳。这意味着无论实际的物理服务器位置如何,时间都会按照UTC来记录。但在Web管理界面中,MinIO会根据浏览器的时区设置自动调整显示时间,使其看起来与本地时间一致。
  • 当使用Java代码通过MinIO的API查询文件的最后修改时间时,如果没有正确处理时区,Java可能会默认将UTC时间作为本地时间(即不进行时区转换)来处理。导致看到的时间比实际的本地时间少8小时(中国大陆时间为UTC+8)。

解决办法

  • Java代码在处理时间时将UTC时间转换为本地时间(虽然麻烦,但只能这么解决问题)

时间转化工具类

  • 这里我给出一个已验证可用的工具类
import java.lang.annotation.Retention;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;public class TimeConverter {// 使用自定义格式化模式private static final DateTimeFormatter isoFormatter = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE).appendLiteral('T').append(DateTimeFormatter.ISO_LOCAL_TIME).optionalStart().appendOffsetId().optionalEnd().toFormatter();private static final DateTimeFormatter customFormatter = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE).appendLiteral('T').append(DateTimeFormatter.ISO_LOCAL_TIME).appendLiteral('Z') // 添加字面值 'Z' 表示时区偏移量.toFormatter();/*** 将UTC时间转换为指定时区的时间,格式保持ISO-8601 默认时区为东八区* @param utcTimeString UTC时间字符串(ISO-8601格式)* @return 指定时区的时间字符串(ISO-8601格式)*/public static String convertUtcToLocal(String utcTimeString) {String zoneIdString="Asia/Shanghai";return convertUtcToLocal(utcTimeString,zoneIdString);}/*** 将UTC时间转换为指定时区的时间,格式保持ISO-8601* @param utcTimeString UTC时间字符串(ISO-8601格式)* @param zoneIdString 时区ID,如"Asia/Shanghai"* @return 指定时区的时间字符串(ISO-8601格式)*/public static String convertUtcToLocal(String utcTimeString, String zoneIdString) {Instant utcTime = Instant.parse(utcTimeString);ZonedDateTime localTime = utcTime.atZone(ZoneId.of(zoneIdString));DateTimeFormatter formatter = customFormatter.withZone(ZoneId.of(zoneIdString));return formatter.format(localTime);}/*** 将本地时间转换为UTC时间* @param localTimeString 本地时间字符串(ISO-8601格式)* @param zoneIdString 时区ID,如"Asia/Shanghai"* @return UTC时间字符串(ISO-8601格式)*/public static String convertLocalToUtc(String localTimeString) {String zoneIdString="Asia/Shanghai";return convertLocalToUtc(localTimeString,zoneIdString);}/*** 将本地时间转换为UTC时间* @param localTimeString 本地时间字符串(ISO-8601格式)* @param zoneIdString 时区ID,如"Asia/Shanghai"* @return UTC时间字符串(ISO-8601格式)*/public static String convertLocalToUtc(String localTimeString, String zoneIdString) {ZonedDateTime localTime = ZonedDateTime.parse(localTimeString, customFormatter.withZone(ZoneId.of(zoneIdString)));Instant utcTime = localTime.toInstant();return isoFormatter.format(utcTime.atZone(ZoneId.of("UTC")));}// 测试主方法public static void main(String[] args) {String utcTime = "2024-05-07T04:20:00Z";System.out.println("原UTC时间: " + utcTime);System.out.println("转换为北京时间: " + convertUtcToLocal(utcTime));String shanghaiTime = "2024-05-20T20:20:00Z";System.out.println("从北京时间转换回UTC时间: " + convertLocalToUtc(shanghaiTime));}
}
  • 测试结果
    UTC时间: 2024-05-07T04:20:00Z
    转换为北京时间: 2024-05-07T12:20:00Z
    从北京时间转换回UTC时间: 2024-05-20T12:20:00Z
    

调用测试和验证

  • 测试类代码
    @SpringBootTest
    class MinioApplicationTests {@Resourceprivate MinioClient minioClient;/*** 判断文件是否存在*/@Testvoid testObjectExists() throws Exception {StatObjectResponse response = minioClient.statObject(StatObjectArgs.builder().bucket("test02").object("image.jpg").build());System.out.println("修改前文件信息:"+response);String localLastModifiedTime = TimeConverter.convertUtcToLocal(response.lastModified().toString());ZonedDateTime localLastModified = ZonedDateTime.parse(localLastModifiedTime);//通过反射 修改文件信息 不影响minio存储的文件信息try {Field lastModifiedField = response.getClass().getDeclaredField("lastModified");lastModifiedField.setAccessible(true);lastModifiedField.set(response, localLastModified);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}System.out.println("修改后文件信息:"+response);}
    }
    
  • 测试结果
    修改前文件信息:ObjectStat{bucket=test02, object=image.jpg, last-modified=2024-05-04T06:53:55Z, size=563102}
    修改后文件信息:ObjectStat{bucket=test02, object=image.jpg, last-modified=2024-05-04T14:53:55Z, size=563102}
    

在这里插入图片描述

上传文件说明

  • 在查询文件信息时,需要将文件修改时间进行本地化转化,但是在上传文件的时候,我没找到直接设置文件修改时间的配置。所以,上传文件的时候,正常上传就行。
/*** 上传文件*/
@Test
void testObjectUpload() throws Exception {ObjectWriteResponse response = minioClient.uploadObject(UploadObjectArgs.builder().bucket("test02").object("image3.jpg").filename("src/main/resources/picture/image.jpg").build());System.out.println(response);
}
  • 上传成功后,在web控制台正常显示本地时间。查询时,使用工具类就可以了!
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/7945.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unit6

Unit6 1. val 强壮 valid invalid validate invalidate prevail prevailing prevalent 2. pri 主要的 prime Prime Minister premier primary primary school prior prior to sth prioritize priority principle principal prince princess 3. nov 新 news newspap…

thinkphp5 中路由常见的使用方法

在ThinkPHP 5中,路由的常见使用方法主要包括以下几个方面: 基本路由配置: 你可以通过修改config目录下面的route.php文件来配置路由规则。例如,使用Route::get或Route::post等方法定义不同的HTTP请求类型的路由。 use think\Route…

stm32芯片外设

STM32 F1系列微控制器是ST公司推出的一系列基于ARM Cortex-M3内核的微控制器。这一系列微控制器拥有丰富的外设资源,包括但不限于: ADC(模数转换器):用于将模拟信号转换为数字信号,通常用于传感器数据的读取…

高级数据结构与算法习题(9)

一、判断题 1、Let S be the set of activities in Activity Selection Problem. Then the earliest finish activity am​ must be included in all the maximum-size subset of mutually compatible activities of S. T F 解析:F。设S是活动选择问题中的一…

flutter开发实战-webview_flutter 4.x版本使用

flutter开发实战-webview_flutter 4.x版本使用 在之前使用的webview_flutter版本是3.x的,升级到4.x后,使用方式有所变化。 一、webview_flutter 在工程的pubspec.yaml中引入插件 webview_flutter: ^4.4.2二、使用webview_flutter 在4.x版本中&#…

JAVA语言开发的(智慧校园系统源码)智慧校园的痛点、智慧校园的安全应用、智慧校园解决方案

一、智慧校园的痛点 1、信息孤岛问题:由于校园内各部门或系统独立开发,缺乏统一规划和标准,导致数据无法有效整合和共享,形成了信息孤岛。 2、技术更新与运维挑战:智慧校园的建设依赖于前沿的信息技术,如云…

15【PS作图】像素画地图绘制

绘制视角 绘制地图的时候,有的人会习惯把要绘制的 房子、车子、围栏 小物件先画好,然后安放在地图上 但这样绘制出的各种物件之间,会缺乏凝聚力 既然物品都是人构造出的,不如以人的视角去一步步丰富地图; 比如下图…

关于c++ 中 string s { ‘a‘ , ‘b‘ , ‘c‘ , ‘d‘ } 的方式的构造过程

(1)这样的构造方式不常见,但也确实 STL 库提供了这样的构造函数 (2)以反汇编分析这行代码 (3)谢谢阅读

前端深度扩展

1 为什么要有webpack 模块化管理:构建工具支持Common JS、ES6模块等规范;依赖管理:在大型项目中,手动管理文件依赖关系。webpack可以自动分析项目中的依赖关系,将其打包成1个或多个优化过的文件,减少页面加…

【网络】深入了解端口,一个端口能否被多个进程绑定

引言 在计算机网络中,端口是一项关键概念,它在网络通信中扮演着重要的角色。本文将深入介绍端口的作用、分类,并分析一个端口能否被多个进程绑定的问题。 1. 端口的作用 端口是计算机与网络通信的入口或出口,用于标识进程和应用…

Prefiquence(双指针,动态规划)

文章目录 题目描述输入格式输出格式样例样例输入 #1样例输出 #1样例输入 #2样例输出 #2样例输入 #3样例输出 #3 提示提交链接解析参考代码 题目描述 给您两个二进制字符串 a a a 和 b b b 。二进制字符串是由字符 0 0 0 和 1 1 1 组成的字符串。 您的任务是确定最大可能的…

【数据结构与算法】力扣 239. 滑动窗口最大值

题干描述 给你一个整数数组 nums,有一个大小为 k **的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入: nums [1,3,-1,-3,5,3…

代码随想录day56 | 动态规划P16 | ● 583. ● 72. ● 编辑距离总结篇

583. 两个字符串的删除操作 给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 示例 1: 输入: word1 "sea", word2 "eat" 输出: 2 解释: 第一步将 &quo…

嵌入式开发常见概念简介

目录 0. 《STM32单片机自学教程》专栏总纲 API Handle(句柄) 0. 《STM32单片机自学教程》专栏总纲 本文作为专栏《STM32单片机自学教程》专栏其中的一部分,返回专栏总纲,阅读所有文章,点击Link: STM32单片机自学教程-[目录总纲]_stm32 学习-CSD…

每日OJ题_贪心算法三⑤_力扣134. 加油站

目录 力扣134. 加油站 解析代码 力扣134. 加油站 134. 加油站 难度 中等 在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一…

java设计模式三

工厂模式是一种创建型设计模式,它提供了一个创建对象的接口,但允许子类决定实例化哪一个类。工厂模式有几种变体,包括简单工厂模式、工厂方法模式和抽象工厂模式。下面通过一个简化的案例和对Java标准库中使用工厂模式的源码分析来说明这一模…

SpringBoot3项目打包和运行

六、SpringBoot3项目打包和运行 6.1 添加打包插件 在Spring Boot项目中添加spring-boot-maven-plugin插件是为了支持将项目打包成可执行的可运行jar包。如果不添加spring-boot-maven-plugin插件配置,使用常规的java -jar命令来运行打包后的Spring Boot项目是无法找…

linux笔记--tmux的使用

目录 1--安装tmux 2--创建新会话 3--离开会话 4--查看所有会话 5--进入会话 6--结束会话 1--安装tmux # Ubuntu 或 Debian sudo apt-get install tmux# CentOS 或 Fedora sudo yum install tmux# Mac brew install tmux 2--创建新会话 tmux new -s <session-name&g…

scrapy常用命令总结

1.创建scrapy项目的命令&#xff1a;     scrapy startproject <项目名字> 示例&#xff1a;     scrapy startproject myspider 2.通过命令创建出爬虫文件&#xff0c;爬虫文件为主要的代码文件&#xff0c;通常一个网站的爬取动作都会在爬虫文件中进行编写。 …

Java学习第01天-Java基本内容

目录 单行注释 多行注释 文档注释&#xff08;GPT生成&#xff09; 字面量 分类 使用示例 变量 定义 定义格式 注意事项 数据类型分类 命名指导规范 补充 单行注释 public class note {public static void main(String[] args) {// 单行注释} }多行注释 publ…