Let's Go Further استقرار و میزبانی › استقرار و اجرای مهاجرت‌ها
قبلی · فهرست مطالب · بعدی
فصل ۲۰.۳.

استقرار و اجرای مهاجرت‌ها

در این مرحله droplet ما با تمام نرم‌افزارها و حساب‌های کاربری مورد نیاز تنظیم شده است، پس بیایید به استقرار و اجرای برنامه API خود بپردازیم.

در سطح بسیار بالا، فرآیند استقرار ما از سه عمل تشکیل شده است:

  1. کپی کردن فایل باینری برنامه و فایل‌های مهاجرت SQL به droplet.
  2. اجرای مهاجرت‌ها روی دیتابیس PostgreSQL در droplet.
  3. شروع اجرای فایل باینری برنامه به عنوان یک background service.

فعلاً فقط روی مراحل ۱ و ۲ تمرکز می‌کنیم و اجرای برنامه به عنوان یک background service را در فصل بعدی بررسی خواهیم کرد.

بیایید با ایجاد یک rule جدید make production/deploy/api در makefile خود شروع کنیم، که از آن برای اجرای خودکار این دو مرحله استفاده خواهیم کرد. به این صورت:

فایل: Makefile
...

# ==================================================================================== #
# PRODUCTION
# ==================================================================================== #

production_host_ip = "161.35.71.158"

## production/connect: connect to the production server
.PHONY: production/connect
production/connect:
	ssh greenlight@${production_host_ip}

## production/deploy/api: deploy the api to production
.PHONY: production/deploy/api
production/deploy/api:
	rsync -P ./bin/linux_amd64/api greenlight@${production_host_ip}:~
	rsync -rP --delete ./migrations greenlight@${production_host_ip}:~
	ssh -t greenlight@${production_host_ip} 'migrate -path ~/migrations -database $$GREENLIGHT_DB_DSN up'

بیایید به سرعت بررسی کنیم این rule جدید چه کاری انجام می‌دهد.

اول، دستور rsync را اجرا می‌کند تا فایل باینری اجرایی ./bin/linux_amd64/api (نسخه‌ای که به طور خاص برای Linux کامپایل شده) و پوشه ./migrations را به دایرکتوری خانه کاربر greenlight در droplet کپی کند.

سپس از دستور ssh با پرچم -t استفاده می‌کند تا این مهاجرت‌های دیتابیس را در droplet به عنوان کاربر greenlight با دستور زیر اجرا کند:

'migrate -path ~/migrations -database $$GREENLIGHT_DB_DSN up'

از آنجا که کاراکتر $ در makefile‌ها معنای خاصی دارد، ما آن را با اضافه کردن یک کاراکتر دالار اضافی مانند $$ escape می‌کنیم. این یعنی دستوری که واقعاً در droplet اجرا می‌شود 'migrate -path ~/migrations -database $GREENLIGHT_DB_DSN up' خواهد بود و در نتیجه مهاجرت با استفاده از متغیر محیطی droplet GREENLIGHT_DB_DSN اجرا می‌شود.

همچنین مهم است که توجه کنید ما این دستور را با کوتیشن تکی احاطه کرده‌ایم. اگر از کوتیشن دوگانه استفاده می‌کردیم، یک interpreted string می‌بود و نیاز به استفاده از یک کاراکتر escape اضافی \ داشتیم به این صورت:

"migrate -path ~/migrations -database \$$GREENLIGHT_DB_DSN up"

خوب، بیایید آن را امتحان کنیم!

دستور make production/deploy/api را که تازه ایجاد کردیم اجرا کنید. باید ببینید که تمام فایل‌ها با موفقیت کپی می‌شوند (این کار بسته به سرعت اتصال شما ممکن است یک یا دو دقیقه طول بکشد) و سپس مهاجرت‌ها روی دیتابیس شما اعمال می‌شوند. به این صورت:

$ make production/deploy/api 
rsync -rP --delete ./bin/linux_amd64/api greenlight@"161.35.71.158":~
api
      7,618,560 100%  119.34kB/s    0:01:02 (xfr#1, to-chk=13/14)
rsync -rP --delete ./migrations greenlight@"161.35.71.158":~
sending incremental file list
migrations/
migrations/000001_create_movies_table.down.sql
             28 100%   27.34kB/s    0:00:00 (xfr#2, to-chk=11/14)
migrations/000001_create_movies_table.up.sql
            286 100%  279.30kB/s    0:00:00 (xfr#3, to-chk=10/14)
migrations/000002_add_movies_check_constraints.down.sql
            198 100%  193.36kB/s    0:00:00 (xfr#4, to-chk=9/14)
migrations/000002_add_movies_check_constraints.up.sql
            289 100%  282.23kB/s    0:00:00 (xfr#5, to-chk=8/14)
migrations/000003_add_movies_indexes.down.sql
             78 100%   76.17kB/s    0:00:00 (xfr#6, to-chk=7/14)
migrations/000003_add_movies_indexes.up.sql
            170 100%  166.02kB/s    0:00:00 (xfr#7, to-chk=6/14)
migrations/000004_create_users_table.down.sql
             27 100%   26.37kB/s    0:00:00 (xfr#8, to-chk=5/14)
migrations/000004_create_users_table.up.sql
            294 100%  287.11kB/s    0:00:00 (xfr#9, to-chk=4/14)
migrations/000005_create_tokens_table.down.sql
             28 100%   27.34kB/s    0:00:00 (xfr#10, to-chk=3/14)
migrations/000005_create_tokens_table.up.sql
            203 100%   99.12kB/s    0:00:00 (xfr#11, to-chk=2/14)
migrations/000006_add_permissions.down.sql
             73 100%   35.64kB/s    0:00:00 (xfr#12, to-chk=1/14)
migrations/000006_add_permissions.up.sql
            452 100%  220.70kB/s    0:00:00 (xfr#13, to-chk=0/14)
ssh -t greenlight@"161.35.71.158" 'migrate -path ~/migrations -database $GREENLIGHT_DB_DSN up'
1/u create_movies_table (11.782733ms)
2/u add_movies_check_constraints (23.109006ms)
3/u add_movies_indexes (30.61223ms)
4/u create_users_table (39.890662ms)
5/u create_tokens_table (48.659641ms)
6/u add_permissions (58.23243ms)
Connection to 161.35.71.158 closed.

بیایید به سرعت به droplet خود وصل شویم و مطمئن شویم که همه چیز به درستی کار کرده است.

$ make production/connect 
ssh greenlight@'161.35.71.158'
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-65-generic x86_64)

...
greenlight@greenlight-production:~$ ls -R
.:
api  migrations

./migrations:
000001_create_movies_table.down.sql
000001_create_movies_table.up.sql
000002_add_movies_check_constraints.down.sql
000002_add_movies_check_constraints.up.sql
000003_add_movies_indexes.down.sql
000003_add_movies_indexes.up.sql
000004_create_users_table.down.sql
000004_create_users_table.up.sql
000005_create_tokens_table.down.sql
000005_create_tokens_table.up.sql
000006_add_permissions.down.sql
000006_add_permissions.up.sql

تا اینجا همه چیز خوب پیش رفته است. می‌توانیم ببینیم که دایرکتوری خانه کاربر greenlight ما شامل فایل باینری اجرایی api و یک پوشه حاوی فایل‌های مهاجرت است.

بیایید همچنین با استفاده از psql به دیتابیس وصل شویم و با استفاده از meta command \dt بررسی کنیم که جداول ایجاد شده‌اند. خروجی شما باید مشابه این باشد:

greenlight@greenlight-production:~$ psql $GREENLIGHT_DB_DSN 
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.

greenlight=> \dt
                List of relations
 Schema |       Name        | Type  |   Owner    
--------+-------------------+-------+------------
 public | movies            | table | greenlight
 public | permissions       | table | greenlight
 public | schema_migrations | table | greenlight
 public | tokens            | table | greenlight
 public | users             | table | greenlight
 public | users_permissions | table | greenlight
(6 rows)

اجرای API

در حالی که به droplet متصل هستیم، بیایید فایل باینری اجرایی api را امتحان کنیم. نمی‌توانیم روی پورت 80 گوش دهیم زیرا Caddy در حال حاضر از آن استفاده می‌کند، بنابراین به جای آن روی پورت بدون محدودیت 4000 گوش خواهیم داد.

اگر همراه ما بوده‌اید، پورت 4000 در droplet شما در حال حاضر باید توسط قوانین firewall مسدود شده باشد، بنابراین نیاز داریم آن را به طور موقت برای اجازه دادن به درخواست‌های ورودی باز کنیم. این کار را به این صورت انجام دهید:

greenlight@greenlight-production:~$ sudo ufw allow 4000/tcp
Rule added
Rule added (v6)

و سپس API را با دستور زیر شروع کنید:

greenlight@greenlight-production:~$ ./api -port=4000 -db-dsn=$GREENLIGHT_DB_DSN -env=production
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established"
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development

در این مرحله باید بتوانید http://<your_droplet_ip>:4000/v1/healthcheck را در مرورگر خود باز کنید و پاسخ موفقی از healthcheck endpoint دریافت کنید، مشابه این:

20.03-01.png

در نهایت، به پنل SSH خود برگردید و Ctrl+C را فشار دهید تا اجرای API در droplet متوقف شود. باید ببینید که به طور صحیح خاموش می‌شود به این صورت:

greenlight@greenlight-production:~$ /home/greenlight/api -port=4000 -db-dsn=$GREENLIGHT_DB_DSN -env=production
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established"
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development
^Ctime=2023-09-10T10:59:14.722+02:00 level=INFO msg="shutting down server" signal=terminated
time=2023-09-10T10:59:14.722+02:00 level=INFO msg="completing background tasks" addr=:4000
time=2023-09-10T10:59:18.722+02:00 level=INFO msg="stopped server" addr=:4000