Hvordan bygge et image for OKD
Hvorfor trenger vi en Containerfile?
For at OKD skal kunne kj?re applikasjonen din, trenger den et s?kalt container image. Dette er en selvstendig pakke som inneholder alt applikasjonen din trenger for ? kj?re: kode, avhengigheter og konfigurasjon.
Verkt?yet som er anbefalt p? UiO for ? bygge disse container image-ene er Podman. Men Podman trenger en detaljert oppskrift for ? vite n?yaktig hvordan image-et skal bygges, fra start til slutt. Denne oppskriften er din Containerfile. Den definerer hvert steg i byggeprosessen, fra hvilket base-image som skal brukes, til hvilke kommandoer som skal kj?res.
Det er god praksis ? bruke en s?kalt multi-stage build. Dette inneb?rer ? dele opp prosessen i flere separate steg for ? skape et lite, sikkert og optimalisert sluttprodukt. Den vanligste varianten har to steg: en byggeprosess og en kj?re-prosess, men du kan ha s? mange steg som n?dvendig.
Eksempelet under viser en Containerfile for en applikasjon bygget i Next.js. Dette er et popul?rt rammeverk for ? lage React-applikasjoner ved UiO, og det kj?rer p? Node.js.
Node.js er et kj?remilj? som gj?r det mulig ? kj?re JavaScript-kode p? en server, alts? utenfor nettleseren. For rammeverk som Next.js fungerer Node.js som motoren som b?de bygger selve nettsiden (omgj?r React-kode til ferdige filer) og kj?rer web-serveren som leverer siden til sluttbrukerne.
Steg 1: Bygging av applikasjonen (build stage)
I det f?rste steget setter vi opp et midlertidig milj? med alle verkt?yene som trengs for ? bygge applikasjonen. Dette steget produserer de ferdige filene, men selve milj?et blir forkastet.
Eksempel
# Steg 1: Bruk et fullt Node.js-image som inneholder alle byggeverkt?y
FROM registry.access.redhat.com/ubi9/nodejs-22 AS build
# Sett en arbeidsmappe inne i containeren
WORKDIR /usr/src/app
# Kopier kun avhengighetsfilene og installer dem
COPY package.json package-lock.json* ./
RUN npm install
# Kopier resten av kildekoden, inkludert konfigurasjonsfilen
COPY . .
# Last inn variabler fra config.env og kj?r byggekommandoen
RUN export $(grep -v '^#' config.env 2>/dev/null | xargs -r) && npm run build
Hva skjer i dette steget?
FROM ... AS build
: Vi starter med ? hente et fullt Node.js-image som har alle n?dvendige byggeverkt?y. Vi navngir dette stegetbuild
for ? kunne referere til det senere.WORKDIR
: Vi oppretter og bytter til mappen/usr/src/app
inne i containeren.COPY
ogRUN npm install
: F?rst kopierer vi kun filene som definerer avhengigheter og installerer dem. Dette er en optimalisering som gj?r at Podman kan gjenbruke dette laget s? lenge avhengighetene ikke endres.COPY . .
: Deretter kopieres resten av applikasjonens kildekode inn.RUN export ... && npm run build
: Dette er en sammensatt kommando:- F?rst leser
export $(grep ...)
innholdet iconfig.env
, ignorerer kommentarlinjer (de som starter med#
), og gj?r variabelene i filen tilgjengelige som milj?variabler under bygging. Dette er nyttig dersom vi trenger variablene n?r vi bygger imaget, ikke bare n?r det kj?rer. Next.js krever ofte dette. Dette krever ogs? at filen config.env enten finnes i applikasjonen, eller blir lest inn av containerfilen fra et annet sted. - Deretter, n?r variablene er lastet inn, kj?res
npm run build
. Dette bygger s? applikasjonen med node package manager som har et regelsett det f?lger ved byggingen. Det er lurt ? teste dette lokalt f?r du pr?ver ? bygge i OKD.
- F?rst leser
Steg 2: Klargj?ring av kj?remilj? (runtime stage)
N? bygger vi det endelige imaget som OKD skal bruke. Dette imaget skal kun inneholde det absolutt n?dvendige for ? kj?re applikasjonen.
Eksempel
# Steg 2: Start p? nytt med et minimalt image optimalisert for kj?ring
FROM registry.access.redhat.com/ubi9/nodejs-22-minimal
ENV NODE_ENV=production
WORKDIR /usr/src/app
# Sett automatisk utl?p for imaget (3 uker)
LABEL quay.expires-after=3w
# Kopier kun de n?dvendige filene fra bygge-steget
COPY --from=build /usr/src/app/package.json ./
COPY --from=build /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/.next ./.next
COPY --from=build /usr/src/app/public ./public
COPY --from=build /usr/src/app/config.env ./
# Informer OKD om hvilken port applikasjonen lytter p?
EXPOSE 3000
# Last inn variabler fra config.env og start applikasjonen
CMD ["sh", "-c", "export $(grep -v '^#' config.env 2>/dev/null | xargs -r) && exec npm start"]
Hva skjer i dette steget?
FROM ...
: Vi starter med blanke ark i hvert steg, denne gangen velger vi et minimalt base-image som kun inneholder det som trengs for ? kj?re en Node.js-applikasjon (ikke bygge).COPY --from=build ...
: Her f?r vi gevinsten av en multi-stage build. Vi kopierer kun de ferdigbygde filene og produksjonsavhengighetene frabuild
-steget over til v?rt nye, rene image. All kildekode og byggeverkt?y blir liggende igjen og forkastet.EXPOSE 3000
: Vi dokumenterer at applikasjonen vil lytte p? port 3000 inne i containeren, dette m? matche det som er satt i appen din.CMD ["sh", "-c", "..."]
: Dette er den endelige kommandoen som kj?res n?r image-et startes som en container.- Den starter en shell (
sh -c
) som f?rst laster inn variablene fraconfig.env
, p? samme m?te som i bygge-steget. Kun n?dvendig dersom vi hentet data i byggefasen og trenger de ved kj?ring av applikasjonen. - Deretter bruker den
exec npm start
. Bruken avexec
er viktig fordi den erstatter shell-prosessen med applikasjonsprosessen (npm start
). Dette sikrer at appen mottar signaler korrekt fra OKD, for eksempel ved en kontrollert nedstengning.
- Den starter en shell (
Eksempel-fil
Her er et eksempel p? hvordan en Containerfile kan se ut.
# Steg 1: Bruk et fullt Node.js-image som inneholder alle byggeverkt?y
FROM registry.access.redhat.com/ubi9/nodejs-22 AS build
# Sett en arbeidsmappe inne i containeren
WORKDIR /usr/src/app
# Kopier kun avhengighetsfilene og installer dem
COPY package.json package-lock.json* ./
RUN npm install
# Kopier resten av kildekoden, inkludert konfigurasjonsfilen
COPY . .
# Last inn variabler fra config.env og kj?r byggekommandoen
RUN export $(grep -v '^#' config.env 2>/dev/null | xargs -r) && npm run build
# Steg 2: Start p? nytt med et minimalt image optimalisert for kj?ring
FROM registry.access.redhat.com/ubi9/nodejs-22-minimal
ENV NODE_ENV=production
WORKDIR /usr/src/app
# Sett automatisk utl?p for imaget (3 uker)
LABEL quay.expires-after=3w
# Kopier kun de n?dvendige filene fra bygge-steget
COPY --from=build /usr/src/app/package.json ./
COPY --from=build /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/.next ./.next
COPY --from=build /usr/src/app/public ./public
COPY --from=build /usr/src/app/config.env ./
# Informer OKD om hvilken port applikasjonen lytter p?
EXPOSE 3000
# Last inn variabler fra config.env og start applikasjonen
CMD ["sh", "-c", "export $(grep -v '^#' config.env 2>/dev/null | xargs -r) && exec npm start"]