Distillery (Βασικά)
Η Distillery είναι ένας διαχειριστής εκδόσεων γραμμένος σε καθαρή Elixir. Μας επιτρέπει να δημιουργούμε εκδόσεις που μπορούν να γίνουν deploy κάπου αλλού με λίγη ή καθόλου παραμετροποίηση.
Τι είναι μια έκδοση
Μια έκδοση είναι ένα πακέτο που περιλαμβάνει τον μεταγλωττισμένο κώδικα Erlang/Elixir (για παράδειγμα BEAM bytecode). Επίσης παρέχει όσα script χρειάζονται για να εκκινήσει η εφαρμογή μας.
Όταν θα έχετε γράψει μια ή παραπάνω εφαρμογές, μπορεί να θέλετε να δημιουργήσετε ένα πλήρες σύστημα με αυτές τις εφαρμογές και ένα υποσύνολο από τις εφαρμογές Erlang/OTP. Αυτό ονομάζεται μια έκδοση. - Τεκμηρίωση Erlang
Οι εκδόσεις καθιστούν δυνατή την απλοποιημένη deployment: είναι αυτόνομες και παρέχουν τα πάντα που απαιτούνται για να εκκινήσει η έκδοση - είναι εύκολα διαχειριζόμενες από το παρεχόμενο script τερματικού για να ανοίξουμε μια απομακρυσμένη κονσόλα, να εκκινήσουμε / σταματήσουμε / επανεκιννήσουμε την έκδοση, να την εκκινήσουμε στο παρασκήνιο, να στείλουμε απομακρυσμένες εντολές και περισσότερα. Επιπρόσθετα, είναι αρχειοθετημένα αντικείμενα, που σημαίνει ότι μπορείτε να επαναφέρετε μια παλαιότερη έκδοση από το tarball της σε οποιοδήποτε σημείο στο μέλλον (εκτός από περιπτώσεις ασυμβατότητας με το υποκείμενο λειτουργικό σύστημα ή βιβλιοθήκες συστήματος). Η χρήση των εκδόσεων είναι επίσης προαπαιτούμενο της λειτουργίας των γρήγορων αναβαθμίσεων και υποβαθμίσεων, ένα από τα πιο ισχυρά χαρακτηριστικά του Erlang VM. - Τεκμηρίωση Distillery
Μια έκδοση θα περιλαμβάνει τα ακόλουθα:
-
ένα φάκελο /bin
- Αυτός περιλαμβάνει ένα script το οποίο είναι το σημείο εκκίνησης για την λειτουργία όλης της εφαρμογής μας.
-
ένα φάκελο /lib
- Αυτός περιλαμβάνει τον μεταγλωττισμένο bytecode της εφαρμογής μας μαζί με τις εξαρτήσεις του.
-
ένα φάκελο /releases
- Αυτός περιλαμβάνει τα μεταδεδομένα για την έκδοση καθώς και hooks και δικές μας εντολές.
-
ένα φάκελο /erts-ΈΚΔΟΣΗ
- Αυτός περιλαμβάνει το πλήρες περιβάλλον χρόνου εκτέλεσης της Erlang το οποίο θα επιτρέψει στο μηχάνημα να τρέξει την εφαρμογή μας χωρίς να έχει την Erlang ή την Elixir εγκατεστημένη
Ξεκινώντας / Εγκατάσταση
Για να προσθέσετε τη Distillery στο project σας, προσθέστε το σαν εξάρτηση στο αρχείο mix.exs
σας.
Σημείωση - αν δουλεύετε σε μια εφαρμογή ομπρέλας αυτό θα πρέπει να είναι στο mix.exs
αρχείο στο γονικό φάκελο του project σας.
defp deps do
[{:distillery, "~> 2.0"}]
end
Τότε στο τερματικό σας τρέξτε:
mix deps.get
mix compile
Χτίζοντας την έκδοσή σας
Στο τερματικό σας, τρέξτε:
mix release.init
Αυτή η εντολή παράγει ένα φάκελο rel
με μερικά αρχεία παραμετροποίησης μέσα του.
Για να παράξετε μια έκδοση στο τερματικό σας τρέξτε την mix release
.
Μόλις η έκδοση χτιστεί θα πρέπει να δείτε μερικές οδηγίες στο τερματικό σας:
==> Assembling release..
==> Building release book_app:0.1.0 using environment dev
==> You have set dev_mode to true, skipping archival phase
Release successfully built!
To start the release you have built, you can use one of the following tasks:
# start a shell, like 'iex -S mix'
> _build/dev/rel/book_app/bin/book_app console
# start in the foreground, like 'mix run --no-halt'
> _build/dev/rel/book_app/bin/book_app foreground
# start in the background, must be stopped with the 'stop' command
> _build/dev/rel/book_app/bin/book_app start
If you started a release elsewhere, and wish to connect to it:
# connects a local shell to the running node
> _build/dev/rel/book_app/bin/book_app remote_console
# connects directly to the running node's console
> _build/dev/rel/book_app/bin/book_app attach
For a complete listing of commands and their use:
> _build/dev/rel/book_app/bin/book_app help
Για να τρέξετε την εφαρμογή γράψτε το παρακάτω στο τερματικό σας:
_build/dev/rel/MYAPP/bin/MYAPP foreground
Στη δική σας περίπτωση αντικαταστήστε τη λέξη MYAPP με το όνομα του project σας. Τώρα τρέχουμε τη μεταγλωττισμένη έκδοση της εφαρμογής μας!
Χρησιμοποιώντας τη Distillery με το Phoenix
Αν χρησιμοποιείτε τη distillery με το Phoenix υπάρχουν μερικά έξτρα βήματα που πρέπει να ακολουθήσετε ώστε να λειτουργήσει.
Αρχικά, πρέπει να επεξεργαστούμε το αρχείο config/prod.exs
.
Αλλάξτε την παρακάτω γραμμή από αυτό:
config :book_app, BookAppWeb.Endpoint,
load_from_system_env: true,
url: [host: "example.com", port: 80],
cache_static_manifest: "priv/static/cache_manifest.json"
σε αυτό:
config :book_app, BookAppWeb.Endpoint,
http: [port: {:system, "PORT"}],
url: [host: "localhost", port: {:system, "PORT"}],
cache_static_manifest: "priv/static/cache_manifest.json",
server: true,
root: ".",
version: Application.spec(:book_app, :vsn)
Κάναμε μερικά πράγματα εδώ:
-
server
- εκκινεί το τελικό σημείο http εφαρμογής της Cowboy στην εκκίνηση της εφαρμογής -
root
- ορίζει το γονικό φάκελο της εφαρμογής όπου όλα τα στατικά αρχεία θα εξυπηρετούνται -
version
- καταργεί την cache της εφαρμογής όταν η έκδοση της εφαρμογής αναβαθμιστεί γρήγορα. -
port
- αλλάζει τη θύρα ώστε να ορίζεται από μια μεταβλητή περιβάλλοντος ENV επιτρέποντάς μας να περάσουμε έναν αριθμό θύρας όταν εκκινούμε την εφαρμογή μας. Όταν ξεκινάμε την εφαρμογή, παρέχουμε τη θύρα τρέχοντας τηνPORT=4001 _build/prod/rel/book_app/bin/book_app foreground
Αν εκτελέσετε την παραπάνω εντολή, θα πρέπει να παρατηρήσετε ότι η εφαρμογή σας κράσαρε επειδή είναι αδύνατο να συνδεθεί στη βάση δεδομένων, από τη στιγμή που δεν υπάρχει βάση δεδομένων ακόμα.
Αυτό μπορεί να λυθεί τρέχοντας μια εντολή mix
του Ecto.
Στο τερματικό σας γράψτε τα παρακάτω:
MIX_ENV=prod mix ecto.create
Αυτή η εντολή θα δημιουργήσει τη βάση δεδομένων για εσάς.
Προσπαθήστε να ξανά τρέξετε την εφαρμογή σας και θα πρέπει να εκκινήσει επιτυχημένα.
Εν τούτοις, θα παρατηρήσετε ότι οι μετατροπές στη βάση δεδομένων σας δεν έχουν τρέξει.
Συνήθως, στο περιβάλλον ανάπτυξης τις τρέχουμε με τη χρήση της mix ecto.migrate
.
Για την έκδοση, θα πρέπει να τη ρυθμίσουμε ώστε να τρέχει τις μετατροπές μόνη της.
Τρέχοντας Μετατροπές στην Παραγωγή
Η Distillery μας παρέχει τη δυνατότητα να εκτελέσουμε κώδικα σε διαφορετικά σημεία του κύκλου λειτουργίας μιας έκδοσης. Αυτά τα σημεία είναι γνωστά σαν boot-hooks. Τα hooks που παρέχονται από την Distillery περιλαμβάνουν
- pre_start
- post_start
- pre/post_configure
- pre/post_stop
- pre/post_upgrade
Για τους δικούς μας σκοπούς, θα χρησιμοποιήσουμε την post_start
hook για να τρέξουμε τις μετατροπές της εφαρμογής μας στην παραγωγή.
Ας πάμε πρώτα να δημιουργήσουμε μια νέα εργασία που θα ονομάσουμε migrate
.
Μια εργασία έκδοσης είναι μια συνάρτηση ενότητας που θα καλέσουμε από το τερματικό μας η οποια περιαλμβάνει κώδικα ο οποίος είναι ξεχωριστός από τα εσωτερικά της ίδιας μας της εφαρμογής.
Είναι χρήσιμο για τις εργασίες ότι η εφαρμογή η ίδια δεν θα χρειάζεται να τρέχει.
defmodule BookAppWeb.ReleaseTasks do
def migrate do
{:ok, _} = Application.ensure_all_started(:book_app)
path = Application.app_dir(:book_app, "priv/repo/migrations")
Ecto.Migrator.run(BookApp.Repo, path, :up, all: true)
end
end
Σημείωση Είναι καλή πρακτική να βεβαιώνεστε ότι η εφαρμογή σας έχει εκκινήσει σωστά πριν να τρέξουν αυτές οι μετατροπές. Η Ecto.Migrator μας επιτρέπει να τρέξουμε τις μετατροπές μας με τη συνδεδεμένη βάση δεδομένων.
Στη συνέχεια, δημιουργήστε ένα νέο αρχείο - rel/hooks/post_start/migrate.sh
και προσθέστε τον παρακάτω κώδικα:
echo "Running migrations"
bin/book_app rpc "Elixir.BookApp.ReleaseTasks.migrate"
Για να τρέξει σωστά αυτός ο κώδικας, χρησιμοποιούμε την ενότητα rpc
της Erlang που μας δίνει πρόσβαση στην υπηρεσία Remote Procedure Call.
Βασικά, αυτό μας επιτρέπει να καλέσουμε μια συνάρτηση στον απομακρυσμένο κόμβο και να πάρουμε μια απάντηση.
Όταν τρέχει στην παραγωγή είναι πιθανό ότι η εφαρμογή μας θα τρέχει σε πολλούς διαφορετικούς κόμβους.
Τελικά, στο αρχείο μας rel/config.exs
θα προσθέσουμε το hook στη ρύθμιση της παραγωγής μας.
Ας αντικαταστήσουμε
environment :prod do
set include_erts: true
set include_src: false
set cookie: :"TkJuF,3nc4)OWPBpPxPDb6mz$>)>a>/v/,l2}W*sUFaz<)bG,v*3pPESE,`XOk{,"
set vm_args: "rel/vm.args"
end
με
environment :prod do
set include_erts: true
set include_src: false
set cookie: :"TkJuF,3nc4)OWPBpPxPDb6mz$>)>a>/v/,l2}W*sUFaz<)bG,v*3pPESE,`XOk{,"
set vm_args: "rel/vm.args"
set post_start_hooks: "rel/hooks/post_start"
end
Σημείωση - Αυτό το hook υπάρχει μόνο στην έκδοση παραγωγής αυτής της εφαρμογής. Αν χρησιμοποιούσαμε την προκαθορισμένη έκδοση ανάπτυξης δεν θα έτρεχε.
Χειροποίητες Εντολές
Όταν εργάζεστε με μια έκδοση, είναι πολύ πιθανό να μην έχετε πρόσβαση στις εντολές mix
καθώς το mix
μπορεί να μην έχει εγκατασταθεί στο μηχάνημα στο οποίο η έκδοση έχει γίνει deploy.
Μπορούμε να το λύσουμε αυτό με τις χειροποίητες εντολές.
Οι χειροποίητες εντολές είναι προεκτάσεις στο script εκκίνησης, και χρησιμοποιούνται με τον ίδιο τρόπο που χρησιμοποιείτε τις εντολές foreground ή remote_console, με άλλα λόγια, εμφανίζονται σαν να είναι μέρος του script εκκίνησης. Σαν τα hooks, έχουν πρόσβαση στις βοηθητικές εργασίες του script εκκίνησης και το περιβάλλον - Τεκμηρίωση Distillery
Οι εντολές είναι παρόμοιες με τις εργασίες έκδοσης στο ότι είναι συναρτήσεις αλλά διαφορετικές από αυτές στο ότι τρέχουν από το τερματικό αντί να τρέχουν από το script έκδοσης.
Τώρα που μπορούμε να τρέξουμε την εφαρμογή μας, μπορεί να θέλουμε να φορτώσουμε τη βάση δεδομένων μας με πληροφορίες μέσω μιας εντολής.
Αρχικά, προσθέστε μια μέθοδο στις εργασίες έκδοσής μας.
Στην ενότητα BookAppWeb.ReleaseTasks
, προσθέστε τα ακόλουθα:
def seed do
seed_path = Application.app_dir(:book_app_web, "priv/repo/seeds.exs")
Code.eval_file(seed_path)
end
Στη συνέχεια, δημιουργήστε ένα νέο αρχείο rel/commands/seed.sh
και προσθέστε τον παρακάτω κώδικα:
#!/bin/sh
release_ctl eval "BookAppWeb.ReleaseTasks.seed/0"
Σημείωση - Το releace_ctl
είναι ένα script τερματικού που παρέχεται από την Distillery για να μας επιτρέψει να εκτελούμε εντολές τοπικά ή σε ένα καθαρό κόμβο.
Αν χρειάζεστε να την τρέξετε σε έναν υπάρχον κόμβο μπορείτε να τρέξετε την release_remote_ctl()
Δείτε περισσότερα για τα shell_scripts από την Distillery εδώ
Τελικά, προσθέστε το παρακάτω στο αρχείο σας rel/config.exs
release :book_app do
...
set commands: [
seed: "rel/commands/seed.sh"
]
end
Επαναδημιουργήστε την έκδοση τρέχοντας την MIX_ENV=prod mix release
.
Όταν ολοκληρωθεί, θα μπορείτε να τρέξετε στο τερματικό σας την PORT=4001 _build/prod/rel/book_app/bin/book_app seed
.
Έπιασες λάθος ή θέλεις να συνεισφέρεις στο μάθημα; Επεξεργαστείτε αυτό το μάθημα στο GitHub!