Załadowywanie obrazków do Heroku - Zappisywanie ich dzięki AWS S3 i Fog

Przez:, Z dnia:

Ten tutorial zakłada, że już ukończyłeś:

  1. Users' avatars

Nasze obrazki zostają załadowane do aplikacji. Jednakże, keidy zrobisz deploy do Heroku:

bash

$ git add . #add changes to git
$ git commit -m "image upload with paperclip" #commit changes
$ git push # push changes to bitbucket
$ git push heroku master # push changes to heroku
$ git heroku run rake db:migrate #update heroku database

Jak spróbujesz załadować obrazki na stronie heroku - będą działać. Jadnak kiedy zrestartujesz aplikację (co ma mjesce podczas "deploy"):

$ heroku restart

Zobaczysz, że wszystkie obrazki zniknęły. Dzieje się tak dlatego, że Heroku nie pozwala na przechowywanie plików na ich serwerze. Żeby temu zaradzić, do przechowywania obrazków, użyjemy zewnętrznego serwara. W naszym przypadku będziemu używać usługi Amazon S3. W tym tutorialu:

  • stworzymy kontro Amazon S3 (wymaga karty kredytowej, ale koszt jest super niski)
  • dodamy gemy AWS-SDK i Fog
  • sprawimy, że załadowywanie obrazków będzie działać na Heroku

Amazon S3 nie jest darmowy, ale jest tak tani, żę nawet nie poczujesz rachunku. Mój pierwszy rachunek od Amazon S3 otrzymałem po trzech miesiącach i wynosił on niecałe 10gr. Amazon oferuje darmowe korzystanie z S3 przez pierwszy rok do 5GB. Ale wciąż musisz użyć karty kredytowej by się zarejestrować. Może być słabo kiedy takiej nie posiadasz. Dla tych z Szanghaju - dajcie znać przez formularz kontaktowy i może będę mógł pomóc. Lub poszukajcie w Google jak dokonać rejestracji bez karty kredytowej, a może nawet znajdziesz jakiś lepszy sposób. Jeżeli znajdziesz coś przydatnego, proszę, podziel się tym w komentarzach.

Krok 1: Stwórz konto Amazon S3

Przejdź do strony AWS i jeżeli nie masz jeszcze konta Amazon, zarejestruj się. Następnie zaloguj. Jak skończysz przejdź do konsoli zarządzania AWS i wybierz S3.

Będziesz musiał jeszcze wyklikać, że rozumiesz warunki itp.

Jak już skończyłeś konfgurację konta S3, otwórz konsolę zarządzania AWS i stwórz dwa nowe "buckets".

Nazwij je odpowiednio "rails-demo-production" i "rails-demo-dev". Jeżeli nazwy nie są dostępne, użyj innych i upewnij się, że używasz właściwych w aplikacji.

Teraz chcemy dodać referencje bezpieczeństwa by mieć dostęp do "buckets". Kliknij na "Security Credentials".

Następnie "Access Keys (Access Key ID and Secret Access Key)".

Powinny wyglądać jak te:

  • Access Key (Klucz dostępu): AKIAIRPKLJNSDO23425
  • Secret Access Key (Sekretny klucz dostępu): 9LXV/GWagu/CJ4DoMLKSmdasdaZeUyuax/Ei92hL7

Upewnij się, że są bezpieczne.

Krok 2: Dodaj gemy AWS-SDK i Fog

Możemy teraz wrócić do aplikacji i dokonać wszystkich potrzebnych zmian:

Gemfile

gem 'aws-sdk', '~> 1.36.1'
gem 'fog'

Załaduj nowe gemy:

bash

$ bundle install

Krok 2.2: Zmodyfikuj plik user.rb

Musimy powiedzieć naszemu modelowi użytkownika żeby używał "fog" do wysyłania plików do S3. Naszą oryginalną deklarację:

app/models/user.rb

has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" },
    :default_url => "/images/:style/missing.png"

Nieco zmodyfikujemy:

app/models/user.rb

has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" },
    :default_url => "/images/:style/missing.png",
    :url  => ":s3_domain_url",
    :path => "public/avatars/:id/:style_:basename.:extension",
    :storage => :fog,
    :fog_credentials => {
        provider: 'AWS',
        aws_access_key_id: "AKIAIRPKLJNSDO23425",
        aws_secret_access_key: "9LXV/GWagu/CJ4DoMLKSmdasdaZeUyuax/Ei92hL7"
    },
    fog_directory: "rails-demo-env"

Krok 2.3: Dodaj gem Figaro

Trzymanie naszych poufnych zmiennych w kodzie źródłowym nie jest najlepszym sposobem. Musimy trzymać je gdziś w bezpiecznym miejscu. Od wyjścia Rails 4.1 możemy używać pliku secrets.yml ale wydaje mi się to mylące i nieużyteczne porównując z gemem Figaro. Pomoże on nam zarządzać wszystkimi sekretami i bezpiecznie aktualizować zmienne Heroku. Zacznijmy od dodania go do Gemfile:

Gemfile

# existing code

gem "figaro"

I załadujmy:

bash

$ bundle install

Krok 2.4: Uruchom instalację

Następnie musimy uruchomić instalator, który wygeneruje plik application.yml na nasze zmienne:

bash

$ rails generate figaro:install

    create  config/application.yml
    append  .gitignore

Krok 2.5: Zastąp zmienne AWS

Ten plik nie będzie dodawany przz git, ponieważ figaro automatycznie dodaje go do pliku .gitignore. Otwórzmy go i dodajmy zmienne:

config/aplication.yml

# Add application configuration variables here, as shown below.
#
# PUSHER_APP_ID: "2954"
# PUSHER_KEY: 7381a978f7dd7f9a1117
# PUSHER_SECRET: abdc3b896a0ffb85d373
# STRIPE_API_KEY: EdAvEPVEC3LuaTg5Q3z6WbDVqZlcBQ8Z
# STRIPE_PUBLIC_KEY: pk_BRgD57O8fHja9HxduJUszhef6jCyS

Zastąpmy to naszymi zmiennymi od AWS:

config/aplication.yml

SECRET_KEY_BASE: 60949ad338a3c9a578350ae917bb74372a40a45e5d93c80addaa13d4bf57a62352c644e861c24ce8a5c61fc193f7dbbbf39aadff80e17285f5ac5bf6f0db8200
AWS_ACCES_KEY_ID: AKIAIRPKLJNSDO23425
AWS_SECRET_ACCESS_KEY: 9LXV/GWagu/CJ4DoMLKSmdasdaZeUyuax/Ei92hL7

development:
  FOG_DIRECTORY: rails-demo-dev
production:
  FOG_DIRECTORY: rails-demo-production

Krok 2.6: Zastąp Ustalone Wartości

Możemy teraz zastąpić nasze ustalone wartości nawiązaniami do "zmiennych środowiskowych przechowywanych przez figaro".

app/models/user.rb

has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" },
    :default_url => "/images/:style/missing.png",
    :url  => ":s3_domain_url",
    :path => "public/avatars/:id/:style_:basename.:extension",
    :storage => :fog,
    :fog_credentials => {
        provider: 'AWS',
        aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"],
        aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"]
    },
    fog_directory: ENV["FOG_DIRECTORY"]

Krok 2.7: Dodaj hasło i login do Aplikacji

Możemy także umieścić tam nasze login i hasło, których użylismy do wysyłania emaili:

config/environments/development.rb

config.action_mailer.smtp_settings = {
    address: "smtp.gmail.com",
    port: 587,
    authentication: "plain",
    enable_starttls_auto: true,
    user_name: ENV["EMAIL_LOGIN"],
    password: ENV["EMAIL_PASSWORD"]
}

config/environments/production.rb

config.action_mailer.smtp_settings = {
    address: "smtp.gmail.com",
    port: 587,
    authentication: "plain",
    enable_starttls_auto: true,
    user_name: ENV["EMAIL_LOGIN"],
    password: ENV["EMAIL_PASSWORD"]
}

Dodajmy zmienne do pliku application.yml:

config/application.yml

SECRET_KEY_BASE: 60949ad338a3c9a578350ae917bb74372a40a45e5d93c80addaa13d4bf57a62352c644e861c24ce8a5c61fc193f7dbbbf39aadff80e17285f5ac5bf6f0db8200
AWS_ACCES_KEY_ID: AKIAIRPKLJNSDO23425
AWS_SECRET_ACCESS_KEY: 9LXV/GWagu/CJ4DoMLKSmdasdaZeUyuax/Ei92hL7
EMAIL_LOGIN: email@gmail.com
EMAIL_PASSWORD: passwordhere

development:
  FOG_DIRECTORY: rails-demo-dev
production:
  FOG_DIRECTORY: rails-demo-production

Zaktualizuj Twój plik secrets.yml:

config/secrets.yml

development:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

test:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

Jeżeli masz odpaloną aplikację - czas na zrestartowanie jej. Jeżeli nie masz, uruchom rails server.

Możesz to teraz przetestować. Twoja aplikacjia zacznie wysyłanie obrazków do Amazon S3. W zależności od tego gdzie mieszkasz, może to być bardzo powolny proces. Jednak się nie martw, jak tylko zrobimy deploy aplikacji do Heroku stanie się ona o wiele szybsza.

Krok 3: Spraw by to wszystko działało na Heroku

Musimu znaleźć jakiś sposób na dostarczyć cały sekretny kod do Heroku. Może to byc bardzo uciążliwe, ale konfiguracja Figaro z Heroku jest przechodzi łatwo. Zwyczajnie odpal tę komendę:

bash

$ rake figaro:heroku

W przypoadku gdy się nie uda - limit czasu/błedy itd. (w Chinach wszystko możliwe), zawsze możesz dodać zmienne manualnie:

bash

$ heroku config:set SECRET_KEY_BASE='1fe51548304cc75187d202dff0bd17a16999b815b1c326382afd2bf8a4323493f04a2a7c63485c022b724f05911170a65ad72ab30be87f40de8be937eaa8f6e2'
$ heroku config:set AWS_ACCESS_KEY='AKIAIRPKLJNSDO23425'
$ heroku config:set AWS_SECRET_ACCESS_KEY='9LXV/GWagu/CJ4DoMLKSmdasdaZeUyuax/Ei92hL7'
$ heroku config:set FOG_DIRECTORY='rails-demo-production'
$ heroku config:set EMAIL_LOGIN='you@gmail.com'
$ heroku config:set EMAIL_PASSWORD='yourpassword'

Upewnij się, że używasz odpowiednich wartości.

Krok 3.2: Ostatnie zmiany w pliku production.rb

Jesteśmy prawie gotowi na dodanie zmian i wypchnięcie aplikacji na serwer. Ale najpierw, dokonajmy ostatnich regulacji. Domyślnie nasza produkcja nie pozwali na dostęp publicznych katalogów z przeglądarki. Aby zmienić to zachowanie (tak by nasz obrazek zastępczy działał) musimy zmienić jedną linijkę w config/environments/production.rb.

config/environments/production.rb

config.serve_static_assets = true

Jesteśmy gotowi.

bash

$ git add .
$ git commit -m "AWS and Fog added for user avatars"
$ git push
$ git push heroku master

Musisz się zalogować by móc oznaczyć tutorial jako ukończony żeby śledzić swój postęp



Komentarze

  • Z dnia: Brunitob napisał:

    I have a questios, where do you get:

    SECRET_KEY_BASE: 60949ad338a3c9a578350ae917bb74372a40a45e5d93c80addaa13d4bf57a62352c644e861c24ce8a5c61fc193f7dbbbf39aadff80e17285f5ac5bf6f0db8200
    
  • Z dnia: Andrew Hamilton napisał:

    run ' $: rake secret ' in your terminal to generate a key. ( http://edgeguides.rubyonrails.org/41release_notes.html#config-secrets-yml)

  • Z dnia: Anchieta Junior napisał:

    Just in case someone has a problem with that, the new comand to run Figaro Gem installation is just "figaro install" and it's no longer "rails generate figaro:install".

  • Z dnia: Andrew Hamilton napisał:

    Also worth noting that the rake task for Figaro setting up on Heroku is now ' $: figaro heroku:set -e production ' instead of ' $: rake figaro:heroku '. ( https://github.com/laserlemon/figaro#heroku-configuration )

  • Z dnia: Adam napisał:

    i'm having a problem uploading my avatar to S3. i get this error : ArgumentError in Devise::RegistrationsController#update Missing required arguments: awsaccesskey_id

    Extracted source (around line #244): unless missing.empty?

          raise ArgumentError, "Missing required arguments: #{missing.join(", ")}"
        end
        unless recognizes.empty?
    

    i followed every step in the tutorial and i updated my AWSACCESKEYID and AWSSECRETACCESSKEY.

    i think it's a fog gem problem. can someone help me please, i'm stuck ! thank you.

  • Z dnia: clement napisał:

    I had the same problem, and I dont really understand why, but wrapping the ENV["AWSACCESSKEYID"] in strings (replacing by : "#{ENV["AWSACCESSKEYID"]}") did it.

Dodaj komentarz

Możesz się zalogować by skomentować