Vad är Multi-Stage Docker Builds?
Multi-steg Docker bygger är en funktion som introduceras i Docker 17.05 som låter dig använda flera uttalanden inom en enda Dockerfile. Varje instruktion börjar ett nytt stadium, som kan ha sin egen basbild, beroenden och kommandon. Artefakter kan selektivt kopieras från ett stadium till ett annat, medan den slutliga bilden bara behåller vad som är strikt nödvändigt för att köra programmet. Detta tillvägagångssätt eliminerar behovet av att manuellt kedjan Dockerfiles eller förlita på komplexa bygg skript, och det dramatiskt minskarörer storleken, och det minskarörs storleken, och det.
Kärnidén är att separera byggmiljön från runtime-miljön. I en typisk enstegsbyggnad installerar en utvecklare alla byggverktyg (t.ex. kompilatorer, pakethanterare, testramar) i samma bild som kommer att användas för produktion. Att svävar bilden och ökar attackytan. Multi-steg bygger lösa detta genom att använda en tjock, funktionsrik bild för sammanställning och sedan kopiera endast de resulterande artefakterna till en minimal runtime-bild som [FLT: 2] eller .
Fördelar med flerstegsbyggnader
Fördelarna med att anta flerstegsbyggnader går utöver enkel storleksminskning. De har en djupgående inverkan på säkerhet, underhållbarhet och utplaceringshastighet.
1. minskad bildstorlek
Genom att kassera byggtidsberoende, bygger flersteg ofta krympa bilder med 50% till 90%. Till exempel kan en Node.js-applikation som byggts med hjälp av hela ] bild (över 300MB) slimmas ner till under 20 MB genom att kopiera endast den inbyggda ] mappen till en ]]]]]] bas. Denna lagringsbesparingar översätts direkt till snabbare dragtider, mindre nätverksbandbredd och lägre registreringskostnader.
2. förbättrad säkerhet
Varje installerat paket eller verktyg i en behållare bild är en potentiell sårbarhet. Multi-steg bygger gör att du kan utesluta kompilatorer, felsökare och utvecklingsbibliotek från den slutliga bilden, vilket avsevärt minskar attackytan. Du kan även använda bilder som eller ] för runtime-scenenen, som endast innehåller det knappa minimumet för att utföra programmet binär.
3. Streamlined byggprocess
Alla byggsteg definieras i en enda Dockerfile, vilket gör processen självinnehållen och lätt att version. CI / CD-rörledningar dra nytta av en enda ingångspunkt: Dockerfile. Det finns ingen anledning att upprätthålla separata byggskript eller manuell rengöringssteg.
Förbättrad reproducerbarhet och konsistens
Eftersom hela bygget fångas i en Dockerfile, kan alla utvecklare eller system reproducera exakt samma lager. Användningen av specifika versionstaggar för basbilder garanterar ytterligare konsekventa byggs över miljöer.
Bygga en multi-steg Dockerfile: Steg för steg
Detta genomgångssätt täcker skapandet av en produktionsklar multi-stegs Dockerfile för en Node.js och React-applikation. Samma principer gäller för alla sammanställda språk.
1. Planera dina scener
Innan du skriver kod, kartlägga de steg du behöver. En typisk flerstegsbyggnad har minst två steg:
- ]Builder-steg - installerar alla byggverktyg, installerar beroenden och kör byggkommandot.
- ]Runtime stage - använder en minimal basbild, kopierar endast de byggda artefakterna från byggarens scen och definierar driftsbeteende.
För komplexa projekt kan du lägga till mellanliggande steg för tester, statisk analys eller komprimering av tillgångar.
Skriv byggarens scen
Börja med en basbild som innehåller den nödvändiga verktygskedjan. Använd namngivna steg ] med ] för att referera dem senare.
FROM node:14-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
Nyckelpunkter:
- Använd för deterministisk, snabbare beroendeinstallation.
- Håll kommandon som separata lager när det är möjligt för att utnyttja cachning.
- Installera byggverktyg (som TypeScript, webbpaket) i det här skedet.
Lägg till en mellansteg (valfri)
För att upprätthålla kodkvaliteten, lägg till ett steg som kör tester. Detta steg kan återanvända byggarens bild eller installera ytterligare verktyg. Eftersom det inte är slutstadiet kommer testfel inte att finnas i slutbilden.
FROM builder AS test
RUN npm run test
Du kan köra detta steg i din CI-rörledning med ] för att fånga misslyckanden tidigt utan att bygga hela den slutliga bilden.
Definiera Runtime Stage
För en Reagera applikation kan runtime-bilden vara en Nginx-server. För en backend API kan det vara en oskälig basbild eller en minimal Alpine med Node.js runtime. Kopiera endast de väsentliga artefakterna med ].
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Om du behöver Node.js runtime, undvik att kopiera ]] från byggaren; istället installera om produktionsberoende i driftsfasen:
FROM node:14-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/server.js"]
5. Bygg och testa bild
Bygg den slutliga bilden med standardkommandot:
docker build -t myapp:latest .
För att verifiera storleken, kör ] och jämföra mot en enstaka steg bygga. Kör behållaren och bekräfta ansökan svarar korrekt:
docker run -d -p 8080:80 myapp:latest
curl http://localhost:8080
Bästa praxis för flerstegsbyggnader
- ] Använd specifika basbildtaggar - undvik för att förhindra överraskningar. Föredra ] eller ].
- ]Optimize layer caching - kopiera och ]]] före resten av källkoden så att ]] lagret endast ogiltigförklaras när beroenden ändras.
- ]]Leverage buildKit - möjliggör BuildKit med ] för snabbare byggnationer, inlinecachning och bättre parallellism.
- ] Skapa flera slutsteg för olika miljöer – till exempel ett utvecklingsstadium med felsökningsverktyg och ett produktionsstadium med en härdad basbild.
- ]]Använd ] för utveckling bygger - i utveckling kan du stanna vid ]] för att få levande reload och källkartor, sedan bygga om med för produktion.
- ]] Behåll hemligheter av bilder - använd Docker BuildKits ] flagga om du behöver passera referenser under byggandet; aldrig inkludera dem i den slutliga bilden.
Vanliga mönster och användningsfall
sammanställda språk (Go, Rust, C++)
För statiska binärer kan runtime-scenen använda (tomma basbilder). Endast binär och kanske en konfigurationsfil kopieras. Exempel för Go:
FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp .
FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]
Python-applikationer
Använd ett byggsteg med ] för att installera beroenden och sammanställa alla C-tillägg, kopiera sedan endast de installerade paketen till en runtime-fas:
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt
COPY . .
FROM python:3.11-slim
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app /app
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Frontend med API Server
Bygg både frontend och backend i en Dockerfile. Använd separata byggsteg för varje, kopiera sedan båda artefakterna till en enda runtime-bild:
FROM node:14-alpine AS frontend-builder
WORKDIR /app
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ .
RUN npm run build
FROM node:14-alpine AS api-builder
WORKDIR /app
COPY api/package*.json ./
RUN npm ci
COPY api/ .
RUN npm run build
FROM node:14-alpine
WORKDIR /app
COPY --from=frontend-builder /app/build ./public
COPY --from=api-builder /app/dist ./dist
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/server.js"]
Felsökning av flerstegsbyggnader
- ]]Layer caching not working - se ] kommandon orderberoende innan källkoden. Använd för att utesluta onödiga filer.
- ]]][[]] - verifiera vägarna i ]]] uttalandet. Byggarens scen måste producera utgång på den angivna platsen. Använd för att avböja.
- ] Hemlig läckage - aldrig kopiera hela kataloger som kan innehålla ]] eller ]]. Kopiera endast filer som behövs.
- ]]Large final images trots flersteg - kontrollera om du av misstag kopierar ] eller hela källan. Använd för att se lagerstorlekar.
Slutsats
Multi-steg Docker bygger är en hörnsten i modern behållare. De gör det möjligt för dig att skicka magert, säkra bilder samtidigt som byggprocessen är enkel och dokumenterad i en enda Dockerfile. Genom att separera oro mellan bygg och drifttid kan du drastiskt minska bildstorlek, förbättra säkerheten och effektivisera CI / CD-rörledningar. De tekniker som visas här gäller för nästan alla stackar - oavsett om du bygger Node.js, Go, Python, Java eller frontend-applikationer. Börja med att konvertera dina befintliga Dockerfiles till multi-stage-byggnader, och du kommer omedelbart se upp.
För mer information, hänvisa till ]officiella Docker multi-steg bygga dokumentation ] och ]]]Dockerfile bästa praxis guide ]. Real-världsexempel finns också i ]] Docker Library dokumentation ]].