Gli script creati usando Node.js possono essere lanciati direttamente dal terminale senza particolari accorgimenti. Quando invece creiamo delle applicazioni con Node.js abbiamo bisogno di eseguirle in modo automatico, riproducibile e semplice. In questo articolo vedremo alcuni dei modi possibili per farlo.

Il Dockerfile di base da usare con Node.js

Uno degli strumenti più utilizzati per effettuare il deploy di applicazioni è Docker perché ci permette di creare un artefatto (l’immagine Docker) che contiene tutti il necessario per l’esecuzione dell’applicazione, riducendo al minimo i possibili problemi derivanti dall’esecuzione su macchine diverse.

Chi non conosce già Docker può iniziare partendo dalle guide introduttive ufficiali (in inglese) oppure al libro Docker (Apogeo) (in italiano).

Su Docker Hub è disponibile l’immagine Node.js ufficiale che contiene i binari node, npm e npx, e che possiamo usare per creare l’immagine della nostra applicazione. Il Dockerfile base da usare per effettuare la build di un’applicazione Node.js (il download delle dipendenze), e ottenere così l’immagine finale, è quello mostrato di seguito.

# La versione da usare
FROM node:20-alpine

# Imposta la variabile d'ambiente NODE_ENV al valore "production" - vedi paragrafo sotto
ENV NODE_ENV production

# Cartella del container in cui sarà copiata e eseguita l'applicazione
WORKDIR /usr/src/app

# Scarica le dipendenze sfruttando la cache di Docker per velocizzare le build successive
# I file package.json e package-lock.json sono montati e non copiati nell'immagine finale
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

# Esegue l'applicazione usando l'utente node (non root)
USER node

# Copia i sorgenti nell'immagine
COPY . .

# Espone la porta usata dall'applicazione
EXPOSE 3000

# Avvia node eseguendo il file indicato
CMD node src/index.js

Un esempio reale

Per creare un’immagine con la prima versione dell’applicazione APOD sviluppata nel libro il codice del Dockerfile è il seguente.

FROM node:20-alpine

ENV NODE_ENV production

WORKDIR /usr/src/app

RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

USER node

COPY . .

EXPOSE 3000

CMD node app_v9.mjs

Una volta creato e salvato il file nella stessa cartella del progetto sarà sufficiente eseguire docker build -t 01-apod:latest . per ottenere l’immagine del progetto. Usando l’immagine sarà poi possibile avviare l’applicazione creando un container con il comando docker run -p 3000:3000 01-apod e accedere al servizio tramite http://127.0.0.1:3000.

Il comando usato per avviare il container farà in modo che il processo in esecuzione rimanga attivo sul terminale usato e che tutti i log emessi vengano mostrati. Per eseguire il server in background è necessario usare l'opzione -d (detached) di docker e poi, per vederne i log, il comando docker logs.