Docker er blevet et uundværligt værktøj i moderne softwareudvikling, der gør det muligt for teams at bygge, levere og køre applikationer med hidtil uset konsistens og lethed. Kernen i denne containeriseringsmagi ligger Dockerfile, et simpelt, men kraftfuldt script, der fungerer som skabelonen til at oprette dine Docker-billeder.
At udarbejde en effektiv Dockerfile-byggeproces er mere end blot en teknisk øvelse; det er en vej til hurtigere udviklingscyklusser, mindre og mere sikre applikationsfodaftryk og mere pålidelige implementeringer. Uanset om du er nybegynder i Docker eller ønsker at forbedre dine færdigheder, vil denne guide gennemgå det grundlæggende i at skrive praktiske, effektive og sikre Dockerfiles.
Forståelse af Docker-økosystemet: En hurtig genopfriskning

Før vi dykker ned i Dockerfiles, lad os kort berøre centrale Docker-koncepter:
- Billeder: Et billede er en let, selvstændig, eksekverbar pakke, der indeholder alt, hvad der er nødvendigt for at køre software, inklusive kode, en runtime, biblioteker, miljøvariabler og konfigurationsfiler. Billeder er uforanderlige skabeloner.
- Containere: En container er en kørbar instans af et billede. Du kan oprette, starte, stoppe, flytte eller slette containere. De leverer isolerede miljøer til dine applikationer.
- Dockerfile: Dette er vores fokus. En Dockerfile er et tekstdokument, der indeholder en række kommandoer, som Docker bruger til automatisk at sammensætte et billede.
- Docker Hub/Registries: Disse er lagre til lagring og deling af Docker-billeder, svarende til GitHub til kode.
En velskrevet Dockerfile sigter mod at producere et image , der er så lean, hurtigt at bygge og sikkert som muligt.
Forklaring af Docker Build Flags
- -t myapp:1.0 : Dette flag tagger dit billede med et navn (myapp) og en version (1.0). Tagging hjælper med versionskontrol og gør det nemmere at referere til specifikke billedbuilds senere, især når du implementerer eller pusher til et register.
- . (punktum) : Dette refererer til byggekonteksten, den mappe hvor Docker skal søge efter Dockerfilen og eventuelle andre filer, der kræves under byggeprocessen (f.eks. filer, der skal KOPIERES til billedet).
Docker komprimerer og sender indholdet af denne mappe til Docker-daemonen. Det er vigtigt at bemærke, at kun filer i byggekonteksten kan tilgås under byggeprocessen.
Vigtige Dockerfile-instruktioner: Byggestenene

Lad os undersøge de mest almindelige instruktioner og hvordan man bruger dem effektivt.
- FRA: Hver Dockerfile skal starte med en FROM-instruktion. Den angiver det basisbillede, som dit billede skal bygges på.
- Formål: At vælge et udgangspunkt, ofte et operativsystem (som Ubuntu:22.04) eller en forudkonfigureret applikationskørsel (som node:18-alpine).
- Eksempel : FRA python:3.9-slim
- Bedste praksis: Vælg det minimale basisaftryk, der opfylder din applikations behov. Alpine-versioner er små, men bruger musl libc, hvilket kan have kompatibilitetsproblemer for nogle C-afhængige pakker. Slanke versioner er et godt kompromis, da de tilbyder en forenklet version af en standarddistribution (som Debian) med glibc.
- ARBEJDSDIR: Denne indstilling angiver warbejdsmappe for alle efterfølgende RUN-, CMD-, ENTRYPOINT-, COPY- og ADD-instruktioner.
- Formål: At definere den aktuelle mappekontekst i billedet for efterfølgende filhandlinger og kommandoudførelser. Hvis mappen ikke findes, opretter Docker den.
- Eksempel: ARBEJDSDIREKTØR /usr/src/app
- Bedste praksis: Brug absolutte stier til WORKDIR. Det er generelt nemmere at ændre mapper ved hjælp af WORKDIR flere gange end at kæde cd-kommandoer sammen i RUN-instruktioner.
- KOPI: Kopierer filer eller mapper fra din byggekontekst til billedets filsystem.
- Formål: Tilføj din programkode, konfigurationsfiler og andre nødvendige aktiver til billedet.
- Eksempel:
Dockerfile
ARBEJDSMATERIALE /usr/src/app
KOPIÉR pakke.json ./
KOPIÉR src/ ./src/
- Bedste praksis: For simpel filkopiering, foretræk COPY frem for ADD. COPY er mere transparent. ADD har ekstra funktioner som URL-download og tar-udpakning, hvilket kan være mindre forudsigeligt. For klarhedens og sikkerheds skyld er det ofte bedre at bruge RUN med curl, wget og tar, hvis du har brug for at downloade og udpakke.
- LØBE: Udfører kommandoer i et nyt lag oven på det aktuelle billede og committer resultaterne. Dette bruges til at installere software, oprette mapper, kompilere kode osv.
- Formål: At ændre billedets filsystem ved at installere pakker, køre byggeskripter eller konfigurere konfigurationer.
- Eksempel:
Dockerfile
KØR apt-get update && apt-get install -y –no-install-recommends \
nginx \
curl \
&& rm -rf /var/lib/apt/lists/*
- Bedste praksis: Kæd relaterede kommandoer ved hjælp af && og ryd op i midlertidige filer eller pakkehåndteringscacher (som rm -rf /var/lib/apt/lists/* for Debian/Ubuntu eller yum clean all for CentOS/RHEL) i den samme RUN-instruktion. Dette minimerer antallet af lag og reducerer billedstørrelsen, da hver RUN-instruktion opretter et nyt lag.
- ENV: Angiver miljøvariabler, der er tilgængelige under byggeprocessen (efter de er defineret), og når containere køres fra billedet.
- Formål: At angive konfigurationsværdier, stier eller indstillinger, der er nødvendige for din applikation eller dine build-scripts.
- Eksempel:
Dockerfile
ENV NODE_ENV=produktions-
ENV APP_PORT=3000
- Bedste praksis: Brug ENV til ikke-følsomme konfigurationsdata. Runtime-injektionsmetoder bør anvendes i stedet for at bage dem ind i billedet med ENV til hemmeligheder.
- ARG: Definerer en variabel under byggetiden, som brugere kan overføre ved hjælp af flaget– build-arg under Docker-build.
- Formål: At tillade parametrisering af byggeprocessen uden at ændre Dockerfilen.
- Eksempel: Dockerfile
Dockerfile
ARG APP_VERSION=1.0.0
ENV APP_VERSION_ENV=${APP_VERSION}
RUN echo “Bygger version ${APP_VERSION_ENV}”
- Byg med: bash docker build– build-arg APP_VERSION=1.2.3 -t myapp.
- Bemærk: ARG-variabler er ikke tilgængelige i den kørende container, medmindre de eksplicit er angivet som en ENV-variabel, som vist ovenfor.
- UDSÆTTE: Informerer Docker om, at containeren lytter på de angivne netværksporte under kørsel.
- Formål: Dette dokument tjener primært som dokumentation for billedbyggeren og brugeren. Det publicerer ikke porteringen.
Eksempel:
Dockerfile
EXPOSE 8080
- Bemærk: For at gøre porten tilgængelig fra værten, bruger du -p eller -P flaget med docker run (f.eks. docker run -p 8080:8080 myimage).
- CMD og INDGANGSPUNKT: Definer hvilken kommando der udføres, når en container starter.
- CMD ["executable", "param1", "param2"] : Angiver standardindstillinger for en udførende container. Disse standardindstillinger kan nemt tilsidesættes ved at tilføje en kommando til docker run. Hvis du har flere CMD'er, træder kun den sidste i kraft.
- ENTRYPOINT ["executable", "param1", "param2"] : Konfigurerer en container til at køre som en eksekverbar fil. Argumenter, der sendes til docker run, tilføjes til ENTRYPOINT-kommandoen.
- Eksempel (typisk mønster):
Dockerfile
ENTRYPOINT [“python”, “app.py”] # Hovedkommando
CMD [“–help”] # Standardargument, hvis intet angives ved docker-kørsel
- Bedste praksis: Brug CMD, hvis du ønsker en standardkommando, der nemt kan overskrives. Brug ENTRYPOINT til at oprette et billede, der opfører sig som en specifik eksekverbar fil, ofte ved hjælp af CMD til at angive standardargumenter. For webapplikationer er CMD ["npm", "start"] eller CMD ["python", "manage.py", "runserver"] standard.
Vigtige bedste praksisser for optimerede Dockerfiles

At skrive en funktionel Dockerfile er kun begyndelsen. Optimering af den giver betydelige fordele.
- Udnyt Build Cache effektivt: Docker bygger billeder i lag, og forsøger at genbruge lag fra tidligere builds, hvis det er muligt (caching). For at maksimere cache-hits:
- Sorter instruktioner fra mindst hyppigt ændret til hyppigst ændret. Installer f.eks. afhængigheder (som ændres sjældnere), før du kopierer din applikations kildekode (som ændres ofte).
Dockerfile
# Godt cacheeksempel for en Node.js-app
FROM node:18-alpine
WORKDIR /app
COPY package.json package-lock.json ./ # Afhængigheder ændres sjældnere
RUN npm ci –omit=dev # Dette lag caches, hvis pakkefiler ikke ændres
COPY . . # Kildekoden ændres ofte, så det er den sidste
CMD [“node”, “server.js”]
- Hold dine billeder små: Mindre billeder er hurtigere at trække, skubbe og implementere, og de har en reduceret angrebsoverflade.
- Brug minimale basisaftryk: Alpine-, slim- eller distroless-varianter er betydeligt mindre end fulde OS-aftryk.
- Ryd op i samme RUN-lag: Fjern unødvendige cacher eller midlertidige filer ved hjælp af den samme RUN-instruktion efter installation af pakker. For eksempel:
- Debian/Ubuntu: apt-get clean && rm -rf /var/lib/apt/lists/*
- CentOS/RHEL: yum clean all eller dnf clean all
- Alpine: rm -rf /var/cache/apk/*
- Omfavn flertrinsbyggeri: Dette er en af de mest effektive måder at reducere billedstørrelsen på, især for kompilerede sprog eller applikationer med byggetrin (som JavaScript-frontends).
- Koncept: Brug én fase (en FROM-blok) med alle dine byggeværktøjer og udviklingsafhængigheder til at kompilere/bygge din applikation. Start derefter en ny fase fra et minimalt runtime-basisbillede og brug COPY– from=
kun at kopiere de nødvendige kompilerede artefakter til denne sidste, rene fase. - Eksempel (forenklet Go-applikation): Dockerfile
- Koncept: Brug én fase (en FROM-blok) med alle dine byggeværktøjer og udviklingsafhængigheder til at kompilere/bygge din applikation. Start derefter en ny fase fra et minimalt runtime-basisbillede og brug COPY– from=
Dockerfile
# Trin 1: Byg
FRA golang:1.20 SOM builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# Trin 2: Kørselstid
FRA debian:bullseye-slim
WORKDIR /app
COPY –from=builder /app/myapp .
CMD [“./myapp”]
- Builder-fasen har Go SDK'et, men det endelige billede indeholder kun den kompilerede binære fil og det minimale Alpine OS.
- Prioriter sikkerhed:
- Kør som en ikke-root-bruger: Som standard kører containere som root. Dette er en sikkerhedsrisiko. Opret en dedikeret, ikke-privilegeret bruger og gruppe i din Dockerfile, og brug USER-instruktionen til at skifte til den. Dockerfile
Dockerfile
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# … KOPIÉR filer og hent dem til appuser:appgroup …
BRUGER appuser
- Installer kun nødvendige pakker: Enhver pakke er en potentiel sårbarhed. Undgå at installere fejlfindingsværktøjer eller udviklingsværktøjer i produktionsbilleder (brug flertrins-builds til dette).
- Undgå hardcode-hemmeligheder: Undgå at placere adgangskoder, API-nøgler eller andre hemmeligheder i din Dockerfile (f.eks. i ENV-variabler). Brug runtime-injektionsmetoder som Docker-hemmeligheder, Kubernetes-hemmeligheder eller miljøvariabler, der leveres sikkert under kørsel.
- Brug .dockerignore effektivt: Opret en .dockerignore-fil i roden af din build-kontekst (på samme niveau som din Dockerfile). Angiv filer og mapper, der skal udelukkes fra at blive sendt til Docker-daemonen (f.eks. .git, node_modules hvis installeret i imaget, lokale IDE-konfigurationer, *.log).
- Fordele: Fremskynd Docker -byggeprocessen ved at reducere størrelsen på byggekonteksten og forhindre følsomme eller unødvendige filer i at blive inkluderet i dit billede.
Ud over det grundlæggende: Yderligere forbedringer

Når du er blevet fortrolig med ovenstående, kan du overveje disse for endnu bedre Dockerfiles:
- BuildKit: Dockers nyere build-motor, ofte aktiveret som standard. Den tilbyder bedre ydeevne (parallelle builds), forbedret caching og avancerede funktioner som build-hemmeligheder (RUN– mount=type=secret,…) og cache-mounts (RUN– mount=type=cache,…) til pakkeadministratorer. Sørg for, at den er aktiv, eller aktiver den med DOCKER_BUILDKIT=1.
- Linting af Dockerfiles: Brug værktøjer som Hadolint (hadolint Dockerfile) til at analysere din Dockerfile statisk for fejl, stilbrud og overholdelse af bedste praksis, før du bygger.
Almindelige hurtige tips til fejlfinding
- "Fil ikke fundet" under KOPIERING eller TILFØJELSE : Dobbelttjek kildestien (den er relativ til byggekontekstens rod), og sørg for, at filen ikke er udeladt af .dockerignore.
- Langsomme builds: Gennemgå instruktionsrækkefølgen for cacheoptimering. Kombinér RUN-kommandoer, hvor det er muligt. Sørg for, at din .dockerignore er omfattende.
- Store billeder: Brug flertrins-builds! Ryd op i RUN-lag. Vælg minimale basisbilleder.
Dockerfiles i din DevOps-workflow
En Dockerfile er et centralt element i "Infrastruktur som kode"
- Versionskontrol: Commit altid din Dockerfile til dit Git-repository sammen med din applikationskode.
- CI/CD-integration: Automatiser din Docker-build- og image-pushing-proces i dine Continuous Integration/Continuous Delivery-pipelines (f.eks. GitHub Actions, Jenkins, GitLab CI). Dette sikrer ensartede og gentagelige builds og implementeringer.
Konklusion: At skabe et fundament for succes
Oprettelse af effektive Dockerfiles er en investering, der giver betydelige fordele i udviklingshastighed, driftssikkerhed og applikationssikkerhed. Ved at mestre grundlæggende instruktioner, implementere bedste praksis såsom flertrins-builds og omhyggelig styring af billedlag samt prioritere sikkerhed, kan du producere Docker-billeder, der er strømlinede, effektive og robuste.
Denne guide giver et solidt fundament. Fortsæt med at udforske, eksperimentere og forfine dine Dockerfiles, mens du fortsætter din Docker-rejse.
Klar til at forbedre dine Docker- og DevOps-praksisser?
Hos Seahawk Media specialiserer vi os i at hjælpe virksomheder med at udnytte det fulde potentiale af containerisering, cloudteknologier og strømlinede CI/CD-pipelines. Vores ekspertteam er her for at hjælpe, hvis du vil optimere dine applikationsimplementeringer, forbedre sikkerheden eller accelerere din udviklingslivscyklus.