Build epäonnistui ilman lokeja: näin saat tulosteen näkyviin
Kun build epäonnistuu ilman lokeja, virhe tapahtui ennen buildin käynnistymistä. Opi tunnistamaan neljä vaihetta, joissa näin voi käydä, erottamaan ne toisistaan ja saamaan tulosteen näkyviin jokaisesta vaiheesta.
"Build failed." Ei stack tracea, compiler-virhettä tai minkäänlaista tulostetta. Kun build epäonnistuu ilman lokeja, kyseessä on vähiten hyödyllinen ilmoitus, jonka alusta voi antaa. Yleensä se kuitenkin tarkoittaa jotain tiettyä, mikä kannattaa ymmärtää: virhe tapahtui ennen lokien tuottamisesta vastaavan vaiheen käynnistymistä.
Build ei ole yksi vaihe. Niitä on neljä, ja jokainen voi epäonnistua eri tavalla.
Neljä vaihetta
1. Lähdekoodin haku. Alusta kloonaa repositoriosi tietyn ref-arvon kohdalta. 2. Buildin valmistelu. Alusta selvittää, miten build tehdään — Dockerfilen, buildpackin tai tunnistetun frameworkin avulla. 3. Buildin suorittaminen. Komentosi suoritetaan. Tämä on ainoa vaihe, joka tuottaa odottamaasi tulostetta. 4. Paketointi. Tulos muunnetaan ajettavaksi imageksi.
Jos lokeja ei ole lainkaan, virhe tapahtui vaiheessa 1 tai 2. Buildiasi ei koskaan suoritettu, joten se ei olisi voinut tulostaa mitään.
Vaihe 1: koodiasi ei koskaan saatu
Oireina ovat täydellinen hiljaisuus ja nopea epäonnistuminen — yleensä alle 15 sekunnissa.
Yleisimmät syyt tärkeysjärjestyksessä:
- Branchia ei ole olemassa. Palvelu on määritetty deployaamaan
master-branch, mutta repository on nimetty uudelleenmain-branchiksi. Tämä epäonnistuu välittömästi eikä kerro juuri mitään. - Käyttöoikeus peruttiin. Viime kuussa toiminut token tai app-asennus poistettiin, tai repository siirrettiin organisaatioon, jossa myönnetty käyttöoikeus ei enää päde.
- Repository on private ja yhteys on vanhentunut. Tilanne on sama kuin edellä: alusta saa 404- eikä 403-vastauksen, koska näin Git-palveluntarjoajat toimivat private-repositoryjen kanssa, joita sinulla ei ole oikeutta nähdä.
- Alamoduulia ei voi hakea. Päärepository kloonataan, mutta SSH-URL-osoitetta käyttävän alamoduulin haku epäonnistuu, koska build-ympäristöllä ei ole siihen tarvittavaa avainta.
Nopea tarkistus: näyttääkö alusta epäonnistuneelle deploylle commit hashia? Jos ei, koodia ei koskaan saatu, eikä millään Dockerfilen asetuksella ole tässä merkitystä.
Vaihe 2: se ei tiedä, miten build tehdään
Myös tämä vaihe on hiljainen, koska build-komentoa ei ole vielä valittu.
- Dockerfilea ei ole konfiguraation ilmoittamassa sijainnissa.
dockerfilePathosoittaa polkuun, joka on siirretty. - Monorepositoriolla ei ole juuripolkua. Alusta tarkastelee repositoryn juurta, vaikka palvelusi sijaitsee polussa
apps/api. - Tunnistus ei löytänyt mitään. Tunnistettua manifestia ei ole, joten mikään buildpack ei sopinut.
- Dockerfilea ei voi jäsentää. Rivin 1 syntaksivirhe aiheuttaa epäonnistumisen ennen yhdenkään layerin suorittamista.
Vaihe 3: tässä vaiheessa lokit ovat olemassa
Jos näet osittaisen tulosteen, joka loppuu äkillisesti, olet vaiheessa 3. Kaksi yleisintä syytä liittyvät tällöin resurssien riittävyyteen, eivät koodiin:
Muisti loppui. OOM-reaperin tappama build ei ehdi tulostaa mitään siitä, mitä tapahtui. Loki vain loppuu kesken vaiheen. TypeScript-, webpack- ja Vite-buildit suurissa codebaseissa törmäävät tähän säännöllisesti. Tunnusmerkkinä on, että sama commit buildautuu ongelmitta laptopillasi, jossa on enemmän muistia kuin builderissa.
Timeout. Alustan aikarajan ylittävä build lopetetaan. Oire on sama: tuloste loppuu kesken eikä pääty normaalisti.
Molemmat näyttävät "lokittomalta" epäonnistumiselta, jos virhe tapahtuu riittävän aikaisin.
Vaihe 4: build onnistui, mutta paketointi ei
Harvinainen ja tarkkarajainen tilanne: build onnistui, mutta artefakti on virheellinen. Imagelta puuttuu CMD tai ENTRYPOINT, arkkitehtuurit eivät täsmää tai image on alustan rajoitusta suurempi.
Diagnostiikan etenemisjärjestys
# 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
Viimeisen komennon tulosteen stageTimings on nopein tapa paikantaa virhe. Deploy, joka käytti kloonaukseen 0,4 sekuntia ja päättyi sen jälkeen epäonnistuneena vaiheessa 1, on selvä tapaus. Jos build kesti 90 sekuntia ja loppui sitten, kyseessä on vaiheen 3 ongelma, todennäköisimmin muisti.
Tulosteen saaminen, kun sitä ei ole
Kolme tekniikkaa vaivannäön mukaisessa järjestyksessä:
Toista rajoite lokaalisti. Älä kysy "buildautuuko tämä omalla koneellani", vaan buildaa se samalla muistimäärällä kuin builderissa:
docker build --memory=2g --memory-swap=2g -t test .
Jos tämä toistaa virheen, olet löytänyt syyn: kyse on muistista, ei mistään mystisestä.
Tee buildista äänekkäämpi. Useimmat build-työkalut ovat oletusarvoisesti hiljaisia siitä, mikä on juuri tappamassa ne.
# 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
Pelkkää NODE_OPTIONS-riviä kannattaa kokeilla erikseenkin — hiljaa kaatuva Node-build johtuu hyvin usein heap-rajoituksesta, ja sen kasvattaminen korjaa buildit, jotka eivät tuottaneet minkäänlaista diagnostiikkaa.
Tee Dockerfilestä bisect. Kommentoi kaikki epäonnistuvan vaiheen jälkeinen sisältö pois ja lisää RUN echo "reached step N" -merkintöjä. Menetelmä on karkea, mutta toimii silloin, kun mikään muu ei auta.
Mikä vähentää tämän ongelmaluokan esiintymistä?
Kaksi asiaa on tärkeämpiä kuin mikään debuggaustekniikka.
Lokien streamaaminen yhteenvetolokien sijaan. Jos tuloste näkyy vasta buildin valmistuttua, tapettu build ei tuota mitään, koska yhteenveto kirjoitetaan lopussa. Streamaamalla käytössäsi on buildin kuollessa juuri siihen asti kertynyt loki.
dockup logs my-project/my-api --build --follow
Nimetyt ja ajastetut vaiheet. "Build failed" on yksi tiedonmurunen. "Clone: 0.4s, build: failed after 94s" riittää rajaamaan kolme neljästä edellä mainitusta syystä pois ilman, että mitään tarvitsee lukea enempää.
Usein kysytyt kysymykset
Miksi buildini ei tuota lainkaan lokeja? Koska se epäonnistui ennen build-komentojesi suorittamista — yleensä lähdekoodin haussa tai build-tavan selvittämisessä. Kumpikaan vaihe ei tuota build-tulostetta.
Miksi buildautuu lokaalisti, mutta ei alustalla?
Useimmiten syynä on muisti. Koneessasi on sitä enemmän kuin builderissa. Vahvista asia suorittamalla docker build --memory=2g ennen kuin etsit syytä muualta.
Mitä tarkoittaa kesken vaiheen loppuva loki? Prosessi tapettiin sen sijaan, että se olisi päättynyt normaalisti. Vaihtoehtoina ovat muistin loppuminen tai buildin timeout. OOM-killer ei anna prosessille tilaisuutta selittää itseään.
Tarvitsenko Dockerfilen? Et välttämättä — alustat voivat tunnistaa yleisiä projektityyppejä ja buildata ne ilman Dockerfilea. Tunnistuksen epäonnistuminen on kuitenkin itsessään hiljainen, lokiton virhe, joten eksplisiittinen Dockerfile poistaa kokonaisen epäselvyyksien luokan.
