0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel + MinIO temporaryUrlメソッドについて

Posted at

MinIOは、AWSのS3と互換性のあるオブジェクトストレージサーバーです。
開発環境でS3の代替として使用されることが多く、ローカル環境でクラウドストレージのシミュレーションを行うのに適しています。

LaravelのファイルストレージでMinIOを使用する際、公式ドキュメントではtemporaryUrlメソッドがサポートされていないと記述されています。

MinIOを使用する場合、temporaryUrlメソッドによる一時ストレージURLの生成はサポートされていません。

サポートされていないと書かれていますが、temporaryUrlメソッド自体は動作します。
ただ、設定によっては、生成されたURLがブラウザからアクセスできない場合があります。
その問題点と解決策について説明します。

問題点

開発環境をDockerで構築した場合、MinIOを使用する際の環境変数は以下のようになると思います。

.env
AWS_ACCESS_KEY_ID=minio_username
AWS_SECRET_ACCESS_KEY=minio_password
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=local
AWS_ENDPOINT=http://minio:9001
AWS_USE_PATH_STYLE_ENDPOINT=true

AWS_ENDPOINTにはPHPアプリケーション側からアクセスするためのURLを指定します。
ただ、この設定のみだと、urlメソッドを使いURLを生成した場合、http://minio:9001/local/xxx のようなURLが生成されます。
このURLはPHPアプリケーション側からみたDockerネットワーク内部のURLなので、Docker外部(つまり、ホストマシンのブラウザなど)から直接アクセスすることはできません。
そのため、ドキュメントには次のように書かれています。

MinIOを使用するときに Laravelの統合が適切なURLを生成するには、AWS_URLアプリケーションのローカル URLと一致し、URLパスにバケット名が含まれるように環境変数を定義する必要があります。

なので、環境変数にAWS_URLを追加します。

.env
AWS_URL=http://localhost:9001/local

この設定を行うことで、urlメソッドでURLを生成した場合、http://localhost:9001/local/xxx のようなURLが生成されDocker外部からアクセスできるようになります。

ただ、temporaryUrlメソッドによるURLの生成はAWS_URLではなくAWS_ENDPOINTを元に生成されるため、Docker外部からアクセスできません。
temporaryUrlメソッド自体は動作するので、AWS_ENDPOINTのURLをDocker外部からアクセスできる状態になれば問題は解決します。

解決策

上記の状態で一番簡単な解決策は、AWS_URLの環境変数は使わず、AWS_ENDPOINTのホスト名をホストマシンの/etc/hostsに追加することです。

hosts
127.0.0.1 minio

少し強引ですが、http://minio:9001/local/xxx はDocker外部からアクセスできるようになります。

その他の解決策

その他解決策は色々あるのですが、MinIOのURLをhttpsにするパターンでLaravelとMinIOが動く環境をDockerで構築してみます。

Dockerの設定

Docker Composeを使用して環境を構築します。以下はdocker-compose.ymlの例です。

minio.laravel.testというホスト名でMinIOにアクセスできるようにします。
minio-create-bucketsはMinIOのバケットを作成するためのコンテナです。

docker-compose.yml
services:
    app:
        build:
            context: ./docker/php
        volumes:
            - .:/var/www
        working_dir: /var/www
        user: 1000:1000
    web:
        build:
            context: ./docker/nginx
        ports:
            - 80:80
            - 443:443
        volumes:
            - ./docker/nginx/config:/etc/nginx/conf.d
            - ./:/var/www
        networks:
            default:
                aliases:
                    - minio.laravel.test
    minio:
        image: minio/minio
        environment:
            MINIO_ROOT_USER: ${MINIO_USERNAME-minio}
            MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD-password}
        command: server /data --address :9001 --console-address :8900
        volumes:
            - minio:/data
        ports:
            - 9001:9001
            - 8900:8900
    minio-create-buckets:
        image: minio/mc
        depends_on:
            - minio
        entrypoint: >
            /bin/sh -c " /usr/bin/mc config host add local http://minio:9001 ${MINIO_USERNAME-minio} ${MINIO_PASSWORD-password}; /usr/bin/mc mb -p local/${MINIO_BUCKET-local}; /usr/bin/mc anonymous set download local/${MINIO_BUCKET-local}; exit 0;"

volumes:
    minio:

nginxのDockerfileでは、自己署名証明書を作成しています。

docker/nginx/Dockerfile
FROM nginx:1.25.4

RUN apt-get update && apt-get -y install openssl \
    && openssl req -newkey rsa:2048 -x509 -nodes -set_serial 1 -days 3650 \
    -subj "/C=JP/ST=Tokyo/L=Chiyoda-ku" \
    -keyout "/etc/ssl/private/server.key" -out "/etc/ssl/private/server.crt" \
    && chmod 400 /etc/ssl/private/server.*

nginxの設定でminio.*のホスト名でMinIOにアクセスできるようにします。

docker/nginx/config/default.conf
server {
    listen 80 default_server;
    listen 443 ssl default_server;

    server_name _;

    client_max_body_size 0;

    root /var/www/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include fastcgi_params;

        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_read_timeout 600;
    }

    ssl_certificate /etc/ssl/private/server.crt;
    ssl_certificate_key /etc/ssl/private/server.key;
}

server {
    listen 80;
    listen 443 ssl;

    server_name minio.*;

    client_max_body_size 0;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        proxy_pass http://minio:9001/;
    }

    ssl_certificate /etc/ssl/private/server.crt;
    ssl_certificate_key /etc/ssl/private/server.key;
}

PHPのDockerfileを作成します。

docker/php/Dockerfile
FROM php:8.2-fpm

RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip

RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

ホスト名の設定

ローカルマシンの/etc/hostsファイルに以下の行を追加します。

127.0.0.1 laravel.test minio.laravel.test

これにより、ブラウザからhttps://minio.laravel.testでMinIOにアクセスできるようになります。

環境変数の設定

.envファイルに以下の設定をします。

.env
AWS_ACCESS_KEY_ID="minio"
AWS_SECRET_ACCESS_KEY="password"
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET="local"
AWS_ENDPOINT="https://minio.laravel.test"
AWS_USE_PATH_STYLE_ENDPOINT=true
AWS_SSL_VERIFY=false

Laravelの設定

config/filesystems.phps3を以下のように設定します。
自己署名証明書の場合、curlでエラーが発生するので、http=>vaerifyfalseに設定します。
そのための.envAWS_SSL_VERIFY=falseを設定してあります。

's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
    'throw' => false,
    'http' => [
        'verify' => env('AWS_SSL_VERIFY', true)
    ],
],

検証

設定が正しく行われたかを確認するために、以下のようなコードを作成し実行します。

app/Console/Commands/TestMinioUrl.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

class TestMinioUrl extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test-minio-url';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'test minio url';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $disk = Storage::disk('s3');

        // Upload a file
        $disk->put('test.txt', 'Hello MinIO!!');

        // Get the URL of a file
        $url = $disk->url('test.txt');
        print "Normal URL: " . $url . PHP_EOL;

        // Generate a temporary URL
        $tempUrl = $disk->temporaryUrl('test.txt', now()->addMinutes(5));
        print "Temporary URL: " . $tempUrl . PHP_EOL;
    }
}
docker-compose exec app php artisan test-minio-url

正しく設定されていれば、生成されたURLがブラウザからアクセス可能であることを確認できます。

リポジトリ

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?