node.js - Σφάλμα μνήμης TypeScript που δεν τερματίζει το Docker build
Πρόσφατα παρατήρησα ότι μια διαδικασία κατασκευής TypeScript σε Docker απέτυχε λόγω ανεπαρκούς μνήμης σε ένα περιβάλλον με χαμηλή RAM, αλλά η κατασκευή Docker συνέχισε μετά το σφάλμα έλλειψης μνήμης του Node στο 5/6 και προχώρησε στο τελευταίο βήμα, εξέρχεται μόνο όταν η εκτέλεση του Node (6/6) απέτυχε λόγω έλλειψης μεταγλωττισμένων αρχείων. Η αναπαραγωγή είναι περίπλοκη λόγω πολλαπλών περιβαλλόντων με περιορισμένη μνήμη - δείτε το Reproduce This στο τέλος για αρχεία.
docker build .
Sending build context to Docker daemon 55.17MB
Step 1/6 : FROM node:14.14-alpine3.12
---> b21353984bd1
Step 2/6 : WORKDIR /app
---> Using cache
---> fe13e46eb756
Step 3/6 : COPY . ./
---> f14ece6934d0
Step 4/6 : RUN npm install
---> Running in 558126753ba5
npm WARN my_container@ No repository field.
npm WARN my_container@ No license field.
added 2 packages from 44 contributors and audited 16 packages in 2.476s
found 0 vulnerabilities
Removing intermediate container 558126753ba5
---> 188ed518072e
Step 5/6 : RUN npm run build
---> Running in ecd6da9c1565
> my_container@ build /app
> tsc index.ts
<--- Last few GCs --->
[16:0x55696cd7c300] 21705 ms: Mark-sweep (reduce) 491.3 (494.4) -> 490.6 (495.4) MB, 738.9 / 0.0 ms (+ 0.1 ms in 16 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 797 ms) (average mu = 0.129, current mu = 0.073) all[16:0x55696cd7c300] 22864 ms: Mark-sweep (reduce) 491.7 (494.4) -> 490.9 (495.6) MB, 1063.0 / 0.0 ms (+ 0.1 ms in 16 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1159 ms) (average mu = 0.102, current mu = 0.083) a
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Removing intermediate container ecd6da9c1565
---> 51bc50e86758
Step 6/6 : RUN npm start
---> Running in cdaed5cbb63e
> my_container@ start /app
> node index.js
internal/modules/cjs/loader.js:883
throw err;
^
Error: Cannot find module '/app/index.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! my_container@ start: `node index.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the my_container@ start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-10-22T21_20_00_360Z-debug.log
The command '/bin/sh -c npm start' returned a non-zero code: 1
Με βάση μια παρόμοια ερώτηση, φαίνεται ότι το πρόβλημα είναι ότι το Docker δεν λαμβάνει έναν κωδικό εξόδου διαφορετικό από το μηδέν από το σφάλμα έλλειψης μνήμης. Στην πραγματικότητα, μπορώ να αλλάξω το tsc index.ts στο σενάριο κατασκευής σε tsc index.ts && exit 0 και να προκαλέσω το σενάριο κατασκευής NPM να τερματιστεί με έναν εντελώς νέο κωδικό σφάλματος που τερματίζει το Docker:
Step 5/6 : RUN npm run build
---> Running in b4f49b1eb460
> my_container@ build /app
> tsc index.ts && exit 0
<--- Last few GCs --->
[17:0x559d4266b300] 21406 ms: Mark-sweep (reduce) 490.7 (493.6) -> 490.0 (494.9) MB, 733.1 / 0.0 ms (average mu = 0.173, current mu = 0.065) allocation failure scavenge might not succeed
[17:0x559d4266b300] 22322 ms: Mark-sweep (reduce) 491.1 (493.9) -> 490.4 (495.4) MB, 721.2 / 0.0 ms (+ 40.0 ms in 9 steps since start of marking, biggest step 17.1 ms, walltime since start of marking 898 ms) (average mu = 0.171, current mu = 0.169) al
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Aborted (core dumped)
npm ERR! code ELIFECYCLE
npm ERR! errno 134
npm ERR! my_container@ build: `tsc index.ts && exit 0`
npm ERR! Exit status 134
npm ERR!
npm ERR! Failed at the my_container@ build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-10-22T21_33_57_785Z-debug.log
The command '/bin/sh -c npm run build' returned a non-zero code: 134
Νόμιζα ότι τα scripts του NPM υποτίθεται ότι επιστρέφουν την έξοδο της τελευταίας εντολής, και πράγματι συμβαίνει αυτό όσο η εντολή node ακολουθείται από ένα && που φαινομενικά παίρνει το σφάλμα με έναν τρόπο που ο εκτελεστής του npm δεν το κάνει. Μπορεί κανείς να εξηγήσει γιατί το σφάλμα έλλειψης μνήμης του Node δεν μεταδίδεται στο Docker, είτε λόγω μιας ιδιαιτερότητας της έλλειψης μνήμης στο TypeScript είτε λόγω κάποιου λάθους στην αρχική μου ρύθμιση;
Αναπαράγω Αυτό
Μπορείτε να αναπαράγετε αυτό σε ένα περιβάλλον με μόλις ~500MB ελεύθερης RAM (δυνατό σε 1GB αν υπάρχουν αρκετές άλλες διεργασίες σε εκτέλεση) με τα ακόλουθα τέσσερα αρχεία, επεκτείνοντας μια δημοσίευση από τον Swatinem για τη βελτιστοποίηση της χρήσης μνήμης στο TypeScript:
package.json: (αλλάξτε το script build για να δείτε το αποτέλεσμα του tsc index.ts && exit 0)
{
"name": "my_container",
"description": "My Container",
"scripts": {
"build": "tsc index.ts",
"start": "node index.js"
},
"dependencies": {
"@types/node": "^13.1.8",
"aws-sdk": "^2.777.0",
"typescript": "~3.8.3"
}
}
index.ts:
export * from "aws-sdk";
tsconfig.json:
{
"compilerOptions": {
"diagnostics": true,
"noEmitOnError": true,
"strict": true,
"target": "ES2020",
"lib": ["ESNext"],
"moduleResolution": "Node",
"module": "ESNext"
}
}
Dockerfile :
FROM node:14.14-alpine3.12
WORKDIR /app
COPY . ./
RUN npm install
RUN npm run build
RUN npm start
(τρέξτε docker build . για να ξεκινήσετε)
Απάντηση #1
Ενώ θα ήθελα ακόμα να καταλάβω τον λόγο, η παρακάτω λύση έχει λειτουργήσει καλά σε σενάρια κατασκευής:
{
// other settings...
"scripts": {
"build": "tsc && exit 0"
}
}
Με κάποιο τρόπο, ο άμεσος κωδικός απόκρισης μιας μεμονωμένης εντολής tsc δεν φτάνει στο εξωτερικό σενάριο, αλλά το αποτέλεσμα της αποτυχίας του λογικού όρου && φτάνει.
