Amazon S3 to niezwykle potężna usługa stanowiąca rdzeń Amazon Web Services. Jednak poza środowiskiem produkcyjnym praca z S3 może być trudna. Na szczęście istnieje narzędzie, które pomaga rozwiązać ten problem. FakeS3 to lekki serwer, który symuluje zachowanie prawdziwego S3. Odpowiada na te same wywołania, na które odpowiada Amazon S3 i przechowuje przesłane pliki w lokalnym systemie plików - bez żądań kierowanych do usługi Amazon. Chociaż gem nie obsługuje pełnego zestawu poleceń S3, zaimplementowane API jest wystarczające dla większości przypadków użycia aplikacji.
![](/app/uploads/2024/05/cover-n-1024x576-1.jpg)
W tym artykule przedstawię podejście do integracji AWS i FakeS3 z Paperclip - popularną biblioteką dołączania plików dla Active Record. Paperclip i S3 połączone razem zapewniają efektywny system przechowywania plików, który łączy przydatne podstawowe funkcje Paperclip (takie jak zarządzanie walidacjami i transformacje obrazów) z zaletami przechowywania online. Chociaż konfiguracja tych narzędzi nie jest oczywista i wymaga zagłębienia się w szczegółową dokumentację, a także rozwiązania wielu specyficznych dla gemów problemów, warto poświęcić trochę czasu, aby przyspieszyć i usprawnić rozwój.
Jaki jest nasz cel?
Integracja opisanych narzędzi wymaga trzech kroków:
- Uruchamianie fakeservera S3 dostarczanego przez gem FakeS3 w tle.
- Konfiguracja klienta AWS S3 do delegowania wszystkich żądań do uruchomionego fakeservera.
- Konfigurowanie Paperclip do używania fałszywego punktu końcowego S3 w adresach URL zbudowanych zasobów.
Instalacja
Zacznijmy od zainstalowania wymaganych klejnotów:
# Gemfile
gem "paperclip"
gem "aws-sdk", "~> 1.6"
gem "fakes3", group: [:development, :test]
Upewnij się, że zainstalowana jest wersja 1.6 aws-sdk. Paperclip, który używa SKD do zarządzania pamięcią masową w usłudze Amazon, nie działa dobrze z wyższymi wersjami tego klejnotu. Wynika to ze znaczących zmian w API SDK wprowadzonych w wersji 2.0.
Należy również pamiętać, że głównym celem FakeS3 jest zminimalizowanie zależności runtime. Jest to bardziej narzędzie programistyczne do testowania wywołań S3 w aplikacji kod a nie serwer produkcyjny, który chce powielić funkcjonalność S3. Dlatego też gem powinien być używany tylko w grupie deweloperskiej i testowej.
Konfiguracja AWS
AWS SDK zapewnia dedykowaną metodę pomocniczą odpowiedzialną za ładowanie konfiguracji. Domyślnie załaduje ona konfigurację z config/aws.yml
, wyodrębnij jego parametry dla bieżącego środowiska i przekaż je klientowi AWS. Po pierwsze, wywołaj następującą metodę w inicjalizatorze:
# config/initializers/aws.rb
AWS::Rails.load_yaml_config
Teraz, gdy plik konfiguracyjny został poprawnie załadowany, możemy przystąpić do określania jego zawartości:
# config/aws.yml
development: &development
access_key_id: "abc"
secret_access_key: "abc"
s3_endpoint: "localhost"
s3_port: 10001
s3_force_path_style: true
use_ssl: false
test: *development
Omówmy po kolei wszystkie parametry:
access_key_id, secret_access_key
- Poświadczenia klienta AWS wymagane do uzyskania dostępu do konta Amazon. Są one ignorowane przez fałszywy serwer S3, stąd niestandardowe wartości w środowiskach sandbox.s3_endpoint, s3_port
- Specyfikacja punktu końcowego S3. Używamy tych parametrów, aby zastąpić prawdziwy punkt końcowy S3 fałszywym punktem końcowym uruchomionym przez gem FakeS3 - wszystkie żądania do usługi Amazon będą teraz delegowane do lokalnego fakeservera.s3_force_path_style
- S3 akceptuje dwa style umieszczania nazwy zasobnika w adresie URL. Można wybrać umieszczenie nazwy bucketu w stylu domeny (bucket.s3.amazonaws.com) lub w stylu ścieżki (s3.amazonaws.com/bucket). Aby zachować prostotę i uniknąć dodatkowej konfiguracji związanej z mapowaniem subdomeny bucket na adres pętli zwrotnej, w środowisku programistycznym preferuję styl ścieżki zamiast stylu domeny.use_ssl
- wymusza na AWS SDK używanie HTTPS zamiast waniliowego HTTP. Musimy wyłączyć tę opcję, ponieważ gem FakeS3 nie obsługuje żądań HTTPS, które klient AWS wykonuje domyślnie.
Konfiguracja dla środowiska produkcyjnego jest dość prosta:
# config/aws.yml
production: &production
access_key_id:
secret_access_key:
staging: *produkcja
Tym razem jednak mamy do czynienia z prawdziwą usługą S3, dlatego konieczne jest podanie autentycznych poświadczeń AWS.
Ze względu na potencjalne zagrożenia bezpieczeństwa dobrą praktyką jest utrzymywanie tajnych wartości, takich jak klucze dostępu, poza systemem kontroli wersji, np. za pomocą zmiennych środowiskowych. Użyjemy ERB do wstrzyknięcia jego wartości do pliku konfiguracyjnego.
Konfiguracja spinacza
Teraz nadszedł czas, aby zmierzyć się z Paperclip i zmusić go do współpracy z już skonfigurowanym klientem S3. Głównym celem konfiguracji Paperclip jest uzyskanie ścieżki do magazynu, która zlokalizuje zasoby hostowane przez fakeserver:
localhost:10001/:bucket_name/:path
Ponownie, zacznijmy od środowiska programistycznego:
# config/paperclip.yml
development: &development
storage: :s3
bucket: "development"
s3_host_name: "localhost"
url: ":s3_alias_url"
path: ":class/:attachment/:id_partition/:style/:filename.:extension"
s3_host_alias: "localhost:10001/development"
test: *development
przechowywanie
- określa nośnik pamięci masowej (domyślnie lokalny system plików). Ponieważ używamy AWS S3, musimy zmienić go na:s3
.wiadro
- nazwa zasobnika S3, w którym będą przechowywane pliki. Jeśli bucket nie istnieje, Paperclip podejmie próbę jego utworzenia.url
- ustawiony na:s3_alias_url
spowoduje, że Paperclip będzie aliasował nazwę hosta bucketu S3 z wartością określoną przez:s3_host_alias
parametr.s3_host_alias
- alias dla domyślnego hosta bucketu S3. Zauważ, że host, port i nazwa bucketu odpowiadają konfiguracji klienta AWS.ścieżka
- wzorzec kluczy, pod którymi pliki będą przechowywane w bucket. Klucze powinny być unikalne w obrębie zasobnika, podobnie jak nazwy plików. Ze względu na fakt, że S3 nie obsługuje katalogów, można użyć klucza/
do symulowania struktur katalogów.
# config/paperclip.yml
production: &production
storage: :s3
bucket:
url: ":s3_domain_url"
path: ":class/:attachment/:id_partition/:style/:filename.:extension"
staging: *produkcja
Podobnie jak poświadczenia AWS, nazwa bucketu jest również uważana za tajną wartość, która powinna być przechowywana poza bazą kodu. Zalecam przechowywanie jej nazwy w zmiennej środowiskowej.
Na koniec połącz konfigurację z domyślnymi opcjami Paperclip w inicjalizatorze:
# config/initializers/paperclip.rb
paperclip_defaults = Rails.application.config_for :paperclip
paperclip_defaults.symbolize_keys!
Paperclip::Attachment.default_options.merge! paperclip_defaults
Uruchamianie fakes3
Zarówno konfiguracja AWS, jak i Paperclip zawierają odniesienie do lokalnego fakeservera S3, który ma działać pod adresem localhost:10001
. Przed rozpoczęciem pracy w programie deweloperskim należy uruchomić serwer za pomocą następującego polecenia (dostarczonego przez gem FakeS3):
fakes3 -r public/system -p 10001
Przekazywane parametry to:
root -r
- katalog główny, w którym będą przechowywane przesłane pliki. Rozważ wyłączenie go z VCS, jeśli nie chcesz, aby przesłane pliki były przechowywane w repozytorium.port -p
- numer portu, na którym zostanie uruchomiony serwer lokalny.
Jeśli używasz Foremana do zarządzania procesami w swojej aplikacji, wygodne może być dodanie następującego wpisu do Procfile:
# Procfile
fakes3: fakes3 -r ${FAKES3_STORAGE_PATH:-public/system} -p ${FAKES3_PORT:-10001}
Pozwoli to zaoszczędzić czas tracony na uruchamianie fakeservera za każdym razem, gdy trzeba będzie opracować funkcje związane z S3.
Wnioski
Skonfigurowaliśmy klienta AWS, aby delegował wszystkie żądania do lokalnego fakeservera, skonfigurowaliśmy Paperclip, aby używał fałszywego punktu końcowego S3 w zbudowanych adresach URL zasobów i uruchomiliśmy fakeserver dostarczony przez gem Fake S3 przechowujący wszystkie pliki w lokalnym systemie plików.
W rezultacie uniezależniliśmy się od połączenia internetowego i zaoszczędziliśmy pieniądze, dzięki czemu nasz rozwój był szybszy i bardziej niezawodny.