介紹
Drive 是 AdonisJS 中的一個存儲抽像庫。 它提供了適用於所有存儲提供商的一致 API。
Drive有一個S3驅動來支持S3兼容的雲存儲,比如Vultr Object Storage。 本指南解釋瞭如何為 Vultr 對象存儲設置 AdonisJS Drive 並使用它來存儲和讀取文件。
以前的要求
在開始之前,您必須:
-
創建具有 sudo 權限的非 root 用戶
安裝 Node.js
AdonisJS 至少需要 Node.js 版本 14。 您可以使用節點版本管理器 (NVM) 安裝最新版本的 Node.js。
-
安裝 NVM:
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
-
斷開並重新連接您的 ssh 會話。
-
安裝 Node.js:
$ nvm install node
-
檢查 Node.js 的版本:
$ node -v v19.3.0
創建對象存儲
-
登錄Vultr 客戶門戶.
-
導航產品 -> 對象.
-
添加對象存儲. 選擇區域並為其添加標籤。
-
單擊您的項目存儲並轉到“立方體”選項卡。
-
創建一個存儲桶並為其命名。
-
請注意
Hostname
這Secret Key
這Access Key
和Bucket Name
.
創建新的 AdonisJS 應用程序
轉到主目錄。
$ cd ~
為您的應用程序創建一個新目錄。
$ mkdir app
前往 app
目錄並使用 npm init
領域。
$ cd app
$ npm init [email protected] website
-
選擇 Web 項目結構。
-
當提示配置 Webpack Encore 時選擇“y”。
構建您的應用程序 website
目錄。 對於其餘任務,您必須在 website
目錄。
$ cd website
安裝 Redis
本指南中的示例應用程序使用 Redis 來存儲圖像的文件名。
安裝 Redis:
$ sudo apt install redis-server
配置 Redis 持久化模式:
-
打開 Redis 配置文件:
$ sudo nano /etc/redis/redis.conf
-
改變
appendonly no
到appendonly yes
. -
保存文件並退出。
-
重新啟動 Redis。
$ sudo systemctl restart redis-server
安裝和配置 AdonisJS Redis 包:
$ npm i @adonisjs/redis
$ node ace configure @adonisjs/redis
打開 env.ts
程序:
$ nano env.ts
添加以下規則:
REDIS_CONNECTION: Env.schema.enum(['local'] as const),
REDIS_HOST: Env.schema.string({ format: 'host' }),
REDIS_PORT: Env.schema.number(),
REDIS_PASSWORD: Env.schema.string.optional(),
配置 AdonisJS 單元
AdonisJS Drive 有一個 S3 驅動程序來與 S3 兼容的雲存儲交互,比如 Vultr 對象存儲。
安裝和配置 S3 驅動程序:
$ npm i @adonisjs/drive-s3
$ node ace configure @adonisjs/drive-s3
打開 env.ts
程序:
$ nano env.ts
更新 DRIVE_DISK
規則:
DRIVE_DISK: Env.schema.enum(['local','s3'] as const),
添加以下規則:
S3_KEY: Env.schema.string(),
S3_SECRET: Env.schema.string(),
S3_BUCKET: Env.schema.string(),
S3_REGION: Env.schema.string(),
S3_ENDPOINT: Env.schema.string.optional(),
打開 config/drive.ts
程序:
$ nano config/drive.ts
在裡面添加S3配置 disks
目的:
s3: {
driver: 's3',
visibility: 'public',
key: Env.get('S3_KEY'),
secret: Env.get('S3_SECRET'),
region: Env.get('S3_REGION'),
bucket: Env.get('S3_BUCKET'),
endpoint: Env.get('S3_ENDPOINT'),
}
打開 .env
程序:
$ nano .env
更新 DRIVE_DISK
值 s3
:
DRIVE_DISK=s3
添加 Vultr 對象存儲憑證:
S3_KEY=
S3_SECRET=
S3_BUCKET=adonis-drive
S3_REGION=sgp1
S3_ENDPOINT=https://sgp1.vultrobjects.com
-
S3_KEY
是您訪問 Vultr 對象存儲的密鑰。 -
S3_SECRET
是您的秘密 Vultr 對象存儲密鑰。 -
S3_BUCKET` 是您的 Vultr 對象存儲桶的名稱。
-
S3_ENDPOINT
是您的 Vultr 對象存儲主機名。 -
S3_REGION
是您的 Vultr 對象存儲區域。
添加順風 CSS
本指南使用 Tailwind CSS 作為 CSS 框架。 通過 NPM 安裝 Tailwind CSS 及其依賴項:
$ npm install -D tailwindcss postcss autoprefixer postcss-loader
打開 webpack.config.js
程序:
$ nano webpack.config.js
啟用 PostCSS 加載器:
Encore.enablePostCssLoader()
創建並打開 Tailwind CSS 配置文件:
$ npx tailwindcss init -p
$ nano tailwind.config.js
將內容更改為:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./resources/**/*.edge",
"./resources/**/*.js",
],
theme: {
extend: {},
},
plugins: [],
}
打開 resources/css/app.css
並用 Tailwind CSS 指令替換內容:
@tailwind base;
@tailwind components;
@tailwind utilities;
添加 JavaScript
打開 resources/js/app.js
並添加以下腳本:
import '../css/app.css'
document.getElementById('fileImage').addEventListener('change',function(){
if( this.files.length > 0 ){
document.getElementById('uploadBtn').removeAttribute('disabled');
}
});
用戶選擇圖像文件後,腳本會啟用上傳按鈕。
創建視圖
創建一個 resources/views/gallery.edge
程序:
$ nano resources/views/gallery.edge
添加以下代碼:
<html>
<head>
<title>Gallery</title>
@entryPointStyles('app')
</head>
<body>
<div class="max-w-7xl m-auto">
<h1 class="text-3xl font-bold text-gray-900 text-center py-8 uppercase">Gallery</h1>
<form action="" method="post" enctype="multipart/form-data" class="flex flex-wrap text-center justify-center items-start p-4 rounded-lg">
<label class="block py-1">
<input id="fileImage" type="file" name="fileImage" class="block w-full text-sm text-slate-500 pr-6
file:cursor-pointer
file:mr-4 file:py-2 file:px-4
file:rounded-full file:border-0
file:text-sm file:font-semibold
file:bg-indigo-50 file:text-indigo-700
hover:file:bg-indigo-100
"/>
@if (flashMessages.has('errors.fileImage'))
<span class="block text-red-700 py-4 text-left">{{ flashMessages.get('errors.fileImage') }}</span>
@endif
</label>
<button id="uploadBtn" disabled class="rounded border border-transparent bg-indigo-600 px-6 py-2 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50" type="submit">
Upload Image
</button>
</form>
<div class="grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-3 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8 ">
@each(image in images)
<div>
<img class="rounded" src="">
</div>
@end
</div>
</div>
@entryPointScripts('app')
</body>
</html>
創建控制器
創建並打開 GalleryController.ts
程序:
$ node ace make:controller GalleryController -e
$ nano app/Controllers/Http/GalleryController.ts
在文件頂部導入庫和助手:
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Drive from '@ioc:Adonis/Core/Drive'
import Redis from '@ioc:Adonis/Addons/Redis'
import { string } from '@ioc:Adonis/Core/Helpers'
import { schema } from '@ioc:Adonis/Core/Validator'
創建 index
行動。 顯示上傳表單並列出 Vultr 對象存儲中的所有圖像。 獲取Redis鏡像文件名和調用 getUrl
從 Drive 庫中獲取每個圖像的 URL。
public async index({ view }: HttpContextContract) {
const galleryString = await Redis.get('gallery')
const gallery = (galleryString) ? JSON.parse(galleryString) : []
let images:string[] = []
for (const filename of gallery) {
const url = await Drive.getUrl(`gallery/${filename}`)
images.push(url)
}
return view.render('gallery', { images })
}
創建 upload
行動。 處理用戶上傳圖片的時間。 驗證文件,將文件名保存到 Redis,然後使用 moveToDisk
方法。
public async upload({ request, response }: HttpContextContract) {
const imageSchema = schema.create({
fileImage: schema.file({
extnames: ['jpg', 'png', 'gif']
}),
})
const payload = await request.validate({ schema: imageSchema })
const filename = `${string.generateRandom(32)}.${payload.fileImage.extname}`
if (payload.fileImage) {
await payload.fileImage.moveToDisk(", {
name: `gallery/${filename}`
}, 's3')
const galleryString = await Redis.get('gallery')
let gallery:string[] = []
if (galleryString) {
gallery = JSON.parse(galleryString)
}
gallery.push(filename)
await Redis.set('gallery', JSON.stringify(gallery))
}
return response.redirect().toPath("https://www.vultr.com/")
}
您需要保存並獲取 Redis 圖像文件名,因為 AdonisJS S3 驅動程序無法獲取存儲桶或文件夾中的文件列表。 您一次只能獲取一個文件。
以下為全文 GalleryController.ts
程序:
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Drive from '@ioc:Adonis/Core/Drive'
import Redis from '@ioc:Adonis/Addons/Redis'
import { string } from '@ioc:Adonis/Core/Helpers'
import { schema } from '@ioc:Adonis/Core/Validator'
export default class GalleryController {
public async index({ view }: HttpContextContract) {
const galleryString = await Redis.get('gallery')
const gallery = (galleryString) ? JSON.parse(galleryString) : []
let images:string[] = []
for (const filename of gallery) {
const url = await Drive.getUrl(`gallery/${filename}`)
images.push(url)
}
return view.render('gallery', { images })
}
public async upload({ request, response }: HttpContextContract) {
const imageSchema = schema.create({
fileImage: schema.file({
extnames: ['jpg', 'png', 'gif']
}),
})
const payload = await request.validate({ schema: imageSchema })
const filename = `${string.generateRandom(32)}.${payload.fileImage.extname}`
if (payload.fileImage) {
await payload.fileImage.moveToDisk(", {
name: `gallery/${filename}`
}, 's3')
const galleryString = await Redis.get('gallery')
let gallery:string[] = []
if (galleryString) {
gallery = JSON.parse(galleryString)
}
gallery.push(filename)
await Redis.set('gallery', JSON.stringify(gallery))
}
return response.redirect().toPath("https://www.vultr.com/")
}
}
添加路線
打開 start/routes.ts
程序:
$ nano start/routes.ts
添加以下代碼:
Route.get("https://www.vultr.com/", 'GalleryController.index')
Route.post("https://www.vultr.com/", 'GalleryController.upload')
測試應用
-
要測試您的應用程序,您必須禁用防火牆Ubuntu.
$ sudo ufw disable
您可以在構建用於生產的應用程序時重新啟用它。
-
啟動開發服務器:
$ node ace serve --encore-args="--host [VULTR_VPS_IP_ADDRESS]"
-
打開
https://[VULTR_VPS_IP_ADDRESS]:3333
在瀏覽器中。 -
您應該看到上傳表單。
-
上傳圖像。
-
檢查圖像是否出現在您的 Vultr 對象存儲和上傳表單下方的圖庫中。
-
按 CTRL+C 停止開發服務器。
使用多個對象存儲位置
Vultr 對象存儲在多個位置可用。 以下是 Vultr 支持的位置:
-
阿姆斯特丹:
ams1.vultrobjects.com
-
新澤西州:
ewr1.vultrobjects.com
-
矽谷:
sjc1.vultrobjects.com
-
新加坡:
sgp1.vultrobjects.com
您可以在 AdonisJS 應用程序中使用多個對象存儲位置來為您的文件添加冗餘。 為此,請為磁盤上的每個位置添加一個磁盤配置 config/drive.ts
程序。 AdonisJS Drive 中的驅動器代表一個特定的存儲位置和控制器。
創建新的對象存儲
-
要去Vultr 客戶門戶.
-
導航產品 -> 對象.
-
添加對象存儲. 選擇不同的地區,例如阿姆斯特丹。
-
在新的對象存儲中創建一個桶。
-
請注意
Hostname
這Secret Key
這Access Key
和Bucket Name
.
設置新磁盤
打開 config/drive.ts
程序:
$ nano config/drive.ts
在 S3 部分添加新的磁盤配置。 您可以將磁盤名稱設置為任何內容,例如, s3ams
. 為環境變量名稱添加後綴,以區別於第一個磁盤。
s3ams: {
driver: 's3',
visibility: 'public',
key: Env.get('S3_KEY_AMS'),
secret: Env.get('S3_SECRET_AMS'),
region: Env.get('S3_REGION_AMS'),
bucket: Env.get('S3_BUCKET_AMS'),
endpoint: Env.get('S3_ENDPOINT_AMS'),
},
打開 .env
程序:
$ nano .env
添加您的對象存儲憑據:
S3_KEY_AMS=
S3_SECRET_AMS=
S3_BUCKET_AMS=adonis-drive
S3_REGION_AMS=ams1
S3_ENDPOINT_AMS=https://ams1.vultrobjects.com
-
S3_KEY_AMS
是您訪問 Vultr 對象存儲的密鑰。 -
S3_SECRET_AMS
是您的秘密 Vultr 對象存儲密鑰。 -
S3_BUCKET_AMS
是它的 Vultr 對象存儲庫名稱。 -
S3_ENDPOINT_AMS
是您的 Vultr 對象存儲主機名。 -
S3_REGION_AMS
是您的 Vultr 對象存儲區域。
打開 env.ts
程序:
$ nano env.ts
添加 s3ams
磁盤名稱 DRIVE_DISK
枚舉值:
DRIVE_DISK: Env.schema.enum(['local','s3','s3ams'] as const),
添加驗證規則 s3ams
磁盤環境變量:
S3_KEY_AMS: Env.schema.string(),
S3_SECRET_AMS: Env.schema.string(),
S3_BUCKET_AMS: Env.schema.string(),
S3_REGION_AMS: Env.schema.string(),
S3_ENDPOINT_AMS: Env.schema.string.optional(),
保存文件並關閉。
更新驅動程序
打開 GalleryController.ts
程序:
$ nano app/Controllers/Http/GalleryController.ts
在裡面 upload
action,找到負責將文件上傳到對象存儲的代碼。
await payload.fileImage.moveToDisk(", {
name: `gallery/${filename}`
}, 's3')
複製代碼並將磁盤重命名為 s3ams
.
await payload.fileImage.moveToDisk(", {
name: `gallery/${filename}`
}, 's3')
await payload.fileImage.moveToDisk(", {
name: `gallery/${filename}`
}, 's3ams')
將文件上傳到兩個對象存儲位置。
設置默認磁盤
他 index
中的動作 GalleryController.ts
使用默認磁盤獲取圖像 url。 要更改默認磁盤,請打開 .env
程序:
$ nano .env
更新 DRIVE_DISK
您想要的磁盤的值:
DRIVE_DISK=s3ams
保存文件並關閉。
試用應用程序
-
啟動開發服務器:
$ node ace serve --encore-args="--host [VULTR_VPS_IP_ADDRESS]"
-
打開
https://[VULTR_VPS_IP_ADDRESS]:3333
在瀏覽器中。 -
上傳圖像。
-
檢查圖像是否同時出現在 Vultr 對象存儲位置和上傳表單下方的圖庫中。
-
按 CTRL+C 停止開發服務器。
為生產而建
AdonisJS 應用程序使用 TypeScript。 您必須先將其編譯為 JavaScript,然後才能在生產環境中運行它。
前往 website
文件:
$ cd ~/app/website
編譯它使用 build
領域。 結果在 build
文件。
$ node ace build --production --ignore-ts-errors
複製 .env
文件到 build
文件夾並打開它:
$ cp .env build/.env
$ nano build/.env
選擇 NODE_ENV
中的變量 .env
歸檔到 production
:
NODE_ENV=production
在上安裝僅限生產的依賴項 build
文件:
$ cd build
$ npm ci --production
使用 PM2 在生產環境中運行應用程序
PM2 是守護進程管理器。 它可以幫助您在生產環境中運行和管理 AdonisJS 應用程序。
安裝最新的 PM2 包:
$ npm install [email protected] -g
創建 PM2 生態系統文件來管理您的應用程序:
$ cd ~/app
$ nano ecosystem.config.js
將這些設置添加到 ecosystem.config.js
程序:
module.exports = {
apps : [
{
name : "website",
script : "./website/build/server.js"
}
]
}
-
將您的應用程序的名稱放在
name
範圍。 -
放生產路線
script.js
在裡面script
範圍。
運行你的應用程序:
$ pm2 start ecosystem.config.js
$ pm2 list
此時,您的應用程序正在運行。 但是,這個過程還不是持久的。 這意味著您必須在重新啟動服務器後再次手動運行您的應用程序。
要運行持久應用程序,您必須為 PM2 生成啟動腳本。
$ pm2 startup
複製並粘貼終端中顯示的命令:
$ sudo env PATH=$PATH:/home/ubuntu/.nvm/versions/node/v19.3.0/bin /home/ubuntu/.nvm/versions/node/v19.3.0/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
使用此命令保存您的 PM2 應用程序列表:
$ pm2 save
Nginx 回退代理
您必須配置 Nginx 回退代理以將您的域連接到您的應用程序。 你把你的應用程序放在 Nginx 網絡服務器後面。 它接受所有傳入的請求並將它們轉發給您的應用程序。
添加 ondrej 存儲庫以獲取最新版本的 Nginx。
$ sudo add-apt-repository -y ppa:ondrej/nginx-mainline
$ sudo apt update
安裝 Nginx:
$ sudo apt install nginx
禁用 Nginx 默認設置:
$ sudo unlink /etc/nginx/sites-enabled/default
新建一個 Nginx 配置文件:
$ sudo nano /etc/nginx/sites-available/website
添加以下設置。 確保更改域名 googlesyndication.com
到您的域。 保存文件並關閉。
server {
listen 80;
server_name googlesyndication.com;
location / {
proxy_pass https://localhost:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
}
啟用 Nginx 配置:
$ sudo ln -s /etc/nginx/sites-available/website /etc/nginx/sites-enabled/
測試您的配置是否存在語法錯誤:
$ sudo nginx -t
如果沒有錯誤,您可以重新加載 Nginx 進程:
$ sudo systemctl reload nginx
將您的域名指向您的 Vultr VPS IP 地址。
配置防火牆
配置防火牆以允許 ssh 端口:
$ sudo ufw allow 'OpenSSH'
允許 HTTP 和 HTTPS 端口:
$ sudo ufw allow 'Nginx Full'
啟用防火牆:
$ sudo ufw enable
查看防火牆狀態:
$ sudo ufw status
使用 Let's Encrypt SSL 證書保護應用程序
Let's Encrypt 為您的網站提供免費的 SSL 證書。 要生成證書,您必須使用 Certbot 軟件工具。
安裝 Certbot:
$ sudo snap install core; sudo snap refresh core
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
生成 SSL 證書:
$ sudo certbot --nginx
在瀏覽器中訪問您的域並確認您有 HTTPS 連接。
Let's Encrypt 證書將在 90 天后過期。 Certbot 將更新命令添加到 systemd 或 Cron Job 計時器,以在證書過期之前自動更新證書。 您可以使用以下命令驗證它:
$ systemctl list-timers | grep 'certbot|ACTIVATES'
結論
本指南展示了在具有一個或多個對象存儲位置的 AdonisJS 中使用 Vultr 對象存儲的示例,包括讓您的應用程序做好生產準備的步驟。
其他閱讀
Vultr 對象存儲。
使用 PM2 和 Nginx 部署多個 Adonis.js 應用程序。
文章標題 名稱(可選) 電子郵件(可選) 描述
發送建議