Как я подружилась с S3: мой путь от локального хранилища до облака в Yandex Cloud
Пока я писала своего Telegram-бота для рецептов на Java, меня настигла вполне земная проблема: куда складывать сами файлы с рецептами? Git - не подходит (слишком много бинарников и частые обновления), Docker - тоже не вариант (образ раздувается, да и не для этого он задуман). Тут-то мне и подсказали про S3.
В этой статье расскажу, как я развернула локальное S3 через LocalStack, потом перешла на Yandex Cloud Object Storage и подключила всё это к Java-коду. Будет полезно, если вы тоже думаете, как хранить файлы вне репозитория и контейнера.
Что же такое S3?
S3 - это облачное объектное хранилище, разработанное Amazon Web Services (AWS) в 2006 году. Оно позволяет хранить данные в виде независимых объектов: фотографий, документов, JSON-файлов с рецептами - чего угодно.
Всё, что вы кладёте в S3, попадает в бакеты - это виртуальные «папки». Внутри бакета файлы могут быть организованы с помощью «псевдо-директорий» - на самом деле это просто префиксы в имени объекта, например: recipes/user_123/recipe_456.json.
Что особенно удобно, API у S3 одинаковый везде: и в облаке (например, в Yandex Cloud Object Storage), и локально, если вы используете эмулятор вроде LocalStack. Это значит, что код, написанный для тестов на локальной машине, без изменений заработает и в продакшене.
В случае с моим Telegram-ботом на Java это стало решающим преимуществом: я могла спокойно загружать и скачивать рецепты через единый интерфейс, не думая о том, где именно сейчас запущено приложение - на моём ноутбуке или в облаке.
Подробнее об S3 и его реализациях можно почитать в документации Yandex Cloud .
Начинаем с локального S3
Чтобы удобно разрабатывать и тестировать бота, я сначала настроила локальное S3-хранилище с помощью LocalStack — это эмулятор AWS-сервисов, который полностью совместим с S3 API.
1. Устанавливаем и запускаем LocalStack
1.1. Убедитесь, что установлен Docker. LocalStack работает в контейнере, поэтому сначала нужно установить Docker (если ещё не установлен).
1.2. Запускаем LocalStack. Выполняем команду:
1.3. Локальный S3 теперь доступен по адресу:
1.4. Создаём бакет
Бакет можно создать либо через AWS CLI, либо прямо из Java-кода. Я создавала через java-код. Но учтите, что на проде бакет нужно будет создать руками.
2. Подключаем Java-проект к локальному S3
2.1. Добавляем зависимость AWS SDK for Java v2 в pom.xml
2.2. Настраиваем S3-клиент для работы с LocalStack
Важные моменты:
- .endpointOverride() - перенаправляет все запросы на LocalStack.
- .forcePathStyle(true) - обязательно для LocalStack (иначе SDK будет использовать виртуальные хосты, которые эмулятор не поддерживает).
- Учётные данные test/test - стандартные для LocalStack и принимаются без проверки.
Теперь вы можете загружать, скачивать и удалять файлы с рецептами прямо в локальный S3, не выходя из IDE. А значит — спокойно писать и тестировать логику бота.
2. Переходим на глобальный s3 - Yandex Cloud
Мне посоветовали Yandex Cloud Object Storage, потому что он полностью совместим с AWS S3 API. Это значит: тот же код, те же методы, нужно лишь поменять endpoint и учётные данные.
3. Создаём сервисный аккаунт и получаем ключи
Для безопасного доступа к хранилищу из кода нужно создать сервисный аккаунт и сгенерировать статические ключи доступа. Это стандартная практика: вы не используете персональные учётные данные, а даёте приложению только те права, которые ему нужны.
Подробная инструкция от Yandex Cloud здесь:👉 Настройка AWS SDK for Java v2 для работы с Yandex Cloud Object Storage
Кратко:
- Создайте сервисный аккаунт в Yandex Cloud.
- Назначьте ему роль storage.editor (или кастомную с правами на ваш бакет).
- Сгенерируйте статический ключ доступа - вы получите access key и secret key.
- Никогда не коммитьте эти ключи в Git! Лучше передавать их через переменные окружения (как в примере ниже).
3.1. Создаём бакет
Бакет нужно создать в интерфейсе Yandex Cloud руками. О том, как создать бакет ребята хорошо описывают в документации по ссылке выше.
3.2. Настраиваем Java-клиент для Yandex Cloud
Код почти не отличается от локальной версии - меняется только endpoint и источник учётных данных:
Теперь приложение одинаково работает и на локальной машине (с LocalStack), и в облаке (с Yandex) достаточно передать нужный endpoint и ключи.
3.3. Хранение ключей доступа
Что еще важно, так это то, где хранятся ключи доступа.
1. Для локального использования AWS (например, при использовании LocalStack) ключи сохраняют в файле по пути ~/user/.aws/credentials. Это удобно, так AWS автоматически подхватывают их без дополнительной настройки.
Так же нужно создать еще файл с конфигами по тому же пути ~/user/.aws/config.
2. В продакшене так делать нельзя. Файлы конфигурации не должны попадать в код или образ. Вместо этого ключи передаются через переменные окружения, как в примере с YANDEX_ACCESS_KEY и YANDEX_SECRET_KEY.
Вывод
S3-совместимое хранилище простое и надёжное решение для хранения файлов. С LocalStack я легко тестировала локально, а с Yandex Cloud Object Storage безболезненно вышла в продакшен. Весь код остался тем же, изменились только endpoint и ключи. Попробуйте.