{"id":393723,"date":"2024-06-29T11:10:52","date_gmt":"2024-06-29T11:10:52","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=393723"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=393723","title":{"rendered":"<span>\u0417\u0430\u0447\u0435\u043c \u0438 \u043a\u0430\u043a \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 MinIO<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/57d\/8fc\/dc2\/57d8fcdc203b2e915385dd093552bf12.png\" width=\"1600\" height=\"901\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/57d\/8fc\/dc2\/57d8fcdc203b2e915385dd093552bf12.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0448\u0430 \u0431\u0438\u0433 \u0434\u0430\u0442\u0430 \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0430 Telegram-\u0447\u0430\u0442\u044b, \u0444\u043e\u0440\u0443\u043c\u044b \u0438 \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440\u044b \u0432 \u043a\u0443\u043b\u0443\u0430\u0440\u0430\u0445 IT-\u043c\u0435\u0440\u043e\u043f\u0440\u0438\u044f\u0442\u0438\u0439 \u0438 \u043f\u043e\u043c\u0435\u0442\u0438\u043b\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043a\u0430\u043a \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0451 \u043d\u0435 \u0432\u0441\u0435 \u043e\u0441\u043c\u0435\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u0425\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0441\u0442\u0430\u0442\u044c\u0438-\u0432\u043e\u0440\u043a\u0448\u043e\u043f\u0430. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u044d\u0442\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 \u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438 \u0435\u0451 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.\u00a0<\/p>\n<p>\u0417\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432?<\/p>\n<p>\u0421 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0445 \u043f\u043e\u0440 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e Golang-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0432 Ozon. \u0423 \u043d\u0430\u0441 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0435\u0441\u0442\u044c \u043a\u0440\u0443\u0442\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0430\u0434\u043c\u0438\u043d\u043e\u0432 \u0438 \u0440\u0435\u043b\u0438\u0437-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0430 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 CI \u0432\u043e\u043a\u0440\u0443\u0433 \u043d\u0435\u0451. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u044f \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u044e\u0441\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c.\u00a0<\/p>\n<p>\u041d\u043e \u0434\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0430 \u0432 Ozon \u044f \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c\u0438 \u043a\u0435\u0439\u0441\u0430\u043c\u0438, \u043a\u043e\u0433\u0434\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439) \u0431\u044b\u043b\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u0438\u0437\u044f\u0449\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u041c\u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043b\u0438\u0441\u044c SFTP, Google Drive \u0438 \u0434\u0430\u0436\u0435 \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 PVC \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440!\u00a0<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u044d\u0442\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0441\u043e\u043f\u0440\u044f\u0436\u0435\u043d\u043e \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u042d\u0442\u043e \u0438 \u043f\u0440\u0438\u0432\u0435\u043b\u043e \u043c\u0435\u043d\u044f \u043a \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0443 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u043c\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u043c\u0438, \u0432\u0435\u0434\u044c \u0441 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0435\u0448\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0439 \u0440\u044f\u0434 \u0437\u0430\u0434\u0430\u0447.\u00a0<\/p>\n<h2>TL;DR<\/h2>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u2013 \u044d\u0442\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u043d\u0430\u0434 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0438 \u0445\u043e\u0441\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 (\u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f, \u0445\u0440\u0430\u043d\u0438\u0442\u044c) \u0447\u0435\u0440\u0435\u0437 API.<\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0432\u0430\u043c \u0432 \u043a\u0435\u0439\u0441\u0430\u0445, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\/-\/tree\/main\/server\"><u>\u0444\u0430\u0439\u043b\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0432\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445<\/u><\/a>, <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\/-\/blob\/main\/manifestos\/gitlab-ci.yml\"><u>\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u043a\u0443<\/u><\/a> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\/-\/blob\/main\/manifestos\/ingress-static.yaml\"><u>Ingress<\/u><\/a> \u0438\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c <a href=\"https:\/\/docs.gitlab.com\/runner\/configuration\/speed_up_job_execution.html#use-minio\"><u>\u043a\u0435\u0448\u0438 \u0432\u0430\u0448\u0435\u0433\u043e CI<\/u><\/a>.\u00a0<\/p>\n<p>\u0412\u0441\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u043a \u0441\u0442\u0430\u0442\u044c\u0435 (\u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438, \u043a\u043e\u043d\u0444\u0438\u0433\u0438, \u0441\u043a\u0440\u0438\u043f\u0442\u044b) \u043b\u0435\u0436\u0430\u0442 \u0432\u043e\u0442 \u0432 \u044d\u0442\u043e\u0439 <a href=\"http:\/\/gitlab.com\/worldbug\/storage-examples\"><u>\u0440\u0435\u043f\u0435<\/u><\/a>.\u00a0<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/h3>\n<p><a class=\"anchor\" name=\"%D1%87%D1%82%D0%BE_%D1%82%D0%B0%D0%BA%D0%BE%D0%B5_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B\" id=\"\u0447\u0442\u043e_\u0442\u0430\u043a\u043e\u0435_\u043e\u0431\u044a\u0435\u043a\u0442\u044b\"><\/a><\/p>\n<p>\u0425\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438, \u043e\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u0434\u043e \u0431\u043b\u043e\u0431\u0430 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0411\u0414 (\u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u044d\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442, \u043a\u043e\u043d\u0435\u0447\u043d\u043e). \u041d\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c?  \u0427\u0430\u0441\u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c: \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c, \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438, \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c. \u0422\u0443\u0442 \u0443\u0436\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u0411\u0414 \u0438\u043b\u0438 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c. \u0412 \u044d\u0442\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0445\u043e\u0441\u0442\u0430, \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439. <\/p>\n<p>\u0418 \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0442\u0435 \u0441\u0430\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0438 \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c. \u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u2013 \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0433\u0438\u0431\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043a \u043d\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u0430\u043a \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c (\u0444\u0430\u0439\u043b\u0430\u043c). \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u2013 \u044d\u0442\u043e \u0444\u0430\u0439\u043b \u0438 \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043d\u0451\u043c.\u00a0<\/p>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0435\u0449\u0451 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c, \u0447\u0442\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u0445 \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u044f\u0442\u0438\u044f, \u043a\u0430\u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432. \u0412\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u00ab\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435\u00bb \u2013 bucket. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a: <code>objectScope\/firstObject.dat<\/code> .<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445 \u2013 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043e\u0442 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0435\u0442\u0430\u043b\u0435\u0439. \u041d\u0430\u0441 \u0443\u0436\u0435 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442, \u043a\u0430\u043a\u0430\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f (\u0438\u043b\u0438 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f) \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0440\u0430\u043d\u0438\u0442 \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435. \u041c\u044b \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u043a\u0430\u043a\u0438\u043c\u0438-\u0442\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u0438\u0445 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430.\u00a0<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0442\u0438\u043f\u044b \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449, \u0430 \u043e\u0431\u0440\u0430\u0442\u0438\u043c \u043d\u0430\u0448\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u0441\u0442\u043e\u0440\u0430\u0434\u0436\u0435\u0439, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 MinIO. \u0412\u044b\u0431\u043e\u0440 \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d \u0442\u0435\u043c, \u0447\u0442\u043e MinIO \u0438\u043c\u0435\u0435\u0442 \u043d\u0438\u0437\u043a\u0438\u0439 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 (\u043f\u0440\u0438\u0432\u0435\u0442, Ceph), <s>\u0430 \u0435\u0449\u0451 \u043e\u043d\u043e Kubernetes Native, \u0447\u0442\u043e \u0431\u044b \u044d\u0442\u043e \u043d\u0438 \u0437\u043d\u0430\u0447\u0438\u043b\u043e<\/s>.\u00a0<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, MinIO \u2013 \u044d\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441: \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c, \u043b\u0435\u0433\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c <s>\u0438 \u0435\u0433\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0431\u044b\u0442\u044c<\/s>. \u041d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0434\u043e\u043b\u0433\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 MinIO \u043c\u043e\u0436\u0435\u0442 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0442\u044c \u0442\u0430\u043a\u0438\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c, \u043a\u0430\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.\u00a0<\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043d\u0430 \u0440\u044b\u043d\u043a\u0435 \u043c\u043d\u043e\u0433\u043e. \u0412\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c, \u0438\u0437 \u0447\u0435\u0433\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c, \u0431\u0443\u0434\u044c \u0442\u043e \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438\u043b\u0438 self-hosted-\u0440\u0435\u0448\u0435\u043d\u0438\u044f.\u00a0 \u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u0434\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e (\u0434\u0430, \u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0440\u043e\u0434\u0430 vendor lock-in, \u043d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439).<\/p>\n<p><strong>Disclaimer: <\/strong>\u043f\u043e\u0434 S3 \u044f \u0431\u0443\u0434\u0443 \u0438\u043c\u0435\u0442\u044c \u0432 \u0432\u0438\u0434\u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e (S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430), \u0430 \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442. \u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u2013 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445.\u00a0<\/p>\n<h2>\u041a\u0435\u0439\u0441 1: \u043f\u0440\u043e\u043a\u0430\u0442 \u0441\u0430\u043c\u043e\u043a\u0430\u0442\u043e\u0432<\/h2>\n<p><a class=\"anchor\" name=\"%D0%BA%D0%B5%D0%B9%D1%81_1\" id=\"\u043a\u0435\u0439\u0441_1\"><\/a><\/p>\n<p>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u0438-\u0432\u043e\u0440\u043a\u0448\u043e\u043f\u0430 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 S3 \u0432 \u043e\u0431\u0449\u0435\u043c \u0438 \u0441 MinIO \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.\u00a0<\/p>\n<p>\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0430\u0448\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c. \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u044b\u0439 \u0441\u043e\u043d \u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u0438, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0451\u0442 \u0432\u0440\u0435\u043c\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u043b\u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.\u00a0<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u043a\u0435\u0439\u0441\u0443. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u0440\u043e\u043a\u0430\u0442\u0430 \u0441\u0430\u043c\u043e\u043a\u0430\u0442\u043e\u0432 \u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c user story, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0440\u0443\u0435\u0442 \u0441\u0430\u043c\u043e\u043a\u0430\u0442 \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435 \u0430\u0440\u0435\u043d\u0434\u044b. \u0425\u0440\u0430\u043d\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0451\u043c \u043d\u0430\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c MinIO \u2013 \u044d\u0442\u043e \u043d\u0430\u0448 \u043b\u044e\u0431\u0438\u043c\u0447\u0438\u043a Docker, \u0441\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439.<\/p>\n<p>\u0421 \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 Docker \u2013 \u043d\u0435 \u0442\u0430\u043a\u0430\u044f \u0443\u0436 \u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0430\u044f \u0448\u0442\u0443\u043a\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\"><u>\u0440\u0435\u043f\u0435<\/u><\/a> \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0435\u0441\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b \u0434\u043b\u044f Podman.\u00a0<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u00ab\u0433\u043e\u043b\u044b\u0439\u00bb \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u2013 \u043d\u044b\u043d\u0447\u0435 \u043c\u043e\u0432\u0435\u0442\u043e\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u043d\u0451\u043c \u0441\u0440\u0430\u0437\u0443 \u0441 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 \u0434\u043b\u044f docker-compose.<\/p>\n<p><a class=\"anchor\" name=\"docker_compose_minio\" id=\"docker_compose_minio\"><\/a><\/p>\n<pre><code class=\"yaml\"># docker-compose.yaml version: '3.7'  services:  minio:    image: minio\/minio:latest    command: server --console-address \":9001\" \/data\/    ports:      - \"9000:9000\"      - \"9001:9001\"    environment:      MINIO_ROOT_USER: ozontech      MINIO_ROOT_PASSWORD: minio123    volumes:      - minio-storage:\/data    healthcheck:      test: [\"CMD\", \"curl\", \"-f\", \"http:\/\/localhost:9000\/minio\/health\/live\"]      interval: 30s      timeout: 20s      retries: 3 volumes:  minio-storage:<\/code><\/pre>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c <code>$ docker-compose up<\/code> \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u043c.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448\u0438\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e web-ui. \u041d\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u0432 CI\/CD), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0432\u0435\u0440\u0445\u0443 \u0435\u0449\u0451 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c <a href=\"https:\/\/github.com\/minio\/mc\"><u>CLI-\u0443\u0442\u0438\u043b\u0438\u0442\u0443<\/u><\/a>: <\/p>\n<p><code>$ go get github.com\/minio\/mc<\/code><\/p>\n<p>\u0418 \u0434\u0430, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e <code>export PATH=$PATH:$(go env GOPATH)\/bin.<\/code><\/p>\n<p>C\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043b\u0438\u0430\u0441 \u0432 mc (\u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0438\u043c\u0441\u044f):<\/p>\n<p>\u2028<code>$ mc alias set minio http:\/\/localhost:9000 ozontech minio123<\/code>\u2028<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c bucket \u2013 \u0440\u0430\u0437\u0434\u0435\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (\u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441 \u043f\u0430\u043f\u043a\u043e\u0439). \u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0440\u0430\u0437\u0434\u0435\u043b, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u041d\u0430\u0437\u043e\u0432\u0435\u043c \u043d\u0430\u0448 \u0431\u0430\u043a\u0435\u0442 \u201cusersPhotos\u201d:<\/p>\n<p><code>$ mc mb minio\/usersPhot<\/code><\/p>\n<p><code><br \/> $ mc ls minio > [0B] usersPhotos<\/code><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0431\u044d\u043a\u0435. \u041f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 Golang. MinIO \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <a href=\"http:\/\/github.com\/minio\/minio-go\"><u>\u043f\u0430\u043a\u0435\u0442\u0438\u043a<\/u><\/a> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0432\u043e\u0438\u043c API.\u00a0<\/p>\n<p><strong><em>Disclaimer:<\/em><\/strong><em> \u043a\u043e\u0434 \u043d\u0438\u0436\u0435 \u2013 \u043b\u0438\u0448\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c; \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0435\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043d\u0430\u0431\u043e\u0440 best practices \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0431\u043e\u0435\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.<\/em><\/p>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443:<\/p>\n<pre><code class=\"go\">func (m *MinioProvider) Connect() error {   var err error   m.client, err = minio.New(m.url, &amp;minio.Options{      Creds:  credentials.NewStaticV4(m.user, m.password, \"\"),      Secure: m.ssl,   })   if err != nil {      log.Fatalln(err)   }    return err }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u043f\u0438\u0448\u0435\u043c \u0440\u0443\u0447\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430:<\/p>\n<pre><code class=\"go\">func (s *Server) uploadPhoto(w http.ResponseWriter, r *http.Request) {   \/\/ \u0423\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043a \u043d\u0430\u043c \u0432 \u0440\u0443\u0447\u043a\u0443 \u0438\u0434\u0443\u0442 \u043d\u0443\u0436\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c   if r.Method != \"POST\" {      w.WriteHeader(http.StatusMethodNotAllowed)      return   }    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c ID \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0440\u0435\u043d\u0434\u044b, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u0442\u044c, \u0432 \u043a\u0430\u043a\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u0442\u043e \u0444\u043e\u0442\u043e   rentID, err := strconv.Atoi(r.Header.Get(HEADER_RENT_ID))   if err != nil {      logrus.Errorf(\"Can`t get rent id: %v\\n\", err)      http.Error(w, \"Wrong request!\", http.StatusBadRequest)      return   }    \/\/ \u0417\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u0444\u043e\u0442\u043e \u0438\u0437 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430   src, hdr, err := r.FormFile(\"photo\")   if err != nil {      http.Error(w, \"Wrong request!\", http.StatusBadRequest)      return   }    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0440\u0435\u043d\u0434\u044b   session, err := s.database.GetRentStatus(rentID)   if err != nil {      logrus.Errorf(\"Can`t get session: %v\\n\", err)      http.Error(w, \"Can`t upload photo!\", http.StatusInternalServerError)      return   }    \/\/ \u0421\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0440\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u043c   \/\/ \u043c\u0435\u0436\u0434\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u043e\u0439   object := models.ImageUnit{      Payload:     src,      PayloadSize: hdr.Size,      User:        session.User,   }   defer src.Close()    \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043e\u0442\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435   img, err := s.storage.UploadFile(r.Context(), object)   if err != nil {      logrus.Errorf(\"Fail update img in image strorage: %v\\n\", err)      http.Error(w, \"Can`t upload photo!\", http.StatusInternalServerError)      return   }    \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0411\u0414 \u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u043e\u0439 \u0444\u043e\u0442\u043e \u043a \u0441\u0435\u0441\u0441\u0438\u0438   err = s.database.AddImageRecord(img, rentID)   if err != nil {      logrus.Errorf(\"Fail update img in database: %v\\n\", err)      http.Error(w, \"Can`t upload photo!\", http.StatusInternalServerError)   } }<\/code><\/pre>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0444\u043e\u0442\u043e:<\/p>\n<pre><code class=\"go\">func (m *MinioProvider) UploadFile(ctx context.Context, object models.ImageUnit) (string, error) {   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u00ab\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435\u00bb \u0438\u043c\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u043e\u0442\u043e   imageName := samokater.GenerateObjectName(object.User)    _, err := m.client.PutObject(      ctx,      UserObjectsBucketName, \/\/ \u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u0431\u0430\u043a\u0435\u0442\u0430      imageName,      object.Payload,      object.PayloadSize,      minio.PutObjectOptions{ContentType: \"image\/png\"},   )    return imageName, err<\/code><\/pre>\n<p>\u041d\u0430\u043c \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u0444\u043e\u0442\u043e \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"go\">func (s *PGS) AddImageRecord(img string, rentID int) error {   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0440\u0435\u043d\u0434\u044b   rent, err := s.GetRentStatus(rentID)   if err != nil {      logrus.Errorf(\"Can`t get rent record in db: %v\\n\", err)      return err   }    \/\/ \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0431\u044b\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0444\u043e\u0442\u043e \u0434\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0440\u0435\u043d\u0434\u044b   \/\/ \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u0435\u0451 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043f\u043e\u043b\u0435 \u0432 \u0411\u0414   if rent.StartedAt.IsZero() {      return s.updateImages(rent.ImagesBefore, img, update_images_before, rentID)   }    return s.updateImages(rent.ImagesAfter, img, update_images_after, rentID) }<\/code><\/pre>\n<p>\u041d\u0443 \u0438 \u0441\u0430\u043c \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414:<\/p>\n<pre><code class=\"go\">func (s *PGS) updateImages(old []string, new, req string, rentID int) error {   \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0442\u0430\u0440\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439   \/\/ \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u043e\u0431 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438   old = append(old, new)   new = strings.Join(old, \",\")    _, err := s.db.Exec(req, new, rentID)   if err != nil {      logrus.Errorf(\"Can`t update image record in db: %v\\n\", err)   }    return err }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0444\u043e\u0442\u043e \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443. \u0412\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u0431\u044b \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:\u00a0<\/p>\n<pre><code class=\"go\">func (s *Server) downloadPhoto(w http.ResponseWriter, r *http.Request) {   if r.Method != \"GET\" {      w.WriteHeader(http.StatusMethodNotAllowed)      return   }    rentID := r.URL.Query()[\"rid\"][0]   if rentID == \"\" {      http.Error(w, \"Can`t get rent-id from request\", http.StatusBadRequest)   }    img, err := s.storage.DownloadFile(r.Context(), rentID)   if err != nil {      logrus.Errorf(\"Cant`t get image from image-storage: %v\\n\", err)      http.Error(w, \"Can`t get image\", http.StatusBadRequest)   }    s.sendImage(w, img.Payload) }<\/code><\/pre>\n<p>\u041d\u0443 \u0438 \u0441\u0430\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430:<\/p>\n<pre><code class=\"go\">func (m *MinioProvider) DownloadFile(ctx context.Context, image string) (models.ImageUnit, error) {   reader, err := m.client.GetObject(      ctx,      UserObjectsBucketName,      image,      minio.GetObjectOptions{},   )   if err != nil {      logrus.Errorf(\"Cant`t get image from image-storage: %v\\n\", err)   }   defer reader.Close()    return models.ImageUnit{}, nil }<\/code><\/pre>\n<p>\u041d\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 MinIO, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u043f\u0440\u0438\u0447\u0438\u043d \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c (\u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0442\u0430\u043a\u0438\u043c\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438\u043b\u0438 \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e). \u0414\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e, \u043e\u0431\u0435\u0440\u043d\u0443\u0432 \u0432\u0441\u0451 \u0432 nginx:<\/p>\n<pre><code class=\"nginx\">server {    listen 8080;    underscores_in_headers on;    proxy_pass_request_headers on;     location \/ {        proxy_pass http:\/\/docker-samokater;    }     location \/samokater {        proxy_pass http:\/\/docker-minio-api;    }  }  server {    listen 9090;     location \/ {        proxy_pass         http:\/\/docker-minio-console;        proxy_redirect     off;    } }<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0440\u0443\u0447\u043a\u0443 rent_info:<\/p>\n<pre><code class=\"go\">func (s *Server) rentInfo(w http.ResponseWriter, r *http.Request) {   if r.Method != \"GET\" {      w.WriteHeader(http.StatusMethodNotAllowed)      return   }    rentID, err := strconv.Atoi(r.Header.Get(HEADER_RENT_ID))   if err != nil {      logrus.Errorf(\"Can`t get rent id: %v\\n\", err)      http.Error(w, \"Wrong request!\", http.StatusBadRequest)      return   }    session, err := s.database.GetRentStatus(rentID)   if err != nil {      logrus.Errorf(\"Can`t get session: %v\\n\", err)      http.Error(w, \"Can`t rent info!\", http.StatusInternalServerError)      return   }    \/\/ \u041e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u044f \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f   session = enrichImagesLinks(session)    s.sendModel(w, session) }<\/code><\/pre>\n<p>\u0418 \u0441\u0430\u043c \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u044f: <\/p>\n<pre><code class=\"go\">func enrichImagesLinks(session models.Rent) models.Rent {   for i, image := range session.ImagesBefore {      session.ImagesBefore[i] = fmt.Sprintf(\"%s\/%s\", ImageStorageSVCDSN, image)   }    for i, image := range session.ImagesAfter {      session.ImagesAfter[i] = fmt.Sprintf(\"%s\/%s\", ImageStorageSVCDSN, image)   }    return session }<\/code><\/pre>\n<p>\u0423\u043f\u0430\u043a\u0443\u0435\u043c \u0432\u0441\u0451 \u0432 docker-compose.yaml:<\/p>\n<p><a class=\"anchor\" name=\"%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0\" id=\"\u0437\u0430\u043f\u0443\u0441\u043a_\u0441\u0435\u0440\u0432\u0438\u0441\u0430\"><\/a><\/p>\n<details class=\"spoiler\">\n<summary>docker-compose.yaml <\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">version: '3.7'  services:  minio:    image: minio\/minio:latest    container_name: minio    restart: unless-stopped    command: server --console-address \":9001\" \/data\/    ports:      - \"9000:9000\"      - \"9001:9001\"    environment:      MINIO_ROOT_USER: ozontech      MINIO_ROOT_PASSWORD: minio123    volumes:      - minio-storage:\/data    healthcheck:      test: [\"CMD\", \"curl\", \"-f\", \"http:\/\/localhost:9000\/minio\/health\/live\"]      interval: 30s      timeout: 20s      retries: 3    networks:      - app-network   samokater:    image: samokater:latest    container_name: samokater    build:      context: .\/      dockerfile: samokater.Dockerfile    restart: unless-stopped    ports:      - 8080:8080    networks:      - app-network    environment:      SERVERPORT: :8080      DBPATH: user=postgres password=devpass dbname=postgres host=db port=5432 sslmode=disable      MINIOHOST: minio:9000      MINIOUSER: ozontech      MINIOPASS: minio123    depends_on:      - db      - minio   initDB:    image: mingration:latest    container_name: init    environment:      DBPATH: user=postgres password=devpass dbname=postgres host=db port=5432 sslmode=disable    build:      context: .\/      dockerfile: mingration.Dockerfile    networks:      - app-network    depends_on:      - db   db:    container_name: db    image: postgres    restart: always    environment:      POSTGRES_PASSWORD: devpass    volumes:      - pg-storage:\/var\/lib\/postgresql\/data    ports:      - 5432:5432    networks:      - app-network   nginx:    image: nginx-custom:latest    build:      context: .\/      dockerfile: nginx.Dockerfile    restart: unless-stopped    tty: true    container_name: nginx    volumes:      - .\/nginx.conf:\/etc\/nginx\/nginx.conf    ports:      - 8000:80      - 443:443    networks:      - app-network    depends_on:      - samokater  networks:  app-network:    driver: bridge  volumes:  minio-storage:  pg-storage:<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\"># \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0435\u0441\u0441\u0438\u044e \u0430\u0440\u0435\u043d\u0434\u044b $ curl -i -X POST --header 'user_id:100' http:\/\/localhost:8080\/api\/v1\/rent HTTP\/1.1 200 OK  {\"ID\":100,\"Name\":\"\",\"RentID\":8674665223082153551}  # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0443 \u0444\u043e\u0442\u043e \u0434\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0440\u0435\u043d\u0434\u044b $ curl -i  -X POST --header 'rent_id:8674665223082153551' --form photo=@\/Users\/ktikhomirov\/image_1.png  http:\/\/localhost:8080\/api\/v1\/upload_photo --insecure HTTP\/1.1 200 OK  # \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441\u0435\u0441\u0441\u0438\u044e \u0430\u0440\u0435\u043d\u0434\u044b $ curl -i -X POST  http:\/\/localhost:8080\/api\/v1\/rent_start  -H  \"Content-Type: application\/json\" -d '{\"ID\":100,\"RentID\":8674665223082153551}' HTTP\/1.1 200 OK  # \u0417\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u043c \u0441\u0435\u0441\u0441\u0438\u044e \u0430\u0440\u0435\u043d\u0434\u044b $ curl -i -X POST  http:\/\/localhost:8080\/api\/v1\/rent_stop  -H  \"Content-Type: application\/json\" -d '{\"ID\":100,\"RentID\":8674665223082153551}' HTTP\/1.1 200 OK  # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043e\u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0430\u0440\u0435\u043d\u0434\u044b $ curl -i  -X POST --header 'rent_id:8674665223082153551' --form photo=@\/Users\/ktikhomirov\/image_2.png http:\/\/localhost:8080\/api\/v1\/upload_photo --insecure  # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0440\u0435\u043d\u0434\u0435 curl -i -X GET -H \"rent_id:8674665223082153551\"  http:\/\/localhost:8080\/api\/v1\/rent_info HTTP\/1.1 200 OK  {\"ID\":100,\"Name\":\"\",\"StartedAt\":\"2021-10-21T08:10:31.536028Z\",\"CompletedAt\":\"2021-10-21T08:19:33.672493Z\",\"ImagesBefore\":[\"http:\/\/127.0.0.1:8080\/samokater\/100\/2021-10-21T15:15:24.png\",\"http:\/\/127.0.0.1:8080\/samokater\/100\/2021-10-21T08:06:15.png\"],\"ImagesAfter\":[\"http:\/\/127.0.0.1:8080\/samokater\/100\/2021-10-21T08:21:06.png\"],\"RentID\":8674665223082153551} <\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/80b\/7cc\/69a\/80b7cc69a1849d2f71149749057cb3ec.png\" alt=\"\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043f\u043e URL \u043e\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\" title=\"\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043f\u043e URL \u043e\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\" width=\"1100\" height=\"1218\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/80b\/7cc\/69a\/80b7cc69a1849d2f71149749057cb3ec.png\"\/><figcaption>\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043f\u043e URL \u043e\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d4b\/d29\/8d0\/d4bd298d04a38cc696ecda91fd279f2e.png\" width=\"1488\" height=\"698\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d4b\/d29\/8d0\/d4bd298d04a38cc696ecda91fd279f2e.png\"\/><figcaption><\/figcaption><\/figure>\n<h2>\u041a\u0435\u0439\u0441 2: \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u0444\u0440\u043e\u043d\u0442\u0430<\/h2>\n<p><a class=\"anchor\" name=\"%D0%BA%D0%B5%D0%B9%D1%81_2\" id=\"\u043a\u0435\u0439\u0441_2\"><\/a><\/p>\n<p>\u0415\u0449\u0451 \u043e\u0434\u043d\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430, \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430,\u00a0\u2013 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u0440\u0430\u0437\u0434\u0430\u0447\u0430 \u0444\u0440\u043e\u043d\u0442\u0430.  \u041e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430\u043c \u0442\u0443\u0442, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c  \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0444\u0440\u043e\u043d\u0442\u0430 \u0438\u043b\u0438 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0438\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c. \u042d\u0442\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e,  \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c.<\/p>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f  \u043f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f. \u041e\u0434\u043d\u0430\u0436\u0434\u044b \u044f \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u043b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0443 \u0432  \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0433\u0434\u0435 \u0432 \u043c\u0435\u0441\u044f\u0446 \u0440\u0435\u043b\u0438\u0437\u0438\u043b\u0438 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u0435\u043d\u0434\u0438\u043d\u0433\u043e\u0432. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043e\u043d\u0438  \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Vue.js, \u0438\u0437\u0440\u0435\u0434\u043a\u0430 \u043f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u043b\u0441\u044f API \u043d\u0430 \u043f\u0430\u0440\u0443 \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0445 \u0440\u0443\u0447\u0435\u043a. \u041d\u043e \u043c\u043e\u0451  \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u043b\u043e \u0442\u043e, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0434\u0435\u043f\u043b\u043e\u0438\u043b\u043e\u0441\u044c: \u0442\u0430\u043c \u0446\u0430\u0440\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438  \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0441 nginx, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043b\u0435\u0436\u0430\u043b\u0430 \u0441\u0442\u0430\u0442\u0438\u043a\u0430, \u0430 \u043d\u0430\u0434 \u0432\u0441\u0435\u043c \u044d\u0442\u0438\u043c \u0441\u0442\u043e\u044f\u043b  \u0445\u043e\u0441\u0442\u043e\u0432\u044b\u0439 nginx, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b \u0440\u043e\u043b\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041a\u0430\u043a \u0442\u0435\u0431\u0435  \u0442\u0430\u043a\u043e\u0439 cloud-native-\u043f\u043e\u0434\u0445\u043e\u0434, \u0418\u043b\u043e\u043d? \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u044d\u0442\u0438\u043c \u043c\u043e\u043d\u0441\u0442\u0440\u043e\u043c \u043c\u043d\u043e\u0439 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043e\u00a0\u043e\u0431\u043c\u0430\u0437\u0430\u0442\u044c\u0441\u044f  \u043a\u0443\u0431\u0430\u043c\u0438, \u0441\u0442\u0430\u0442\u0438\u043a\u0443 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 MinIO, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043b\u0435\u043d\u0434\u0438\u043d\u0433\u0430  \u0441\u0432\u043e\u0439 \u0431\u0430\u043a\u0435\u0442, \u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Ingress \u0443\u0436\u0435 \u0432\u0441\u0451 \u044d\u0442\u043e \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0440\u0443\u0436\u0443. \u041d\u043e, \u043a\u0430\u043a  \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043f\u043b\u043e\u0445\u043e\u043c, \u0430 \u043b\u0443\u0447\u0448\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c! <\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c,  \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u043c\u0438 \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0445\u043e\u0436\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0438 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c Kubernetes.  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0443\u0434\u0430 \u0440\u0430\u0441\u043a\u0430\u0442\u0430\u0435\u043c MinIO Operator. \u0421\u0442\u043e\u043f, \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u043e\u0441\u0442\u043e  \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c MinIO \u0432 \u043f\u043e\u0434\u0435 \u0438 \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0442\u0443\u0434\u0430 \u043f\u043e\u0440\u0442\u044b? \u0410\u00a0\u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e MinIO-Operator \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u044d\u0442\u043e \u0437\u0430 \u043d\u0430\u0441, \u0430 \u0437\u0430\u043e\u0434\u043d\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442 High Availability-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e\u00a0\u043d\u0430\u043c \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043d\u0430\u0434\u043e <s>\u0442\u0440\u0438 \u0441\u0442\u043e\u043b\u043e\u0432\u044b\u0435 \u043b\u043e\u0436\u043a\u0438\u00a0\u0441\u043e\u0434\u044b&#8230;<\/s>\u00a0\u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 <a href=\"https:\/\/www.google.com\/url?q=https:\/\/docs.min.io\/minio\/baremetal\/&amp;sa=D&amp;source=editors&amp;ust=1635344630066000&amp;usg=AOvVaw1hiSRyIX51O88IPWM6frjA\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439<\/a>.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043c\u044b \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u043c\u0441\u044f \u0441\u043c\u0443\u0437\u0438\u00a0<a href=\"https:\/\/www.google.com\/url?q=https:\/\/github.com\/kubernetes-sigs\/krew&amp;sa=D&amp;source=editors&amp;ust=1635344630066000&amp;usg=AOvVaw3-9gG5neKjfA4TsJG6XvwE\">Krew<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0451 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441:<\/p>\n<p><code>$ kubectl krew update <\/code><\/p>\n<p><code>$ kubectl krew install minio <\/code><\/p>\n<p><code>$ kubectl minio init<\/code><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c tenant. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0432 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0427\u0442\u043e\u0431\u044b \u0442\u0443\u0434\u0430 \u043f\u043e\u043f\u0430\u0441\u0442\u044c, \u043f\u0440\u043e\u043a\u0438\u043d\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438: <br \/><code>$ kubectl minio proxy -n minio-operator<\/code><\/p>\n<p>\u041f\u043e\u0441\u043b\u0435\u00a0\u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0440\u0442\u043e\u0432 \u0434\u043e \u043d\u0430\u0448\u0435\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 \u0432\u044b\u0432\u043e\u0434\u00a0\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 JWT-\u0442\u043e\u043a\u0435\u043d, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0438 \u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0438\u043c\u0441\u044f \u0432 \u043d\u0430\u0448\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f: <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9a5\/381\/be0\/9a5381be032f74f1b0246129c0ade6eb.png\" alt=\"\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043d\u0430\u043d\u0442\u0430\u043c\u0438\" title=\"\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043d\u0430\u043d\u0442\u0430\u043c\u0438\" width=\"1600\" height=\"1207\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9a5\/381\/be0\/9a5381be032f74f1b0246129c0ade6eb.png\"\/><figcaption>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043d\u0430\u043d\u0442\u0430\u043c\u0438<\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u043d\u0430\u043d\u0442\u00bb \u0438 \u0437\u0430\u0434\u0430\u0451\u043c \u0435\u043c\u0443 \u0438\u043c\u044f \u0438 \u043d\u0435\u0439\u043c\u0441\u043f\u0435\u0439\u0441: <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/25c\/985\/4b0\/25c9854b00021750d16919b20e2ee94d.png\" alt=\"\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0435\u043d\u0430\u043d\u0442\u0430\" title=\"\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0435\u043d\u0430\u043d\u0442\u0430\" width=\"1402\" height=\"1368\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/25c\/985\/4b0\/25c9854b00021750d16919b20e2ee94d.png\"\/><figcaption>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0435\u043d\u0430\u043d\u0442\u0430<\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u043e\u0437\u0434\u0430\u0442\u044c\u00bb \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043a\u0440\u0435\u0434\u0435\u043d\u0448\u0438\u0430\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c <a href=\"https:\/\/www.google.com\/url?q=https:\/\/www.vaultproject.io\/&amp;sa=D&amp;source=editors&amp;ust=1635344630070000&amp;usg=AOvVaw3IOpCcxiobocyk0r_KOZCV\">Vault<\/a>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/201\/cc8\/c4d\/201cc8c4d66f35417e1e2304ae531e6f.png\" alt=\"\" title=\"\" width=\"1308\" height=\"528\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/201\/cc8\/c4d\/201cc8c4d66f35417e1e2304ae531e6f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0430\u043d\u0435\u043b\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449, \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438 \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 minio-svc \u0438 \u0435\u0433\u043e \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\"># \u041f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438 \u043a \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0443 minio-svc kubectl -n minio-operator  port-forward service\/minio-svc-console 9090:9090  # \u041f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438 \u043a API minio-svc kubectl -n minio-operator  port-forward service\/minio-svc-hl 9000:9000<\/code><\/pre>\n<p>\u0418 \u0432\u0443\u0430\u043b\u044f! \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u044b\u0441\u043e\u043a\u043e\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 MinIO. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043c \u0435\u0433\u043e \u043a \u043d\u0430\u0448\u0435\u043c\u0443 GitLab CI \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c .gitlab_ci, \u0447\u0442\u043e\u0431\u044b \u0432 \u043f\u0430\u0440\u0443 \u043a\u043b\u0438\u043a\u043e\u0432 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0444\u0440\u043e\u043d\u0442.<\/p>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f CI\/CD \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 GitLab CI (\u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u043b\u0435\u0436\u0438\u0442 \u0432 \u0440\u0435\u043f\u0435):<\/p>\n<p><a class=\"anchor\" name=\"gitlab_job\" id=\"gitlab_job\"><\/a><\/p>\n<pre><code class=\"yaml\"># gitlab-ci  deploy-front:  stage: deploy  image: minio\/mc  script:   # \u041b\u043e\u0433\u0438\u043d\u0438\u043c\u0441\u044f \u0432 MinIO   - mc config host add --insecure deploy $CI_OBJECT_STORAGE $CI_OBJECT_STORAGE_USER $CI_OBJECT_STORAGE_PASSWORD   # \u0418 \u0432\u0441\u0451 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0440\u0430\u043d\u0435\u0435 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u0432 \u043d\u0430\u0448 \u0431\u0430\u043a\u0435\u0442   - mc cp dist\/* deploy\/static --insecure -c -r  dependencies:    - build-front<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u043a\u0443, \u0434\u043e\u0431\u0430\u0432\u0438\u043c Ingress-\u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442:<\/p>\n<p><a class=\"anchor\" name=\"static.yaml\" id=\"static.yaml\"><\/a><\/p>\n<pre><code class=\"yaml\"># static.yaml --- apiVersion: networking.k8s.io\/v1beta1 kind: Ingress metadata:  name: example-static  labels:    app.kubernetes.io\/name: example-static    app.kubernetes.io\/version: \"latest\"  annotations:    cert-manager.io\/cluster-issuer: letsencrypt-worker    kubernetes.io\/ingress.class: nginx    kubernetes.io\/tls-acme: \"true\"    nginx.ingress.kubernetes.io\/proxy-body-size: 100m    nginx.ingress.kubernetes.io\/secure-backends: \"true\"    nginx.ingress.kubernetes.io\/ssl-redirect: \"true\"    nginx.ingress.kubernetes.io\/backend-protocol: \"HTTPS\"    nginx.ingress.kubernetes.io\/rewrite-target: \/$1 spec:  tls:    - hosts:        - \"domain.ru\"      secretName: ssl-letsencrypt-example  rules:    - host: \"domain.ru\"      http:        paths:          - backend:              serviceName: minio-svc              servicePort: 9000            path: \/(.+)            pathType: Prefix<\/code><\/pre>\n<p>\u0410 \u0435\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043d\u0435\u0439\u043c\u0441\u043f\u0435\u0439\u0441\u043e\u0432, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441 ExternalName:<\/p>\n<p><a class=\"anchor\" name=\"external_name\" id=\"external_name\"><\/a><\/p>\n<pre><code class=\"yaml\">--- apiVersion: v1 kind: Service metadata:  name: minio-svc  namespace: deploy spec:  ports:    - port: 9000      protocol: TCP      targetPort: 9000  sessionAffinity: None  type: ExternalName<\/code><\/pre>\n<h2>\u0412\u043c\u0435\u0441\u0442\u043e \u0432\u044b\u0432\u043e\u0434\u0430<\/h2>\n<p><a class=\"anchor\" name=\"%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4\" id=\"\u0432\u044b\u0432\u043e\u0434\"><\/a><\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u00a0\u2013 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u044b\u0441\u043e\u043a\u043e\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430 cloud-native \u044d\u0442\u043e \u043d\u0435\u0437\u0430\u043c\u0435\u043d\u0438\u043c\u044b\u0439 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u043c\u043d\u043e\u0433\u0438\u0445 \u0437\u0430\u0434\u0430\u0447. \u0414\u0430, \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435\u00a0\u043c\u043e\u0433\u0443\u0442  \u0441\u043b\u0443\u0447\u0430\u0442\u044c\u0441\u044f \u043a\u0435\u0439\u0441\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445  \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u043c, \u043d\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u043e\u0432\u043e\u0434\u043e\u043c \u0441\u043e\u0432\u0441\u0435\u043c  \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. <\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u044f \u0431\u044b \u043f\u043e\u0441\u043e\u0432\u0435\u0442\u043e\u0432\u0430\u043b\u00a0\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c  \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0435\u0441\u044c \u043c\u0430\u0448\u0438\u043d\u043d\u044b\u043c  \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0438\u043b\u0438 BigData \u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e  \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0438\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u0435 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 MinIO \u2013 \u044d\u0442\u043e \u043d\u0435 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u043e\u0439\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <a href=\"https:\/\/www.google.com\/url?q=https:\/\/github.com\/ceph\/ceph&amp;sa=D&amp;source=editors&amp;ust=1635344630080000&amp;usg=AOvVaw0P6W-Kt1JTMKHem52kKtrt\">Ceph<\/a>\u00a0\u0438 <a href=\"https:\/\/www.google.com\/url?q=https:\/\/github.com\/basho\/riak&amp;sa=D&amp;source=editors&amp;ust=1635344630080000&amp;usg=AOvVaw0TK0CwuBpjEx2iUxDFqkJO\">Riak CS<\/a>\u00a0\u0438\u00a0\u0434\u0430\u0436\u0435 S3 \u043e\u0442 Amazon. \u0423 \u0432\u0441\u0435\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u043c\u0438\u043d\u0443\u0441\u044b.\u00a0<\/p>\n<p>\u0416\u0435\u043b\u0430\u044e \u0432\u0430\u043c \u0443\u0441\u043f\u0435\u0445\u043e\u0432 \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c! <\/p>\n<p>\u0414\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043e \u0432\u0430\u0448\u0435\u043c \u043e\u043f\u044b\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u043c\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u043c\u0438 \u0438 \u0437\u0430\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u043e\u043f\u0440\u043e\u044b!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/586024\/\"> https:\/\/habr.com\/ru\/articles\/586024\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0448\u0430 \u0431\u0438\u0433 \u0434\u0430\u0442\u0430 \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0430 Telegram-\u0447\u0430\u0442\u044b, \u0444\u043e\u0440\u0443\u043c\u044b \u0438 \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440\u044b \u0432 \u043a\u0443\u043b\u0443\u0430\u0440\u0430\u0445 IT-\u043c\u0435\u0440\u043e\u043f\u0440\u0438\u044f\u0442\u0438\u0439 \u0438 \u043f\u043e\u043c\u0435\u0442\u0438\u043b\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043a\u0430\u043a \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0451 \u043d\u0435 \u0432\u0441\u0435 \u043e\u0441\u043c\u0435\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u0425\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0441\u0442\u0430\u0442\u044c\u0438-\u0432\u043e\u0440\u043a\u0448\u043e\u043f\u0430. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u044d\u0442\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 \u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438 \u0435\u0451 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.\u00a0<\/p>\n<p>\u0417\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432?<\/p>\n<p>\u0421 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0445 \u043f\u043e\u0440 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e Golang-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0432 Ozon. \u0423 \u043d\u0430\u0441 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0435\u0441\u0442\u044c \u043a\u0440\u0443\u0442\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0430\u0434\u043c\u0438\u043d\u043e\u0432 \u0438 \u0440\u0435\u043b\u0438\u0437-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0430 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 CI \u0432\u043e\u043a\u0440\u0443\u0433 \u043d\u0435\u0451. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u044f \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u044e\u0441\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c.\u00a0<\/p>\n<p>\u041d\u043e \u0434\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0430 \u0432 Ozon \u044f \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c\u0438 \u043a\u0435\u0439\u0441\u0430\u043c\u0438, \u043a\u043e\u0433\u0434\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439) \u0431\u044b\u043b\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u0438\u0437\u044f\u0449\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u041c\u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043b\u0438\u0441\u044c SFTP, Google Drive \u0438 \u0434\u0430\u0436\u0435 \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 PVC \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440!\u00a0<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u044d\u0442\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0441\u043e\u043f\u0440\u044f\u0436\u0435\u043d\u043e \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u042d\u0442\u043e \u0438 \u043f\u0440\u0438\u0432\u0435\u043b\u043e \u043c\u0435\u043d\u044f \u043a \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0443 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u043c\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u043c\u0438, \u0432\u0435\u0434\u044c \u0441 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0435\u0448\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0439 \u0440\u044f\u0434 \u0437\u0430\u0434\u0430\u0447.\u00a0<\/p>\n<h2>TL;DR<\/h2>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u2013 \u044d\u0442\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u043d\u0430\u0434 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0438 \u0445\u043e\u0441\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 (\u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f, \u0445\u0440\u0430\u043d\u0438\u0442\u044c) \u0447\u0435\u0440\u0435\u0437 API.<\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0432\u0430\u043c \u0432 \u043a\u0435\u0439\u0441\u0430\u0445, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\/-\/tree\/main\/server\"><u>\u0444\u0430\u0439\u043b\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0432\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445<\/u><\/a>, <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\/-\/blob\/main\/manifestos\/gitlab-ci.yml\"><u>\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u043a\u0443<\/u><\/a> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\/-\/blob\/main\/manifestos\/ingress-static.yaml\"><u>Ingress<\/u><\/a> \u0438\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c <a href=\"https:\/\/docs.gitlab.com\/runner\/configuration\/speed_up_job_execution.html#use-minio\"><u>\u043a\u0435\u0448\u0438 \u0432\u0430\u0448\u0435\u0433\u043e CI<\/u><\/a>.\u00a0<\/p>\n<p>\u0412\u0441\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u043a \u0441\u0442\u0430\u0442\u044c\u0435 (\u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438, \u043a\u043e\u043d\u0444\u0438\u0433\u0438, \u0441\u043a\u0440\u0438\u043f\u0442\u044b) \u043b\u0435\u0436\u0430\u0442 \u0432\u043e\u0442 \u0432 \u044d\u0442\u043e\u0439 <a href=\"http:\/\/gitlab.com\/worldbug\/storage-examples\"><u>\u0440\u0435\u043f\u0435<\/u><\/a>.\u00a0<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/h3>\n<p><a class=\"anchor\" name=\"%D1%87%D1%82%D0%BE_%D1%82%D0%B0%D0%BA%D0%BE%D0%B5_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B\" id=\"\u0447\u0442\u043e_\u0442\u0430\u043a\u043e\u0435_\u043e\u0431\u044a\u0435\u043a\u0442\u044b\">\u043e\u0431\u044a\u0435\u043a\u0442\u044b&#187;<\/a><\/p>\n<p>\u0425\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438, \u043e\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u0434\u043e \u0431\u043b\u043e\u0431\u0430 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0411\u0414 (\u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u044d\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442, \u043a\u043e\u043d\u0435\u0447\u043d\u043e). \u041d\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c?  \u0427\u0430\u0441\u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c: \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c, \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438, \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c. \u0422\u0443\u0442 \u0443\u0436\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u0411\u0414 \u0438\u043b\u0438 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c. \u0412 \u044d\u0442\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0445\u043e\u0441\u0442\u0430, \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439. <\/p>\n<p>\u0418 \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0442\u0435 \u0441\u0430\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0438 \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c. \u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u2013 \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0433\u0438\u0431\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043a \u043d\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u0430\u043a \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c (\u0444\u0430\u0439\u043b\u0430\u043c). \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u2013 \u044d\u0442\u043e \u0444\u0430\u0439\u043b \u0438 \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043d\u0451\u043c.\u00a0<\/p>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0435\u0449\u0451 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c, \u0447\u0442\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u0445 \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u044f\u0442\u0438\u044f, \u043a\u0430\u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432. \u0412\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u00ab\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435\u00bb \u2013 bucket. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a: <code>objectScope\/firstObject.dat<\/code> .<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445 \u2013 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043e\u0442 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0435\u0442\u0430\u043b\u0435\u0439. \u041d\u0430\u0441 \u0443\u0436\u0435 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442, \u043a\u0430\u043a\u0430\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f (\u0438\u043b\u0438 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f) \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0440\u0430\u043d\u0438\u0442 \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435. \u041c\u044b \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u043a\u0430\u043a\u0438\u043c\u0438-\u0442\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u0438\u0445 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430.\u00a0<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0442\u0438\u043f\u044b \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449, \u0430 \u043e\u0431\u0440\u0430\u0442\u0438\u043c \u043d\u0430\u0448\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u0441\u0442\u043e\u0440\u0430\u0434\u0436\u0435\u0439, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 MinIO. \u0412\u044b\u0431\u043e\u0440 \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d \u0442\u0435\u043c, \u0447\u0442\u043e MinIO \u0438\u043c\u0435\u0435\u0442 \u043d\u0438\u0437\u043a\u0438\u0439 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 (\u043f\u0440\u0438\u0432\u0435\u0442, Ceph), <s>\u0430 \u0435\u0449\u0451 \u043e\u043d\u043e Kubernetes Native, \u0447\u0442\u043e \u0431\u044b \u044d\u0442\u043e \u043d\u0438 \u0437\u043d\u0430\u0447\u0438\u043b\u043e<\/s>.\u00a0<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, MinIO \u2013 \u044d\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441: \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c, \u043b\u0435\u0433\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c <s>\u0438 \u0435\u0433\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0431\u044b\u0442\u044c<\/s>. \u041d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0434\u043e\u043b\u0433\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 MinIO \u043c\u043e\u0436\u0435\u0442 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0442\u044c \u0442\u0430\u043a\u0438\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c, \u043a\u0430\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.\u00a0<\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435 S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043d\u0430 \u0440\u044b\u043d\u043a\u0435 \u043c\u043d\u043e\u0433\u043e. \u0412\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c, \u0438\u0437 \u0447\u0435\u0433\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c, \u0431\u0443\u0434\u044c \u0442\u043e \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438\u043b\u0438 self-hosted-\u0440\u0435\u0448\u0435\u043d\u0438\u044f.\u00a0 \u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u0434\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e (\u0434\u0430, \u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0440\u043e\u0434\u0430 vendor lock-in, \u043d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439).<\/p>\n<p><strong>Disclaimer: <\/strong>\u043f\u043e\u0434 S3 \u044f \u0431\u0443\u0434\u0443 \u0438\u043c\u0435\u0442\u044c \u0432 \u0432\u0438\u0434\u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e (S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430), \u0430 \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442. \u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u2013 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445.\u00a0<\/p>\n<h2>\u041a\u0435\u0439\u0441 1: \u043f\u0440\u043e\u043a\u0430\u0442 \u0441\u0430\u043c\u043e\u043a\u0430\u0442\u043e\u0432<\/h2>\n<p><a class=\"anchor\" name=\"%D0%BA%D0%B5%D0%B9%D1%81_1\" id=\"\u043a\u0435\u0439\u0441_1\">_1&#8243;><\/a><\/p>\n<p>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u0438-\u0432\u043e\u0440\u043a\u0448\u043e\u043f\u0430 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 S3 \u0432 \u043e\u0431\u0449\u0435\u043c \u0438 \u0441 MinIO \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.\u00a0<\/p>\n<p>\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0430\u0448\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c. \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u044b\u0439 \u0441\u043e\u043d \u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u0438, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0451\u0442 \u0432\u0440\u0435\u043c\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u043b\u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.\u00a0<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u043a\u0435\u0439\u0441\u0443. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u0440\u043e\u043a\u0430\u0442\u0430 \u0441\u0430\u043c\u043e\u043a\u0430\u0442\u043e\u0432 \u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c user story, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0440\u0443\u0435\u0442 \u0441\u0430\u043c\u043e\u043a\u0430\u0442 \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435 \u0430\u0440\u0435\u043d\u0434\u044b. \u0425\u0440\u0430\u043d\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0451\u043c \u043d\u0430\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c MinIO \u2013 \u044d\u0442\u043e \u043d\u0430\u0448 \u043b\u044e\u0431\u0438\u043c\u0447\u0438\u043a Docker, \u0441\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439.<\/p>\n<p>\u0421 \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 Docker \u2013 \u043d\u0435 \u0442\u0430\u043a\u0430\u044f \u0443\u0436 \u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0430\u044f \u0448\u0442\u0443\u043a\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 <a href=\"https:\/\/gitlab.com\/worldbug\/storage-examples\"><u>\u0440\u0435\u043f\u0435<\/u><\/a> \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0435\u0441\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u044b \u0434\u043b\u044f Podman.\u00a0<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u00ab\u0433\u043e\u043b\u044b\u0439\u00bb \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u2013 \u043d\u044b\u043d\u0447\u0435 \u043c\u043e\u0432\u0435\u0442\u043e\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u043d\u0451\u043c \u0441\u0440\u0430\u0437\u0443 \u0441 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 \u0434\u043b\u044f docker-compose.<\/p>\n<p><a class=\"anchor\" name=\"docker_compose_minio\" id=\"docker_compose_minio\"><\/a><\/p>\n<pre><code class=\"yaml\"># docker-compose.yaml version: '3.7'  services:  minio:    image: minio\/minio:latest    command: server --console-address \":9001\" \/data\/    ports:      - \"9000:9000\"      - \"9001:9001\"    environment:      MINIO_ROOT_USER: ozontech      MINIO_ROOT_PASSWORD: minio123    volumes:      - minio-storage:\/data    healthcheck:      test: [\"CMD\", \"curl\", \"-f\", \"http:\/\/localhost:9000\/minio\/health\/live\"]      interval: 30s      timeout: 20s      retries: 3 volumes:  minio-storage:<\/code><\/pre>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c <code>$ docker-compose up<\/code> \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u043c.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448\u0438\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e web-ui. \u041d\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u0432 CI\/CD), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0432\u0435\u0440\u0445\u0443 \u0435\u0449\u0451 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c <a href=\"https:\/\/github.com\/minio\/mc\"><u>CLI-\u0443\u0442\u0438\u043b\u0438\u0442\u0443<\/u><\/a>: <\/p>\n<p><code>$ go get github.com\/minio\/mc<\/code><\/p>\n<p>\u0418 \u0434\u0430, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e <code>export PATH=$PATH:$(go env GOPATH)\/bin.<\/code><\/p>\n<p>C\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043b\u0438\u0430\u0441 \u0432 mc (\u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0438\u043c\u0441\u044f):<\/p>\n<p>\u2028<code>$ mc alias set minio http:\/\/localhost:9000 ozontech minio123<\/code>\u2028<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c bucket \u2013 \u0440\u0430\u0437\u0434\u0435\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (\u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441 \u043f\u0430\u043f\u043a\u043e\u0439). \u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0440\u0430\u0437\u0434\u0435\u043b, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u041d\u0430\u0437\u043e\u0432\u0435\u043c \u043d\u0430\u0448 \u0431\u0430\u043a\u0435\u0442 \u201cusersPhotos\u201d:<\/p>\n<p><code>$ mc mb minio\/usersPhot<\/code><\/p>\n<p><code><br \/> $ mc ls minio > [0B] usersPhotos<\/code><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0431\u044d\u043a\u0435. \u041f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 Golang. MinIO \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <a href=\"http:\/\/github.com\/minio\/minio-go\"><u>\u043f\u0430\u043a\u0435\u0442\u0438\u043a<\/u><\/a> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0432\u043e\u0438\u043c API.\u00a0<\/p>\n<p><strong><em>Disclaimer:<\/em><\/strong><em> \u043a\u043e\u0434 \u043d\u0438\u0436\u0435 \u2013 \u043b\u0438\u0448\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c; \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0435\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043d\u0430\u0431\u043e\u0440 best practices \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0431\u043e\u0435\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.<\/em><\/p>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443:<\/p>\n<pre><code class=\"go\">func (m *MinioProvider) Connect() error {   var err error   m.client, err = minio.New(m.url, &amp;minio.Options{      Creds:  credentials.NewStaticV4(m.user, m.password, \"\"),      Secure: m.ssl,   })   if err != nil {      log.Fatalln(err)   }    return err }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u043f\u0438\u0448\u0435\u043c \u0440\u0443\u0447\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430:<\/p>\n<pre><code class=\"go\">func (s *Server) uploadPhoto(w http.ResponseWriter, r *http.Request) {   \/\/ \u0423\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043a \u043d\u0430\u043c \u0432 \u0440\u0443\u0447\u043a\u0443 \u0438\u0434\u0443\u0442 \u043d\u0443\u0436\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c   if r.Method != \"POST\" {      w.WriteHeader(http.StatusMethodNotAllowed)      return   }    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c ID \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0440\u0435\u043d\u0434\u044b, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u0442\u044c, \u0432 \u043a\u0430\u043a\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u0442\u043e \u0444\u043e\u0442\u043e   rentID, err := strconv.Atoi(r.Header.Get(HEADER_RENT_ID))   if err != nil {      logrus.Errorf(\"Can`t get rent id: %v\\n\", err)      http.Error(w, \"Wrong request!\", http.StatusBadRequest)      return   }    \/\/ \u0417\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u0444\u043e\u0442\u043e \u0438\u0437 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430   src, hdr, err := r.FormFile(\"photo\")   if err != nil {      http.Error(w, \"Wrong request!\", http.StatusBadRequest)      return   }    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0440\u0435\u043d\u0434\u044b   session, err := s.database.GetRentStatus(rentID)   if err != nil {      logrus.Errorf(\"Can`t get session: %v\\n\", err)      http.Error(w, \"Can`t upload photo!\", http.StatusInternalServerError)      return   }    \/\/ \u0421\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0440\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u043c   \/\/ \u043c\u0435\u0436\u0434\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u043e\u0439   object := models.ImageUnit{      Payload:     src,      PayloadSize: hdr.Size,      User:        session.User,   }   defer src.Close()    \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043e\u0442\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435   img, err := s.storage.UploadFile(r.Context(), object)   if err != nil {      logrus.Errorf(\"Fail update img in image strorage: %v\\n\", err)      http.Error(w, \"Can`t upload photo!\", http.StatusInternalServerError)      return   }    \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0411\u0414 \u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u043e\u0439 \u0444\u043e\u0442\u043e \u043a \u0441\u0435\u0441\u0441\u0438\u0438   err = s.database.AddImageRecord(img, rentID)   if err != nil {      logrus.Errorf(\"Fail update img in database: %v\\n\", err)      http.Error(w, \"Can`t upload photo!\", http.StatusInternalServerError)   } }<\/code><\/pre>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0444\u043e\u0442\u043e:<\/p>\n<pre><code class=\"go\">func (m *MinioProvider) UploadFile(ctx context.Context, object models.ImageUnit) (string, error) {   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u00ab\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435\u00bb \u0438\u043c\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u043e\u0442\u043e   imageName := samokater.GenerateObjectName(object.User)    _, err := m.client.PutObject(      ctx,      UserObjectsBucketName, \/\/ \u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u0431\u0430\u043a\u0435\u0442\u0430      imageName,      object.Payload,      object.PayloadSize,      minio.PutObjectOptions{ContentType: \"image\/png\"},   )    return imageName, err<\/code><\/pre>\n<p>\u041d\u0430\u043c \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u0444\u043e\u0442\u043e \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"go\">func (s *PGS) AddImageRecord(img string, rentID int) error {   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0440\u0435\u043d\u0434\u044b   rent, err := s.GetRentStatus(rentID)   if err != nil {      logrus.Errorf(\"Can`t get rent record in db: %v\\n\", err)      return err   }    \/\/ \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0431\u044b\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0444\u043e\u0442\u043e \u0434\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0440\u0435\u043d\u0434\u044b   \/\/ \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u0435\u0451 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043f\u043e\u043b\u0435 \u0432 \u0411\u0414   if rent.StartedAt.IsZero() {      return s.updateImages(rent.ImagesBefore, img, update_images_before, rentID)   }    return s.updateImages(rent.ImagesAfter, img, update_images_after, rentID) }<\/code><\/pre>\n<p>\u041d\u0443 \u0438 \u0441\u0430\u043c \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414:<\/p>\n<pre><code class=\"go\">func (s *PGS) updateImages(old []string, new, req string, rentID int) error {   \/\/<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-393723","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/393723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=393723"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/393723\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=393723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=393723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=393723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}