Η μεταγλώττιση απέτυχε χωρίς logs: Πώς να λάβετε output
Όταν ένα build αποτυγχάνει χωρίς logs, αυτό σημαίνει ότι η αποτυχία συνέβη πριν ξεκινήσει το ίδιο το build. Μάθετε τα τέσσερα στάδια στα οποία μπορεί να συμβεί, πώς να τα ξεχωρίζετε και πώς να λαμβάνετε output από καθένα.
«Το build απέτυχε.» Χωρίς stack trace, χωρίς compiler error, χωρίς καθόλου output. Ένα build που απέτυχε χωρίς logs είναι το λιγότερο χρήσιμο μήνυμα που μπορεί να εμφανίσει μια πλατφόρμα και συνήθως σημαίνει κάτι συγκεκριμένο που αξίζει να κατανοήσετε: η αποτυχία συνέβη πριν ξεκινήσει αυτό που παράγει τα logs.
Ένα build δεν είναι ένα μόνο βήμα. Αποτελείται από τέσσερα, και το καθένα αποτυγχάνει με διαφορετικό τρόπο.
Τα τέσσερα στάδια
1. Λήψη του source code. Η πλατφόρμα κάνει clone του repository σας σε ένα ref. 2. Προετοιμασία του build. Καθορίζει πώς θα γίνει το build — μέσω Dockerfile, buildpack ή framework που εντοπίστηκε. 3. Εκτέλεση του build. Εκτελούνται οι εντολές σας. Αυτό είναι το μόνο στάδιο που παράγει το output που περιμένετε. 4. Packaging. Το αποτέλεσμα μετατρέπεται σε runnable image.
Αν δεν έχετε καθόλου logs, η αποτυχία συνέβη στο στάδιο 1 ή 2. Το build σας δεν εκτελέστηκε ποτέ, επομένως δεν θα μπορούσε να εμφανίσει τίποτα.
Στάδιο 1: ο κώδικάς σας δεν λήφθηκε ποτέ
Τα συμπτώματα είναι απόλυτη σιωπή και γρήγορη αποτυχία — συνήθως σε λιγότερο από δεκαπέντε δευτερόλεπτα.
Συνηθισμένες αιτίες, κατά σειρά:
- Το branch δεν υπάρχει. Μια υπηρεσία που έχει ρυθμιστεί να κάνει deploy το
masterσε ένα repository που μετονομάστηκε σεmain. Αυτό αποτυγχάνει αμέσως και δεν παρέχει σχεδόν καμία πληροφορία. - Ανακλήθηκε η πρόσβαση. Το token ή η εγκατάσταση της εφαρμογής που λειτουργούσε τον περασμένο μήνα καταργήθηκε ή το repository μεταφέρθηκε σε organisation όπου η παραχώρηση πρόσβασης δεν ισχύει πλέον.
- Το repository είναι private και η σύνδεση έληξε. Έχει την ίδια μορφή με την παραπάνω περίπτωση· η πλατφόρμα λαμβάνει 404 αντί για 403, επειδή αυτό επιστρέφουν οι Git providers για private repositories που δεν μπορείτε να δείτε.
- Δεν είναι δυνατή η λήψη ενός submodule. Το κύριο repository γίνεται clone, αλλά ένα submodule που χρησιμοποιεί SSH URL αποτυγχάνει, επειδή το build environment δεν διαθέτει κλειδί για αυτό.
Ο γρήγορος έλεγχος: εμφανίζει η πλατφόρμα commit hash για το failed deployment; Αν όχι, δεν έλαβε ποτέ τον κώδικα και τίποτα στο Dockerfile σας δεν είναι σχετικό.
Στάδιο 2: δεν γνωρίζει πώς να κάνει build
Και αυτό το στάδιο είναι αθόρυβο, επειδή δεν έχει επιλεγεί ακόμη καμία build command.
- Δεν υπάρχει Dockerfile στη διαδρομή που έχει δηλωθεί στο config. Ένα
dockerfilePathπου δείχνει σε μια διαδρομή που μετακινήθηκε. - Monorepo χωρίς root. Η πλατφόρμα εξετάζει το root του repository, ενώ η υπηρεσία σας βρίσκεται στο
apps/api. - Η διαδικασία detection δεν βρήκε τίποτα. Δεν υπάρχει αναγνωρίσιμο manifest, επομένως δεν έγινε match με κανένα buildpack.
- Ένα Dockerfile που αποτυγχάνει στο parsing. Ένα syntax error στη γραμμή 1 προκαλεί αποτυχία πριν εκτελεστεί οποιοδήποτε layer.
Στάδιο 3: εδώ υπάρχουν logs
Αν βλέπετε μερικό output που σταματά απότομα, βρίσκεστε στο στάδιο 3 και οι δύο συνηθέστερες αιτίες αφορούν resources και όχι τον κώδικα:
Έλλειψη μνήμης. Ένα build που τερματίζεται από τον OOM reaper δεν προλαβαίνει να εμφανίσει τι συνέβη. Το log απλώς σταματά στη μέση ενός βήματος. Τα builds με TypeScript, webpack και Vite σε μεγάλα codebases αντιμετωπίζουν συχνά αυτό το πρόβλημα. Η ένδειξη είναι ότι το ίδιο commit γίνεται κανονικά build στο laptop σας, το οποίο διαθέτει περισσότερη μνήμη από τον builder.
Timeout. Ένα build που ξεπερνά το όριο της πλατφόρμας τερματίζεται. Το σύμπτωμα είναι το ίδιο: το output σταματά αντί να ολοκληρώνεται.
Και οι δύο περιπτώσεις μοιάζουν με «χωρίς logs», αν η αποτυχία συμβεί αρκετά νωρίς.
Στάδιο 4: έγινε build, αλλά δεν μπορεί να γίνει packaging
Σπάνιο και συγκεκριμένο: το build ολοκληρώθηκε επιτυχώς, αλλά το artefact δεν είναι σωστό. Για παράδειγμα, ένα image χωρίς CMD ή ENTRYPOINT, ασυμβατότητα αρχιτεκτονικής ή image που είναι υπερβολικά μεγάλο για το όριο της πλατφόρμας.
Η σειρά του diagnostic ελέγχου
# Is there a commit hash? If not, stage 1.
dockup deployments my-project/my-api --json
# Build logs of the latest deployment, streamed as it goes
dockup logs my-project/my-api --build --follow
# The full record, including which stage took how long
dockup status my-project/my-api --json
Το stageTimings στο τελευταίο output είναι ο γρηγορότερος τρόπος για να εντοπίσετε την αποτυχία. Ένα deployment που χρειάστηκε 0,4 δευτερόλεπτα για το clone και στη συνέχεια τερμάτισε ως failed βρίσκεται στο στάδιο 1. Ένα deployment που χρειάστηκε ενενήντα δευτερόλεπτα για το build και μετά σταμάτησε αντιμετωπίζει πρόβλημα στο στάδιο 3, πιθανότατα λόγω μνήμης.
Πώς να λάβετε output όταν δεν υπάρχει
Τρεις τεχνικές, με σειρά αυξανόμενης προσπάθειας:
Αναπαραγάγετε το constraint τοπικά. Όχι «γίνεται build στον υπολογιστή μου» — κάντε build με την ίδια μνήμη που διαθέτει ο builder:
docker build --memory=2g --memory-swap=2g -t test .
Αν έτσι αναπαράγεται η αποτυχία, την έχετε εντοπίσει και οφείλεται στη μνήμη, όχι σε κάτι μυστηριώδες.
Κάντε το build σας πιο verbose. Τα περισσότερα build tools είναι σιωπηλά από προεπιλογή σχετικά με το πρόβλημα που πρόκειται να τα τερματίσει.
# Print progress so a truncated log still shows where it stopped
RUN npm ci --loglevel verbose
RUN NODE_OPTIONS="--max-old-space-size=3072" npm run build
Αξίζει να δοκιμάσετε από μόνο του και το NODE_OPTIONS — ένα Node build που τερματίζεται σιωπηλά οφείλεται πολύ συχνά σε όριο heap, και η αύξησή του διορθώνει builds που δεν παρήγαγαν κανένα διαγνωστικό output.
Κάντε bisect στο Dockerfile. Αφαιρέστε προσωρινά ό,τι ακολουθεί το βήμα που αποτυγχάνει και προσθέστε markers όπως RUN echo "reached step N". Είναι πρόχειρη λύση, αλλά λειτουργεί όταν τίποτα άλλο δεν βοηθά.
Τι μειώνει αυτού του είδους τα προβλήματα
Δύο πράγματα έχουν μεγαλύτερη σημασία από οποιαδήποτε τεχνική debugging.
Logs σε streaming αντί για συνοπτικά logs. Αν το output εμφανίζεται μόνο αφού ολοκληρωθεί ένα build, ένα build που τερματίζεται δεν παράγει τίποτα, επειδή η σύνοψη γράφεται στο τέλος. Με το streaming, το log που έχετε όταν τερματίζεται είναι ό,τι καταγράφηκε μέχρι εκείνη τη στιγμή.
dockup logs my-project/my-api --build --follow
Στάδια με ονόματα και μετρήσεις χρόνου. Το «Το build απέτυχε» είναι μία μόνο πληροφορία. Το «Clone: 0,4s, build: απέτυχε μετά από 94s» αρκεί για να αποκλείσετε τρεις από τις τέσσερις παραπάνω αιτίες χωρίς να διαβάσετε τίποτα άλλο.
Συχνές ερωτήσεις
Γιατί το build μου δεν παράγει καθόλου logs; Επειδή απέτυχε πριν εκτελεστούν οι build commands — συνήθως κατά τη λήψη του source code ή κατά τον καθορισμό του τρόπου με τον οποίο θα γίνει το build. Κανένα από τα δύο στάδια δεν παράγει build output.
Γιατί γίνεται build τοπικά αλλά όχι στην πλατφόρμα;
Τις περισσότερες φορές ευθύνεται η μνήμη. Ο υπολογιστής σας διαθέτει περισσότερη από τον builder. Κάντε αναπαραγωγή με docker build --memory=2g για επιβεβαίωση, πριν εξετάσετε οτιδήποτε άλλο.
Τι σημαίνει ένα log που σταματά στη μέση ενός βήματος; Η διεργασία τερματίστηκε αντί να ολοκληρωθεί κανονικά. Οι δύο πιθανότερες αιτίες είναι η έλλειψη μνήμης και το build timeout, ενώ ο OOM killer δεν δίνει στη διεργασία την ευκαιρία να εξηγήσει τι συνέβη.
Χρειάζομαι Dockerfile; Όχι απαραίτητα — οι πλατφόρμες μπορούν να εντοπίσουν συνηθισμένους τύπους project και να κάνουν build χωρίς αυτό. Ωστόσο, η αποτυχία του detection είναι από μόνη της μια αθόρυβη αποτυχία χωρίς logs, επομένως ένα explicit Dockerfile αφαιρεί μια ολόκληρη κατηγορία ασάφειας.
