ConoHaオブジェクトストレージをboto3で使ってみる

この記事はConoHa Advent Calendar 2025の11日目の記事です。このはのアドカレは3年ぶりの参加です。

今年はあんずちゃんがいっぱいツイートしてくれて嬉しいです。

さて、2025/8/28に、ConoHaのオブジェクトストレージはS3互換APIを提供開始しました。

S3互換APIがあるということは、オブジェクトストレージの代表格であるAmazon S3を操作するAWS CLIや、AWSのPython SDKであるboto3が使えてうれしいところです。

この記事では、AWSリソースを操作するPythonライブラリのboto3を使ってConoHaのオブジェクトストレージを操作してみます。S3の経験はあるけどConoHaオブジェクトストレージは使ったことがない人の参考になれば幸いです。

ConoHaオブジェクトストレージとは

名前のとおり、ConoHaが提供するオブジェクトストレージです。

実際に使用した容量にかかわらず、確保した容量に対して100GBあたり545円/月の料金がかかります。その一方、1時間単位で使った時間分だけ課金されるので、試しやすくていいですね。また、S3やGoogle Cloud Storageなどと異なり、アウトバウンドの通信に転送料金がかかりません。

ConoHaオブジェクトストレージはオープンソースのオブジェクトストレージであるOpenStack Swiftで構築されています。そのため、従来はOpenStack SwiftのAPIを叩くか、OpenStack SwiftからS3に「翻訳」してくれるS3Proxyをローカルなどに立てたうえでS3相当の操作をする必要があり、S3と同様に扱うには若干の壁があるのが正直なところでした。

S3互換APIがあれば、S3との差異をあまり意識することなく操作できて扱いやすいですね。

事前準備

まずはオブジェクトストレージを使う前に準備をしておきましょう。手順は以下の通りです。

オブジェクトストレージの契約

事前にConoHaのコントロールパネルにログインし、左のパネルから「オブジェクトストレージ」を選び、適当に容量を選択します。お試しならまず100GBでいいでしょう。公式マニュアルに画像付きで分かりやすくまとまっているのでこれを参考にしてください。

mendoitarou_さんの昨年のアドカレの記事も分かりやすいです!(ConoHaのオブジェクトストレージを使ってみる #Conoha - Qiita

APIユーザーの作成

次に、APIユーザーを作成したことがない場合は、公式マニュアルに従って、コントロールパネルの左のパネルの「API」からAPIユーザーを作成しておいてください。

EC2 Credentialの発行

こちらも既にやったことがあれば飛ばしてOKです。

EC2 Credentialは、ConoHaのオブジェクトストレージをS3互換APIから操作するのに必要なクレデンシャルです1。AWSのaws_access_key_idaws_secret_access_keyに相当します。

まず、コントロールパネルの「API」を開きます。

ちょうど端っこからこのはちゃんが見えてかわいいですね。

以下をそれぞれメモしておきます。

EC2 Credentialを発行するためにはトークンが必要なので、先にトークンを発行します(公式マニュアル)。

次に、EC2 Credentialを発行します(公式マニュアル)。

合わせて、こんなコードで発行できます。このコードを含め、本記事の全てのコードはPython=3.13.7, boto3=1.42.5, botocore=1.42.5で実行しました。

クリックで折り畳みが開きます
import os
import requests

# os.environの各Keyの環境変数に設定していることを前提とします
# コード中べた書きでもいいですが、セキュリティ上推奨しません
# それぞれ順に
# - APIユーザーの「ユーザーID」
# - APIユーザーの「パスワード」
# - テナント情報の「テナントID」
api_user_id = os.environ["CONOHA_API_USER_ID"]
api_user_password = os.environ["CONOHA_API_USER_PASSWORD"]
tenant_id = os.environ["CONOHA_TENANT_ID"]

# トークンの発行
auth_url = "https://identity.c3j1.conoha.io/v3/auth/tokens"
auth_data = {
    "auth": {
        "identity": {
            "methods": ["password"],
            "password": {
                "user": {
                    "id": api_user_id,
                    "password": api_user_password
                }
            }
        },
        "scope": {
            "project": {
                "id": tenant_id
            }
        }
    }
}

resp = requests.post(auth_url, json=auth_data)
token = resp.headers["x-subject-token"]

# EC2 Credentialの作成
credential_url = f"https://identity.c3j1.conoha.io/v3/users/{api_user_id}/credentials/OS-EC2"
credential_data = {"tenant_id": tenant_id}

resp = requests.post(
    credential_url,
    json=credential_data,
    headers={"X-Auth-Token": token}
)
credential = resp.json()["credential"]
access_key = credential["access"]
secret_key = credential["secret"]

api_user_id, api_user_password, tenant_id, access_key, secret_keyは他人に知られないよう管理に注意してください(tokenは有効期限が24時間ではありますが、これも漏らさない方がもちろんよいですね)。

access_keyとsecret_keyの中身をそれぞれメモしておいてください。EC2 Credentialは1ユーザーにつき3つしか作成できません。もし忘れた場合は、同様にAPIで既存のEC2 Credentialを削除してから再度作成してください。

boto3を使ってConoHaオブジェクトストレージで遊んでみる

参考: Object Storage API|ConoHaドキュメントサイト

clientインスタンスの作成

まずはboto3.clientを作ります。

import boto3
from botocore.config import Config

cli = boto3.client(
    "s3",
    endpoint_url=endpoint_url,
    aws_access_key_id=access_key,
    aws_secret_access_key=secret_key,
    config=Config(
        signature_version="s3v4",
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
    ),
)

endpoint_urlは、先ほどのコントロールパネルの画像の「エンドポイント」の「S3 Service」のURLです。

ポイントは、request_checksum_calculation="when_required"と、 response_checksum_validation="when_required"を指定することです。"when_required"にしておかないと、オブジェクトをアップロードするときにXAmzContentSHA256Mismatchなどというエラーが出ます。

S3が提供する新しいチェックサム機能に合わせて、boto3>=1.36.0では、これらの引数はデフォルトで"when_supported"になりました。boto3のissueでは、S3互換ストレージでは対応していないものもあるため、エラーが出たら"when_required"にするようにとありますので、そのとおりやってあげれば回避できます。

これは地味にはまりポイントでした。

コンテナの作成

S3をboto3で操作したことがあれば、ここからは全く同じ操作で扱うことができます。

コンテナとはS3でいうバケットに相当するものです。conohaという名前のコンテナを作ってみます。

cli.create_bucket(Bucket="conoha")

コンテナのリストアップ

作ったコンテナをリストアップします。AWS CLIでいう、aws s3 ls相当の操作です。

response = cli.list_buckets()
for bucket in response.get("Buckets", []):
    print(bucket["Name"])
conoha

今作ったconohaがありますね!

オブジェクトのアップロード

2025年12月に公開されたばかりの、このはちゃんの清楚かわいい冬壁紙をアップロードしてみます。

壁紙は公式サイトからダウンロードできます。眺めていると幸せな気持ちになれますね。皆さんもダウンロードして自分のデバイスの壁紙に設定しましょう。昨今の公式素材といえばSNSアイコンが多い印象ですが、壁紙を配布してくれていて大変ありがたい…

わたしが好きなのはこのおまつりこのはちゃんですね。これはきっと夏の終わりに見た幻…

さて、さっきの冬壁紙(conoha-wallpaper-2025winter-1280x800.jpg)を、コンテナconohaに、mikumo/conoha.jpgというkeyでアップロードしてみます。S3でいうところのs3://conoha/mikumo/conoha.jpgにアップロードするということです。

cli.upload_file("conoha-wallpaper-2025winter-1280x800.jpg", "conoha", "mikumo/conoha.jpg")

オブジェクトストレージなのでディレクトリという概念はありませんが、keyをスラッシュで区切ることで仮想的にディレクトリのような階層構造で扱うことができます。

オブジェクトのリストアップ

conohaというコンテナにある全てのオブジェクトをリストアップします。aws s3 ls s3://conoha相当の操作ですね。

# 以下はオブジェクトが1000件を超える場合ページネーションが必要
# resp = cli.list_objects_v2(Bucket="conoha")
# for obj in resp.get("Contents", []):
#     print(obj["Key"])

# こちらはページネーションに対応
paginator = cli.get_paginator("list_objects_v2")
for page in paginator.paginate(Bucket="conoha"):
    for obj in page.get("Contents", []):
        print(obj["Key"])
mikumo/conoha.jpg

今アップロードしたmikumo/conoha.jpgがありますね!

オブジェクトのダウンロード

ローカルにダウンロードもできます。

cli.download_file("conoha", "mikumo/conoha.jpg", "mikumo-conoha.jpg")

Presigned URLの発行

非公開のオブジェクトでも、S3のPresigned URLという、有効期限付きのダウンロードリンクを発行することができます。

以下の例では、mikumo/conoha.jpgに対して、1時間だけ有効なURLを発行します。

url = cli.generate_presigned_url(
    "get_object",
    Params={"Bucket": "conoha", "Key": "mikumo/conoha.jpg"},
    ExpiresIn=3600  # 3600 secs = 1 hour
)
print(url)

例えばブラウザからこのURLにアクセスすると、画像を開くことができます。

ConoHaオブジェクトストレージは一時的Web公開で同様の操作ができます。これは、OpenStack Swiftが提供するSwift TempURLというOpenStack独自の一時的なアクセスURLを発行する仕組みによります。

一方でS3互換APIがありますので、ConoHa公式には記載がありませんがS3相当のPresigned URLも発行できます(上のコードです)。以下の記事にあるようにS3互換のCloudflare R2でもできるそうなので、ConoHaでもできるかな?と思ったらできました。

S3互換のCloudflare R2で署名付きURLを発行する(AWS CLI, Python + Boto3) | DevelopersIO

オブジェクトの削除

オブジェクトストレージは現在使っている容量以下に契約容量を下げることはできませんし、オブジェクトとコンテナを全て削除しないと解約できません(公式マニュアル)。そのため、オブジェクトとコンテナの削除の方法もみておきましょう。

cli.delete_object(Bucket="conoha", Key="mikumo/conoha.jpg")

ばいばいこのはちゃん…

コンテナの削除

最後にコンテナを削除します。なお、コンテナの中身が全て空でなければ削除できません(エラーが返ります)。

cli.delete_bucket(Bucket="conoha")

これで全て削除されたのでオブジェクトストレージを解約しても構いませんが、契約し続けたほうがこのはちゃんが喜びます。

おわりに

S3の経験があれば簡単に触れますし、boto3のドキュメントはいっぱいあるのでS3の経験がなくても触れそうです。

活用例を調べてみると、2015年のアドカレ記事でConoHaのインスタンスのリバースプロキシと合わせた画像アップローダーサイトが面白いなと思いました。

【月額1350円でできる!!】ConoHaのオブジェクトストレージを使ってWEB画像アップローダーサイトを作ってみよう #Ruby - Qiita

転送料金フリーなメリットを活かしてなんか作れたらいいな!

個人的な話ですが、3年前のこのはのアドカレはわたしがはじめて書いたアドカレなので、このはのアドカレには少し思い入れがあります(そのときの記事: GPT-2で作ったConoHa上のこのはちゃんbotとSlackで会話する)。久々に参加できて楽しかったので、来年も何か記事を出せるようにConoHaを触りながら考えてみます!

(本文中で引用した壁紙は©GMO Internet, Inc., 再使用禁止です)


  1. 正確には、OpenStackをS3互換APIで使うのに必要なクレデンシャルです。 ↩︎