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对象
    @Bean
    public 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 {
       @Resource
    	private MinioClient minioClient;
        /**
    	 * 判断文件是否存在
    	 */
    	@Test
    	void 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控制台正常显示本地时间。查询时,使用工具类就可以了!
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成结构—虚拟存储器

目录 一、虚拟存储器的基本概念 二、页式虚拟存储器 1.页表 2.快表(TLB) 3.具有 TLB 和 Cache 的多级存储系统 三、段式虚拟存储器 四、段页式虚拟存储器 五、虚拟存储器和Cache比较 早期的计算机,CPU 是直接操作主存的,也就是运行程序时&#xf…

深度学习之基于Vgg16卷积神经网络书法字体风格识别

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 书法是中国传统文化的重要组成部分,具有深厚的历史底蕴和独特的艺术魅力。在数字化时代&…

第50期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大语言模型(LLM)等安全领域应用的知识。在这里,您可以找…

损失函数详解

1.损失函数 是一种衡量模型与数据吻合程度的算法。损失函数测量实际测量值和预测值之间差距的一种方式。损失函数的值越高预测就越错误,损失函数值越低则预测越接近真实值。对每个单独的观测(数据点)计算损失函数。将所有损失函数(loss function&#xf…

Baidu Comate:你的智能编码助手,编程效率倍增的秘密武器

Baidu Comate智能编码助手 Baidu Comate 智能编码助手简单介绍安装使用查看Comate插件功能智能代码提示使用飞浆和百度智能小程序进行智能问答使用AutoWork插件实现二次函数图像的生成引用Comate知识库存在的问题结束语 Baidu Comate 智能编码助手简单介绍 Baidu Comate&#x…

设计模式(十一):外观模式

设计模式(十一):外观模式 1. 外观模式的介绍2. 外观模式的类图3. 外观模式的实现3.1 创建一个接口3.2 创建接口的实现3.3 创建一个外观类3.4 测试 1. 外观模式的介绍 外观模式(Facade Pattern)属于结构型模式&#xf…

Jupyter Notebook输入python代码没智能提示

1、在Jupyter中打开控制台 2、再控制台中执行以下两个命令: pip install jupyter_contrib_nbextensions jupyter contrib nbextension install --user pip install jupyter_contrib_nbextensions命令需要下载文件,请耐心等待。 3、执行完成后&#xff0…

202003青少年软件编程(Python)等级考试试卷(二级)

第 1 题 【单选题】 运行下方代码段,输出的结果是(   )。 a=(1,2,3)print(type(a))A :<class ‘float’> B :<class ‘int’> C :<class ‘str’> D :<class ‘tuple’> 正确答案:D 试题解析: 第 2 题 【单选题】 content.txt中原来的内容…

第11篇:创建Nios II工程之控制多个七段数码管

Q&#xff1a;DE2-115开发板上有8个七段数码管&#xff0c;如何用PIO IP并设计Nios II工程控制呢&#xff1f; A&#xff1a;基本思路&#xff1a;DE2-115上有8个7位七段数码管&#xff0c;而一个PIO最多可配置为32位&#xff0c;如此就可以添加2个PIO都配置为28位output。 Ni…

《500 Lines or Less》(13)—— A 3D Modeller

原文 作者 原code 我用py3重写的code 3D 建模器 介绍 计算机辅助设计&#xff08;Computer-aided design, CAD&#xff09;工具允许我们在2D屏幕上查看和编辑3D对象。为此&#xff0c;CAD工具必须具有3个基本功能&#xff1a; 表示对象&#xff1a;使用一种数据结构保存和表示…

SpringBoot的@Async注解有什么坑?

前言 SpringBoot中&#xff0c;Async注解可以实现异步线程调用&#xff0c;用法简单&#xff0c;体验舒适。 但是你一定碰到过异步调用不生效的情况&#xff0c;今天这篇文章总结了Async注解的坑点&#xff0c;希望对你会有所帮助。 未启用异步支持 Spring Boot默认情况下不启…

2024年短剧小程序视频怎么下载

想在闲暇之余轻松追剧&#xff0c;但不想跳转复杂的网页或者安装多个APP吗&#xff1f;来试试2024年的短剧小程序视频下载器吧&#xff01;它是一款专门为短剧爱好者打造的视频下载工具&#xff0c;让你轻松下载任何短剧小程序视频&#xff0c;随时随地享受精彩的短剧内容&…

Python密码测试程序

下面是一个简单的 Python 密码测试程序&#xff0c;用于检查用户输入的密码是否符合一些基本的安全要求&#xff0c;如长度、包含字母和数字等。这个程序可以作为一个基本的密码验证器&#xff0c;你可以根据需要进行修改和扩展。 1、问题背景 我们正在编写一个程序&#xff0…

解决 git克隆拉取代码报SSL certificate problem错误

问题&#xff1a;拉取代码时报错&#xff0c;SSL证书问题:证书链中的自签名证书问题 解决&#xff1a;只需要关闭证书验证&#xff0c;执行下面代码即可&#xff1a; git config --global http.sslVerify "false" 再次拉取代码就可以了

ssh远程免密登录

ssh远程连接分为五个阶段 版本号协商阶段密钥和算法协商阶段认证阶段会话请求阶段交互会话阶段 而上图的SessionKey即是在阶段2&#xff1a;密钥和算法协商阶段&#xff0c;服务器端和客户端利用DH交换&#xff08;Diffie-Hellman Exchange&#xff09;算法、主机密钥对等参数…

零基础自学网络安全/Web安全(超详细入门到进阶)学完即可就业(含学习笔记)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

【前端】HTML实现个人简历信息填写页面

文章目录 前言一、综合案例&#xff1a;个人简历信息填写页面 前言 这篇博客仅仅是对HTML的基本结构进行了一些说明&#xff0c;关于HTML的更多讲解以及CSS、Javascript部分的讲解可以关注一下下面的专栏&#xff0c;会持续更新的。 链接&#xff1a; Web前端学习专栏 下面我对…

OpenNJet 应用引擎:在 NGINX 基础上的云原生增强

目录 一、初识OpenNJet二、系统架构三、动手实践1.CentOS 编译环境配置1.1配置yum源&#xff1a;1.2.yum安装软件包1.3.创建符号连接 2.编译代码编译 OpenNJet执行 make 四、基本使用说明1.目录结构概述:2.常用命令: 五、部署 Web 应用程序配置文件修改启动 NJet 六、总结 一、…

设计宝典与速查手册,设计师必备资料合集

一、资料描述 本套设计资料&#xff0c;大小194.34M&#xff0c;共有13个文件。 二、资料目录 01-《商业设计宝典》.pdf 02-《色彩速查宝典》.pdf 03-《配色宝典》.pdf 04-《解读色彩情感密码》.pdf 05-《行业色彩应用宝典》.pdf 06-《构图宝典》.pdf 07-《创意宝典》…

PXE 批量安装部署

目录 一、PEX批量部署优点 二、PXE&#xff1a;预启动执行环境 三、搭建PXE远程服务器 要想全自动安装 接下来请看步骤&#xff1a; 一、PEX批量部署优点 规模化&#xff1a;同时装配多台服务器自动化&#xff1a;安装系统 配置各种服务远程实现&#xff1a;不需要光盘&…