DockerとMinioでAWS SDK for C++の開発環境を構築する

AWS SDK for C++を利用した開発を行うのにDockerとMinioを利用して開発環境を用意してみました。


## 環境構築

GitHubに設定と実装をアップしていますので、よければご参考ください。
https://github.com/kai-kou/aws-sdk-cpp-on-docker


`Dockerfile` でAWS SDK for C++がインストールされたイメージをビルドできるようにします。
ベースとなるイメージに`ubuntu` 指定していますが、他に変えてもおｋです。お好みで。

SDKのビルド時に`-DBUILD_ONLY` を指定しないとSDK全体がビルドされることになり、おそらく数時間かかりますので、ご注意ください。

```Dockerfile:Dockerfile
FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y git build-essential cmake clang

RUN apt-get update && \
    apt-get install -y libcurl4-openssl-dev libssl-dev uuid-dev zlib1g-dev libpulse-dev
RUN git clone https://github.com/aws/aws-sdk-cpp.git && \
    mkdir aws-sdk-cpp-build && \
    cd aws-sdk-cpp-build && \
    cmake -DBUILD_ONLY="s3" ../aws-sdk-cpp && \
    make && \
    make install
```

AWS SDK for C++を利用してS3へアクセスするのに、ローカル環境としてMinioを利用しています。
Minioについては下記をご参考ください。

S3互換のオブジェクトストレージ MinioをDocker Composeで利用する - Qiita
https://qiita.com/kai_kou/items/9fe06d4d24928d9efa2a

```yaml:docker-compose.yaml
version: '3.3'

services:
  dev:
    build: .
    volumes:
    - type: bind
      source: ./src
      target: /cpp-dev
  minio:
    image: minio/minio
    volumes:
    - type: bind
      source: ./data
      target: /export
    ports:
    - "9000:9000"
    environment:
      MINIO_ACCESS_KEY: hogehoge
      MINIO_SECRET_KEY: hogehoge
    command: server /export
```

上記ファイルを含むファイル構成は以下のようになります。

```console
> tree
.
├── Dockerfile
├── data
│   └── hoge
├── docker-compose.yml
└── src
    ├── CMakeLists.txt
    ├── build
    └── main.cpp
```

### 実装

`put_object` メソッドでS3(Minio)へファイルをPUTしています。
Minioを利用する都合、`endpointOverride` を利用しています。
詳細は下記をご参考ください。

S3互換のオブジェクトストレージ MinioにAWS SDK for C++でアクセスするのにハマるポイント - Qiita
https://qiita.com/kai_kou/items/095e409539fbe77f0d59


```cpp:main.cpp
#include <iostream>

#include <aws/core/Aws.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/auth/AWSAuthSigner.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>

void put_object(Aws::String key_name) {
  const Aws::String endpoint = "minio:9000";
  const Aws::String bucket_name = "hoge";

  auto input_data = Aws::MakeShared<Aws::StringStream>("");
  *input_data << "hoge!" << '\n';

  Aws::S3::Model::PutObjectRequest object_request;
  object_request.WithBucket(bucket_name)
                .WithKey(key_name)
                .SetBody(input_data);

  Aws::SDKOptions options;
  Aws::InitAPI(options);

  // Minioを利用する場合、ちょっと面倒
  Aws::Auth::AWSCredentials cred = Aws::Auth::EnvironmentAWSCredentialsProvider().GetAWSCredentials();
  Aws::Client::ClientConfiguration clientConfig;
  if (!endpoint.empty()) {
    clientConfig.scheme = Aws::Http::Scheme::HTTP;
    clientConfig.endpointOverride = endpoint;
  }
  auto const s3_client = Aws::S3::S3Client(cred, clientConfig,
    Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false);

  // Minioを利用しない場合、下記でおｋ
  // Aws::S3::S3Client s3_client(clientConfig);

  auto const outcome = s3_client.PutObject(object_request);
  if (outcome.IsSuccess()) {
    std::cout << key_name << " Done!" << std::endl;
  }
  else {
    std::cout << key_name << " Error: ";
    std::cout << outcome.GetError().GetMessage().c_str() << std::endl;
  }

  Aws::ShutdownAPI(options);
}

int main()
{
  put_object("hoge1.txt");

  return 0;
}
```

`CMakeLists.txt` でAWS SDK for C++が利用できるように指定します。

```txt:CMakeLists.txt
cmake_minimum_required(VERSION 3.5)

find_package(AWSSDK REQUIRED COMPONENTS s3)

add_definitions(-DUSE_IMPORT_EXPORT)

add_executable(main main.cpp)

target_link_libraries(main ${AWSSDK_LINK_LIBRARIES})
```


### Dockerコンテナの立ち上げ

```console
> docker-compose build

> docker-compose up -d minio

> docker-compose run dev bash
#
```

#### Minioの準備

`docker-compose up -d minio` でMinioのコンテナが立ち上がったら`http://localhost:9000` にブラウザでアクセスしてバケット`hoge` を作成します。作成後、Bucket PolicyをPrefix:`*` に`Read and Write` で設定します。

設定の詳細は下記をご参考ください。

S3互換のオブジェクトストレージ MinioをDocker Composeで利用する - Qiita
https://qiita.com/kai_kou/items/9fe06d4d24928d9efa2a


## ビルドして実行する

```console:コンテナ内
# cd /cpp-dev/build
# cmake ..
# cmake --build .
# ./main
hoge1.txt Done!
```

問題なく実行できました。
Minioが利用するディレクトリにファイルが保存されたのも確認できます。

```console：コンテナ外
> tree data/hoge
data/hoge/
└── hoge1.txt
> cat data/hoge/hoge1.txt
hoge!
```

やったぜ。


## 参考

aws/aws-sdk-cpp: AWS SDK for C++
https://github.com/aws/aws-sdk-cpp

S3互換のオブジェクトストレージ MinioをDocker Composeで利用する - Qiita
https://qiita.com/kai_kou/items/9fe06d4d24928d9efa2a

S3互換のオブジェクトストレージ MinioにAWS SDK for C++でアクセスするのにハマるポイント - Qiita
https://qiita.com/kai_kou/items/095e409539fbe77f0d59