Lösning av felet "Skript saknas" i Node.js i Docker

Node.js

Starta Node.js Backend i Docker: En felsökningsguide

Stöter på ett fel när du försöker köra din inuti a kan vara frustrerande, särskilt när det beror på ett enkelt meddelande om att man saknar startskript. Detta fel uppstår ofta när kan inte hitta rätt startkommando i din installation. Om du har drabbats av detta är du inte ensam!

I många fall beror problemet på felaktiga sökvägar eller felaktiga konfigurationer mellan dina package.json- och Docker-inställningar. Det är lätt att förbise en liten detalj när man har att göra med , containerisering och konfigurationsfiler. Efter att ha ställts inför det här problemet själv kan jag säga att åtgärda det ofta innebär att man kontrollerar varje fils placering och skript.

Till exempel distribuerade jag en gång en backend och insåg senare att min dist-mapp inte var korrekt mappad, vilket gjorde att startkommandot misslyckades. Enkla justeringar kan lösa dessa problem, men att hitta den rätta kräver tålamod. Att kontrollera om alla beroenden och skript är korrekt mappade kan spara timmar av felsökning.

I den här guiden kommer vi att dyka ner i några praktiska steg för att åtgärda det här felet, särskilt om du kör din backend tillsammans med en databas som i Docker. Låt oss felsöka felet "saknat startskript" tillsammans för att få din backend att fungera smidigt!

Kommando Beskrivning
CMD ["node", "dist/server.js"] Definierar det primära kommandot som körs i Docker-behållaren vid start. Här uppmanar den Docker att starta applikationen genom att köra server.js inuti dist-mappen, som adresserar problem genom att säkerställa att Docker vet vilket skript som ska köras.
WORKDIR /app Ställer in arbetskatalogen inuti behållaren till /app. Detta är avgörande för att säkerställa att alla filsökvägar i efterföljande kommandon hänvisar till den här katalogen, vilket effektiviserar bygg- och körningsprocesserna inom Docker.
COPY --from=builder /app/dist ./dist Kopierar de byggda filerna från dist-mappen i byggarstadiet till körtidsmiljöns dist-katalog. Detta kommando är viktigt för att se till att kompilerade TypeScript-filer är tillgängliga i behållaren.
RUN npm install --omit=dev Installerar endast produktionsberoendena genom att utelämna dev-beroendena. Det här kommandot är optimerat för produktionsbyggnationer, vilket minskar behållarens slutliga storlek och förbättrar säkerheten genom att utesluta utvecklingsverktyg.
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000"] Definierar en hälsokontroll för att verifiera om DynamoDB-tjänsten i Docker körs. Den använder curl för att försöka ansluta till den angivna lokala slutpunkten, vilket säkerställer att tjänsten är tillgänglig innan backend startar.
depends_on: Anger beroenden i docker-compose.yml. Här säkerställer den att backend-tjänsten väntar på att DynamoDB ska initieras, vilket förhindrar att fel försöker ansluta till en oförklar tjänst.
EXPOSE 3001 Öppnar port 3001 i Docker-behållaren, vilket gör backend-tjänsten tillgänglig på denna port. Detta kommando krävs för att ställa in nätverk och tillåta externa tjänster eller andra behållare att komma åt backend.
test('dist folder exists', ...) Ett Jest-enhetstest som kontrollerar om dist-mappen skapades korrekt. Det här testet hjälper till att verifiera att byggsteget lyckades och fångar upp potentiella problem med saknade filer i dist-katalogen.
expect(packageJson.scripts.start) En Jest-testrad som bekräftar att startskriptet finns i package.json. Detta hjälper till att förhindra körtidsfel från att missa startkommandon genom att säkerställa konfigurationsnoggrannhet före driftsättning.

Docker-konfiguration för Node.js och databasanslutning

I exemplet ovan utnyttjar Docker-installationen en flerstegsbyggnad, vilket är användbart för att skapa effektiva produktionsklara behållare. Det första steget, definierat som "byggare", installerar beroenden och kompilerar filer till JavaScript i mapp. Detta steg säkerställer att den kompilerade koden är redo för produktion utan att inkludera onödiga dev-beroenden. När det har byggts kopierar det andra steget (runtime) endast de kompilerade filerna och produktionsberoendena, vilket minimerar behållarstorleken. Denna inställning är särskilt användbar om du ofta distribuerar till molnmiljöer där varje bit av optimering räknas! 🚀

De kommandot i båda stegen ställer in containerns arbetskatalog till /app. Detta förenklar filsökvägar och organiserar alla operationer runt den här katalogen. Efter det, instruktioner flyttar specifika filer från värddatorn till behållaren. I det första steget kopieras paket*.json-filer och tsconfig.json för att möjliggöra beroendeinstallation och TypeScript-kompilering, och och KÖR npm kör bygg kommandon säkerställer att allt är korrekt inställt. Den här installationen hjälper till att undvika problem som saknade startskript genom att se till att alla filer är korrekt kopierade och konfigurerade.

De fil ansluter backend med , vilket är väsentligt för lokal testning och utveckling. De alternativet säger åt Docker att starta DynamoDB före backend-tjänsten, vilket säkerställer att databasen är redo för alla anslutningsförsök från backend. I verkliga scenarier kan att inte ha en sådan beroendeinställning leda till anslutningsproblem när backend startar före databasen, vilket resulterar i frustrerande fel. De hälsokontroll kommandot testar om DynamoDB kan nås genom att pinga slutpunkten och försöka igen tills en anslutning har upprättats. Denna nivå av felhantering sparar tid genom att se till att tjänsterna startar i rätt ordning 🕒.

Slutligen, i package.json, har vi definierat manus som . Detta kommando säkerställer att NPM vet exakt vilken fil som ska köras i behållaren, vilket hjälper till att undvika felet "saknat startskript". Det finns också ett build-kommando för att kompilera TypeScript-kod och ett clean-kommando för att ta bort dist-mappen, vilket säkerställer att varje distribution startar om. Att använda npm-skript som dessa gör installationen mer tillförlitlig, särskilt när Docker är inblandad, eftersom den erbjuder förutsägbara vägar och åtgärder. Denna omfattande konfiguration av Docker-, Docker Compose- och NPM-skript fungerar tillsammans för att skapa ett strömlinjeformat arbetsflöde från utveckling till produktion.

Lösning 1: Justera Dockerfile och Package.json för korrekt filkopiering

Denna lösning använder Docker och Node.js för att säkerställa att filerna kopieras korrekt till dist mapp och att NPM kan hitta start manus.

# Dockerfile
FROM node:18 AS builder
WORKDIR /app
# Copy necessary config files and install dependencies
COPY package*.json tsconfig.json ./
RUN npm install
# Copy all source files and build the project
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/package*.json ./
RUN npm install --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 3001
# Adjust command to start the server
CMD ["node", "dist/server.js"]

Lösning 2: Ändra docker-compose.yml för miljökontroll

Denna lösning modifierar docker-compose.yml konfiguration för att specificera rätt kommandon och säkerställa att skript körs korrekt i Docker.

# docker-compose.yml
version: "3.9"
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3001:3001"
    environment:
      PORT: 3001
    depends_on:
      - dynamodb
    command: ["npm", "run", "start"]
  dynamodb:
    image: amazon/dynamodb-local
    ports:
      - "8001:8000"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000"]
      interval: 10s
      timeout: 5s
      retries: 5

Lösning 3: Verifiera och uppdatera Package.json-skripten

Denna lösning innebär att se till att start skriptet är korrekt definierat i package.json fil för att förhindra saknade skriptfel.

{
  "name": "backend",
  "version": "1.0.0",
  "main": "dist/server.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "dev": "nodemon --exec ts-node src/server.ts",
    "clean": "rimraf dist"
  }
}

Enhetstester: Säkerställer skript- och dockarkonfigurationsintegritet

Dessa Jest-test validerar att viktiga filer är korrekt kopierade och att NPM-skript fungerar i containermiljön.

// test/deployment.test.js
const fs = require('fs');
describe('Deployment Tests', () => {
  test('dist folder exists', () => {
    expect(fs.existsSync('./dist')).toBe(true);
  });
  test('start script exists in package.json', () => {
    const packageJson = require('../package.json');
    expect(packageJson.scripts.start).toBe("node dist/server.js");
  });
  test('Dockerfile has correct CMD', () => {
    const dockerfile = fs.readFileSync('./Dockerfile', 'utf8');
    expect(dockerfile).toMatch(/CMD \["node", "dist\/server.js"\]/);
  });
});

Säkerställa korrekt filkopiering och struktur i Docker för Node.js-projekt

När du arbetar med Node.js-applikationer i Docker är en viktig faktor att se till att alla nödvändiga filer är korrekt kopierade och strukturerade i behållaren. I flerstegsbyggen, som exemplet ovan, har varje steg ett specifikt syfte. Det inledande skedet, "byggare", hanterar kompilering av TypeScript till JavaScript och förbereder mapp. I det andra steget ingår endast produktionsfiler, vilket minskar behållarens storlek och optimerar distributionen. Detta tillvägagångssätt minskar inte bara onödig svullnad utan ökar också säkerheten genom att utelämna utvecklingsverktyg.

En viktig aspekt av Docker för Node.js är att organisera och exakt. Genom att tydligt ange sökvägar i Dockerfilen och se till att startkommandot är korrekt inställt i package.json, minimerar du fel som "Saknar startskript." Det är också viktigt att bekräfta att Docker vet var varje fil ska vara, särskilt i komplexa inställningar som involverar flera tjänster eller mappar. Använd till exempel kommandot COPY för att bara lägga till mapp och nödvändiga konfigurationer till den slutliga behållaren säkerställer att endast viktiga filer är tillgängliga i produktionen 📂.

För att kontrollera hälsan hos dina tjänster filen använder en hälsokontroll för att verifiera att databasen är klar. Genom att definiera beroenden säkerställer vi att backend-tjänsten inte startar förrän databasen är lyhörd, vilket förhindrar tidsrelaterade anslutningsproblem. Denna inställning är särskilt fördelaktig i verkliga applikationer där databasanslutning är avgörande. Utan denna struktur kan tjänster försöka ansluta innan andra tjänster är uppe, vilket leder till körtidsfel och potentiell driftstopp för användare 🔄.

  1. Vad orsakar felet "saknat startskript" i NPM?
  2. Detta fel inträffar ofta när filen har inte en skript definierat. NPM kan inte hitta rätt ingångspunkt för att starta applikationen.
  3. Gör det filen måste finnas i mapp?
  4. Nej, den finns vanligtvis i rotkatalogen och endast nödvändiga filer kopieras till mapp.
  5. Varför använder vi flerstegsbyggen i Docker?
  6. Flerstegskonstruktioner tillåter oss att skapa lätta, produktionsklara behållare. Genom att separera bygg- och körningsmiljöer utesluts onödiga filer, vilket förbättrar säkerheten och effektiviteten.
  7. Hur fungerar i Docker Compose hjälp?
  8. De kommando kontrollerar om en tjänst är igång, vilket är viktigt i de fall där beroende tjänster måste vara redo först, som databaser.
  9. Kan jag använda andra databaser istället för DynamoDB i den här installationen?
  10. Ja, du kan byta ut med andra databaser. Justera Docker Compose-konfigurationen så att den passar din föredragna databastjänst.
  11. Varför använder vi kommando?
  12. Det här kommandot installerar bara produktionsberoende, vilket hjälper till att hålla behållaren lätt genom att utesluta utvecklingsverktyg.
  13. Hur kan jag bekräfta är mappen korrekt kopierad?
  14. Du kan lägga till ett test i din kod för att kontrollera om finns, eller använd Docker CLI för att inspektera behållarens innehåll efter bygget.
  15. Behöver jag ange porten i både Dockerfile och Docker Compose?
  16. Ja, att specificera porten i båda säkerställer att containerporten matchar värdporten, vilket gör tjänsten tillgänglig utanför Docker.
  17. Varför är inställningen i Docker viktigt?
  18. Miljö skapar en standardkatalogsökväg för alla kommandon, förenklar filsökvägar och organiserar containerfiler systematiskt.
  19. Hur kan jag visa Docker-loggar för att felsöka det här felet?
  20. Använda för att komma åt loggar, som kan ge insikter om eventuella startfel eller saknade filer.

Att åtgärda felet "saknat startskript" kräver uppmärksamhet på detaljer, särskilt vid konfigurering av Dockers filstruktur och NPM-skript. Kontrollera din Dockerfile för att säkerställa att kompilerade filer kopieras till mapp och att startskriptet i package.json är korrekt definierat kan spara timmar av felsökning.

Att upprätthålla en tydlig installation och organiserade skript hjälper Docker-containrar att fungera utan problem, och att använda hälsokontroller i Docker Compose säkerställer att tjänster laddas i rätt ordning. Med dessa justeringar bör din backend starta på ett tillförlitligt sätt, vilket ger dig ett smidigare utvecklingsarbetsflöde. 🛠️

  1. Detaljerad information om flerstegsbyggnationer och bästa praxis för Node.js-applikationer i Docker: Docker-dokumentation
  2. Omfattande guide för att ställa in hälsokontroller och beroenden i Docker Compose för att säkerställa att tjänsterna startar i rätt ordning: Docker Compose Health Check
  3. Felsökning av "saknade startskript"-fel och andra vanliga NPM-problem, inklusive att konfigurera package.json korrekt för produktionsversioner: NPM-dokumentation
  4. Introduktion till konfigurering och testning av DynamoDB Local i Docker-miljöer, inklusive användning med Node.js backends: AWS DynamoDB Local Guide