はじめに
はじめまして!基幹システムグループの田澤です。普段はNifMoの運用を担当しています。
みなさんはS3を利用したアプリケーションを作成する際に開発環境をどのように構築していますか?
endpointにawsのs3を指定するのは楽ですが少額とはいえお金がかかるので、ローカルのほうが検証しやすいですよね。
今回の記事では、ローカルS3の開発環境のサンプルを作ってみました!
サンプルでできること
Pythonのコンテナからminio(S3)に対してAWS SDKでアクセスし、以下の事ができます
- バケット作成と削除
- ファイル作成と削除と内容取得
環境
- Microsoft Windows [Version 10.0.19044.2604]
- Docker version 20.10.11, build dea9396
- docker-compose version 1.29.2, build 5becea4c
ファイル構成
1 2 3 4 5 6 7 8 9 |
│─docker-compose.yml │─python.Dockerfile └─sample └─Pipfile └─create_bucket.py └─create_file.py └─read_file.py └─delete_file.py └─delete_bucket.py |
ファイル内容
docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
version: "3.7" services: python: image: sample/python container_name: python build: context: ./ dockerfile: python.Dockerfile stdin_open: true volumes: - ./sample:/sample networks: default: ipv4_address: 172.21.1.2 minio: container_name: minio image: minio/minio:latest volumes: - ./minio:/export ports: - "9090:9000" - "9091:9001" environment: - MINIO_ROOT_USER=miniominio - MINIO_ROOT_PASSWORD=miniominio networks: default: ipv4_address: 172.21.1.3 command: ['server', '/export', '--console-address', ':9001'] createbuckets: image: minio/mc depends_on: - minio entrypoint: > /bin/sh -c " until (/usr/bin/mc config host add minio http://minio:9000 miniominio miniominio) do echo '...waiting...' && sleep 1; done; /usr/bin/mc mb minio/default-bucket; /usr/bin/mc policy download minio/default-bucket; exit 0; " networks: default: ipam: driver: default config: - subnet: "172.21.1.0/24" |
各サービスの説明:
- Python
- 使用しているコンテナイメージ: https://hub.docker.com/_/python
- minio
- 使用しているコンテナイメージ: https://hub.docker.com/r/minio/minio/
- ports
- minioのデフォルトポートは9000と9001です。僕の環境だと9000番ポートは競合するため、9090と9091を割り当てています。
- environment
- minioにアクセスする際のキーを環境変数として指定しています
- createbuckets
- 使用しているコンテナイメージ: https://hub.docker.com/r/minio/mc/
- entrypoint
- until ~~ の部分では、minioに接続できるまで待機しています。ここでは、minioにアクセスする際のキーを利用し、接続しています。
- 接続できしだい、default-bucketの作成を行っています。
python.Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
FROM python:3.11-slim # 日本時間対応 ENV TZ=Asia/Tokyo # 作業ディレクトリ ENV WORKDIR /sample # ディレクトリ作成 RUN mkdir ${WORKDIR} WORKDIR ${WORKDIR} COPY . ${WORKDIR} # Python依存ライブラリをインストール RUN pip install --upgrade pip && \ pip install pipenv |
Pipfile
1 2 3 4 5 6 7 8 9 |
[[source]] url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" [packages] boto3 = "==1.26.92" [dev-packages] |
create_bucket.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # bucketを作成 s3_resource.create_bucket(Bucket=bucket_name) |
boto3.resourceでは、minioの環境変数で決めたMINIO_ROOT_USER、MINIO_ROOT_PASSWORDを指定しています。
create_file.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # file名 file_name = "test-file" # bucketにファイル作成 s3_resource.Object(bucket_name, file_name).put(Body="hogehoge") |
read_file.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # file名 file_name = "test-file" # ファイルの内容を読み込む file_data = s3_resource.Object(bucket_name, file_name).get()[ 'Body'].read().decode('utf-8') print("#test-fileのファイル内容の出力") print(file_data) |
delete_file.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # file名 file_name = "test-file" # test-fileを削除 s3_resource.Object(bucket_name, file_name).delete() |
delete_bucket.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # bucketを削除 s3_resource.Bucket(bucket_name).delete() |
動作確認
docker-compose.ymlがあるディレクトリで以下コマンドを打ちます
1 2 |
$ docker-compose build $ docker-compose up -d |
コンテナが起動したら以下を確認します。
- http://127.0.0.1:9091/ にアクセス
- docker-compose.yml内で指定しているMINIO_ROOT_USER、MINIO_ROOT_PASSWORDでログイン
1 2 3 4 |
#docker-compose.yml より抜粋 environment: - MINIO_ROOT_USER=miniominio - MINIO_ROOT_PASSWORD=miniominio |
ログインすると以下のような画面が表示されるはずです。
その際にdefault-bucketが作成されていることを確認しましょう。
これはdocker-compose.ymlのcreatebucketsで作成されたバケットになります。
画面確認ができたので、次はpythonコンテナに入り、サンプルソースを実行していきます。
pythonコンテナに入りpipenv shellをする
1 2 3 |
$ docker exec -it python bash root@0669eae81131:/sample# pipenv install root@0669eae81131:/sample# pipenv shell |
create_bucket.pyを実行しminioのweb画面からtest-bucketが作成されていることを確認する
1 |
(sample) root@0669eae81131:/sample# python create_bucket.py |
http://127.0.0.1:9091/buckets
にアクセスし、以下のようにtest-bucketが作成されていることを確認する
create_file.pyを実行しminioのweb画面でtest-fileが作成されていることを確認する
1 |
(sample) root@0669eae81131:/sample# python create_file.py |
http://127.0.0.1:9091/buckets/test-bucket/browse
にアクセスし、以下のようにtest-fileが作成されていることを確認する
read_file.pyを実行しtest-fileの中身を読み込めることを確認する
1 2 3 |
(sample) root@0669eae81131:/sample# python read_file.py #test-fileのファイル内容の出力 hogehoge |
delete_file.pyを実行し、minioのweb画面でtest-fileが削除されていることを確認する
1 |
(sample) root@0669eae81131:/sample# python delete_file.py |
http://127.0.0.1:9091/buckets/test-bucket/browse
にアクセスし、以下のようにtest-fileが削除されていることを確認する
delete_bucket.pyを実行し、minioのweb画面でtest-bucketが削除されていることを確認する
1 |
(sample) root@0669eae81131:/sample# python delete_bucket.py |
http://127.0.0.1:9091/buckets
にアクセスし以下のようにtest-bucketが削除されていることを確認する
長くなりましたが、以上でサンプルの実行ができました。
おわりに
今回はMinIOを利用したローカル開発環境のサンプルを作成しました。
ブログ投稿は初めてなのでお手柔らかにお願いします!