Utilizzo di LiteFS con Bun su Fly.io
Poiché né Bun né LiteFS sono ancora consigliati per la produzione, ho deciso che era ovviamente una buona idea implementare la " loro sinergia " su fly.io
“ …ma perché? ” … beh, ecco perché!
In cosa Bun è molto bravo:
- è molto veloce al bootstrapping, il che lo rende ideale per avviamenti lambda a caldo e a freddo, insieme a container basati su docker
- è molto veloce nel servire, rendendolo un runtime ideale per tutto ciò che riguarda il cloud (in più è compatibile con TS/JSX senza bisogno di strumenti aggiuntivi!)
- è il runtime JS/TS più veloce là fuori quando si tratta di SQLite … in effetti, bun ha SQLite costruito e associato direttamente nel suo core in modo che possa facilmente competere con qualsiasi altro PL tipizzato con collegamenti SQLite
- fornisce gratuitamente un intero GB di filesystem montato che può ospitare da 1 a molti database SQLite (1 GB è un sacco di testo!!!)
- può replicare e sincronizzare i database in tutto il mondo quando/se necessario (paga in base al consumo o è necessario un piano adeguato, ma possiamo iniziare gratuitamente)
- fly.io consente qualsiasi immagine Docker, in modo da poter testare sia localmente che implementare in produzione con facilità
L'albero del progetto
- la cartella litefs viene utilizzata al posto del vero percorso litefs montato ogni volta che stiamo testando localmente e/o non in produzione. Digitiamo semplicemente
mkdir litefsla directory che vorremmo utilizzare per testare questa configurazione tramitebun run start(onpm startse il nodo è presente e il bun è disponibile) - il
.dockerignorefile contiene tutte le cose possibili che non dovremmo inviare alla finestra mobile - contiene
Dockerfilel' immagine docker ufficiale basata su alpine del panino (è ~ 100 MB in totale ) più alcuni comandi per eseguire il bootstrap del server - contiene
fly.tomlun mix di come sarebbero gli esempi preparati di scaffolding Nodejs e LiteFS - il
litefs.jsfile gestisce la connessione al database come punto di ingresso del modulo univoco, oltre ad alcune utilità basate su template letterali - the
package.jsonviene utilizzato per fornire unstartcomando e dipendenze facoltative - il
serve.jsfile avvia semplicemente una demo del server che mostra un po 'di benvenuto e tutte le righe nel database SQLite fittizio/di esempio
Prima di iniziare
Il modo più semplice per impalcare un progetto fly.io è usare fly apps create, che genererà un univoco YOUR_FLY_APP_NAME(vedi fly.toml più avanti) e ti darà indicazioni sulle regioni che puoi utilizzare per distribuire la tua app, quindi devi creare il tuo LiteFS volume , utilizzando la posizione gratuita consentita più vicina.
PS usa l'esempio LiteFS se non sai da dove o come iniziare, poiché è stato aggiornato di recente e funziona davvero fuori dagli schemi come iniziato (ma usa GO, che "può andare" ( dehihi ) subito dopo
Dopo averlo fatto, ogni file nell'elenco è obbligatorio e questo è ciò che ho come contenuto di ogni file:
.dockerignore
.git
litefs
node_modules
.dockerignore
bun.lockb
Dockerfile
fly.toml
### GLOBALS ###
ARG GLIBC_RELEASE=2.34-r0
### GET ###
FROM alpine:latest as get
# prepare environment
WORKDIR /tmp
RUN apk --no-cache add unzip
# get bun
ADD https://github.com/oven-sh/bun/releases/latest/download/bun-linux-x64.zip bun-linux-x64.zip
RUN unzip bun-linux-x64.zip
# get glibc
ARG GLIBC_RELEASE
RUN wget https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_RELEASE}/glibc-${GLIBC_RELEASE}.apk
### IMAGE ###
FROM alpine:latest
# install bun
COPY --from=get /tmp/bun-linux-x64/bun /usr/local/bin
# prepare glibc
ARG GLIBC_RELEASE
COPY --from=get /tmp/sgerrand.rsa.pub /etc/apk/keys
COPY --from=get /tmp/glibc-${GLIBC_RELEASE}.apk /tmp
# install glibc
RUN apk --no-cache --force-overwrite add /tmp/glibc-${GLIBC_RELEASE}.apk && \
# cleanup
rm /etc/apk/keys/sgerrand.rsa.pub && \
rm /tmp/glibc-${GLIBC_RELEASE}.apk && \
# smoke test
bun --version
#######################################################################
RUN mkdir /app
WORKDIR /app
# NPM will not install any package listed in "devDependencies" when NODE_ENV is set to "production",
# to install all modules: "npm install --production=false".
# Ref: https://docs.npmjs.com/cli/v9/commands/npm-install#description
ENV NODE_ENV production
COPY . .
RUN bun install
LABEL fly_launch_runtime="bun"
WORKDIR /app
ENV NODE_ENV production
CMD [ "bun", "run", "start" ]
app = "YOUR_FLY_APP_NAME"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[env]
PORT = "8080"
[experimental]
auto_rollback = true
enable_consul = true
[mounts]
source = "litefs"
destination = "/var/lib/litefs"
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
import {existsSync} from 'node:fs';
import {join} from 'node:path';
import {Database} from 'bun:sqlite';
import createSQLiteTags from 'better-tags';
// use mounted point on production, use local folder otherwise
const litefs = join(
process.env.NODE_ENV === 'production' ? '/var/lib' : '.',
'litefs'
);
// if litefs folder doesn't exist get out!
if (!existsSync(litefs)) {
console.error('Unable to reach', litefs);
process.exit(1);
}
// shared db + template literals based utilities
const {db, get, all, values, exec, run, entries, transaction} =
createSQLiteTags(new Database(join(litefs, 'db')));
export {db, get, all, values, exec, run, entries, transaction};
///////////////////////////////////////////////////////////////
// FOR DEMO SAKE ONLY - EXECUTED ON EACH DEPLOY
///////////////////////////////////////////////////////////////
// some table schema
exec`
CREATE TABLE IF NOT EXISTS persons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
phone TEXT NOT NULL,
company TEXT NOT NULL
)
`;
// some table entry
exec`
INSERT INTO persons
(name, phone, company)
VALUES
(${
crypto.randomUUID()
}, ${
('+' + (Date.now() * Math.random())).replace(/[^+\d]/, ' ')
}, 'fly.io')
`;
{
"name": "flying-bun",
"description": "A Bun & LiteFS love affair",
"type": "module",
"scripts": {
"start": "bun serve.js"
},
"dependencies": {
"better-tags": "^0.1.2"
}
}
import {serve} from 'bun';
// grab the db or some utility
import {all} from './litefs.js';
// grab the port and start the server
const port = process.env.PORT || 3000;
serve({
fetch(request) {
const greeting = "<h1>Hello From Bun on Fly!</h1>";
const results = `<pre>${JSON.stringify(
all`SELECT * FROM persons ORDER BY id DESC`, null, '\t')
}</pre>`;
return new Response(greeting + '<br>' + results, {
headers: {'Content-Type': 'text/html; charset=utf-8'}
});
},
error(error) {
return new Response("Uh oh!!\n" + error.toString(), { status: 500 });
},
port
});
console.log(`Flying Bun app listening on port ${port}!`);
È praticamente tutto, una volta che hai un nome app univoco, una directory montata LiteFS che puoi raggiungere e il codice fornito, puoi bun run startlocalmente, magari dopo a bun installo an npm install, e infine fly deployvedere il tuo " ciao panino " in esecuzione dal cloud
Se tutto è andato bene, dovresti essere in grado di raggiungere https://YOUR_FLY_APP_NAME.fly.deve vedere almeno un record mostrato nella pagina.
Qualche metrica
L'immagine alpina di base con solo bun e glibc sopra, oltre ai file di progetto, non dovrebbe consumare più di 40 MB di RAM sui 232 MB consentiti, ma la parte interessante di fly.io è che possiamo sempre optare per un pagamento man mano che procedi, pianifica di ridimensionare CPU, RAM, database replicati o aumentare anche la dimensione del DB montato con facilità, ogni volta che riusciremo a raggiungere 1 GB di limite di dimensione del file LiteFS montato. Una guida dettagliata su come gestire i volumi di volo può essere trovata qui .
E questo è tutto gente
Congratulazioni! Hai imparato come distribuire il tuo prossimo progetto bun sul cloud e con una soluzione di database gratuita che ospiterà fino a un GB gratuitamente e non limitato a un singolo DB, in modo che sia anche possibile separare le preoccupazioni per DB (1 per Geolocalizzazione IP, 1 per il testo del blog, 1 per gli utenti da amministrare, 1 per...)
La parte più sottovalutata di SQLite come database, oltre ad essere il database incorporato più interessante che esista sulla terra, è che nessun utente e password segreti potrebbero mai trapelare, e anche i filesystem montati su fly.io sono crittografati in modo che un'intera classe di problemi di sicurezza viene automaticamente rimosso da tutte le equazioni e responsabilità per le persone che condividono il codice, come ho appena fatto qui

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































