Du kan køre Docker i produktion i flere måneder uden et synligt problem. Containere starter, apps reagerer, intet går i stykker. Så skaber en blotlagt port eller en forkert konfigureret tilladelse et fodfæste, som en angriber ikke behøvede at tjene. De fleste Docker-sikkerhedsfejl ligner ikke fejl, før noget går galt.
Denne artikel dækker de specifikke konfigurationer, der sætter containermiljøer i fare, hvad hver enkelt muliggør for en angriber, og afsluttes med en tjekliste, du kan køre mod din egen opsætning i dag.
Hvorfor Docker Security er sværere end det ser ud
Containere føles isolerede. Du starter en, den kører sit eget procesrum, og inde fra den eksisterer den næste container ikke. Du får isolation, men det er kun delvist. Containere deler værtens kerne, hvilket betyder, at en proces inde i en container under specifikke forhold kan nå hele værtssystemet.
Docker-skibe er konfigureret til udviklerens bekvemmelighed, ikke produktionshærdning. Root-adgang til. Alle porte kan bindes til alle grænseflader. Ingen køretidsovervågning. De fleste udviklere accepterer disse indstillinger, sender containeren og går videre. Det er en rimelig tilgang til at komme i gang; det er ikke en færdig sikkerhedsstilling.
Ifølge Red Hats 2024 State of Kubernetes Security-rapport, 67 % af organisationerne forsinkede eller forsinkede implementeringen af applikationer på grund af container- eller Kubernetes-sikkerhedsproblemer. Den friktion er normalt ikke fra angreb. Det er fra hold, der opdagede, at deres containeropsætninger trængte til hærdning, som de ikke havde indbygget.
Vi ser ofte containere køre i produktion med den samme konfiguration, som de havde på en udviklers lokale maskine. Det er her, Docker-sikkerhedsfejl har en tendens til at forværres stille og roligt uden synlige symptomer, indtil noget er revideret eller fejler.
De fejl, der skaber disse huller, er specifikke, forudsigelige og for det meste undgåelige, startende på konfigurationsniveauet.
Almindelige Docker-konfigurationsfejl
De fleste containerbrud starter ikke med en nul-dages udnyttelse. De starter med et konfigurationssæt på dag ét uden megen tanke om netværkseksponering eller privilegieomfang.
Standard Docker-indstillinger er bygget til at fungere. Gabet mellem funktionelt og sikkert er, hvor Docker-containersikkerhedsrisici akkumuleres, især i selv-hostede opsætninger, der bliver implementeret og aldrig genbesøgt.
Vi ser ofte dette mønster: containere på offentlige IP-servere med portbindinger, brugerindstillinger og netværkskonfigurationer, præcis som de var ved den første implementering.
Kører containere som rod
Når du starter en Docker-container uden at angive en bruger, kører den som root. Det betyder, at enhver proces inde i containeren, inklusive din applikation, har rettigheder på rodniveau inden for containerens navneområde.

Rod inde i en beholder er ikke det samme som root på værten, men adskillelsen er ikke absolut. Privilegium-eskaleringsudnyttelser målrettet mod runtime, som den veldokumenterede runc CVE-2019-5736 og lignende runtime-fejl, kræver ofte en root-beholderproces for at lykkes.
Ikke-root-beholdere fjerner rodproceskravet, som disse udnyttelser er afhængige af, hvilket indsnævrer angrebsoverfladen betydeligt for denne sårbarhedsklasse, selvom de ikke helt eliminerer risikoen for beholderudslip.
Tilføjelse af et BRUGER-direktiv til din Dockerfile løser dette. Nogle officielle billeder sendes med en uprivilegeret bruger, som du kan aktivere med et BRUGER-direktiv, men mange er stadig som standard at roote uden nogen færdiglavet app-bruger. I disse tilfælde opretter du brugeren i Dockerfilen, før du skifter til den. For de fleste selv-hostede opsætninger fjerner denne enkelte ændring en hel kategori af eskaleringsrisiko.
Udsætter for mange havne for det offentlige internet
Når du udgiver en port med Docker, skriver Docker sine egne iptables-regler direkte. Disse regler kører før firewallregler på værtsniveau. Dette er en velkendt adfærd rapporteret af fællesskabet og dokumenteret i Dockers pakkefiltreringsvejledning, ikke en fejlkonfiguration, og det betyder, at UFW og lignende værktøjer ikke blokerer, hvad Docker allerede har åbnet.

Docker skriver direkte til iptables og omgår UFW- og firewalld-standarder på mange Linux-værter. Det betyder, at en port, der er bundet til 0.0.0.0, kan være offentlig tilgængelig, selv når din firewall ser ud til at være konfigureret. Cloud-sikkerhedsgrupper og DOCKER-USER-kæderegler kan stadig blokere denne trafik, så den faktiske eksponering afhænger af din specifikke netværksopsætning.
Bind tjenester til 127.0.0.1, hvor det er muligt, diriger offentlig vendt trafik gennem en omvendt proxy, og udgiv kun det, der virkelig kræver ekstern adgang. En omvendt proxy er den mest pålidelige måde at kontrollere, hvad der eksponeres uden for værten.
Ignorerer netværksisolation mellem containere
Enhver container på det netværk kan nå enhver anden container på den uden begrænsninger. Standardbroen anvender ingen trafikfiltrering mellem containere, der deler den, og de fleste opsætninger ændrer aldrig denne konfiguration.

Hvis en container bliver kompromitteret, bliver den åbne kommunikation en sideværts bevægelsesvej. En frontend-container kan nå en database, en intern API eller noget andet på det samme standardbro-netværk, selv når den adgang aldrig var tiltænkt.
Brugerdefinerede netværk giver dig eksplicit kontrol over, hvilke containere der kan kommunikere, men et enkelt brugerdefineret netværk, der deles af alle dine tjenester, tillader stadig gratis inter-container-trafik. Virkelig isolation kræver at lægge tjenester, der ikke skal tale sammen, på separate netværk. At slukke for standardbroen er startpunktet, ikke målstregen.
Med udsigt over Docker Socket
Docker-socket på /var/run/docker.sock er kontrolgrænsefladen for hele Docker-motoren. Montering af den i en container giver denne container direkte API-adgang til den dæmon, der kører på værten.

Med den adgang kan en container starte nye containere, montere værtsmapper, inspicere og ændre kørende containere og effektivt kontrollere værtsmaskinen. Angrebsoverfladen svarer til root på værten, hvorfor ethvert værktøj, der kræver socket-adgang, fortjener en omhyggelig evaluering.
I de fleste tilfælde er der sikrere alternativer: API'er med omfang eller Docker-administrationsværktøjer som ikke kræver stikkontakt. Docker-in-Docker har sine egne sikkerhedsmæssige og operationelle kompromiser og er ikke en ligetil erstatning.
Konfigurationsfejl skaber den første eksponering. Billed- og afhængighedsvalg bestemmer, hvordan eksponeringen forstærkes over tid.
Billed- og hemmelighedsfejl, der overlever containeren
Når du stopper en container, stopper konfigurationsfejlene inde i den med den. Når du genopbygger fra et billede, der bærer en sårbarhed eller en hardkodet legitimation, genstarter problemet med containeren. Fejl på billedniveau nulstilles ikke mellem implementeringer.
De rejser med billedet til alle miljøer, der trækker det, hvert register, der gemmer det, og hvert teammedlem, der kører det. Denne vedholdenhed gør billed- og hemmelighedshåndtering til en særskilt risikokategori, der er værd at revidere adskilt fra konfigurationen.
Vi ser ofte dette mønster: et billede valgt omhyggeligt ved projektstart og aldrig genopbygget siden, langsomt glidende fra den sikkerhedsgrundlinje, det oprindeligt repræsenterede.
Brug af upålidelige eller forældede billeder
Offentlige registre er åbne for alle. Ondsindede billeder er blevet distribueret gennem Docker Hub med kryptominere og bagdøre indlejret i laghistorikken, som fortsætter på tværs af containergenstarter. Bekræftelse, før du trækker sager, især for billeder fra uofficielle eller ukendte udgivere.

Det separate problem er forældethed. Et officielt billede, du tog for seks måneder siden og aldrig blev genopbygget siden, har akkumuleret upatchede Docker-sårbarheder med hver CVE, der er afsløret mod dens pakker. Billedet er ikke ødelagt. Det er bare ikke længere aktuelt.
Sonatypes 2024 State of the Software Supply Chain-rapport fandt ud af, at 95 % af tiden en sårbar komponent forbruges, er en fast version allerede tilgængelig, og 80 % af applikationsafhængighederne forbliver uopgraderet i over et år. Dette mønster er også relevant for Docker-basebilleder, da de er afhængige af de samme open source-pakker.
Brug officielle billeder fra bekræftede udgivere, og fastgør specifikke versionstags i stedet for at stole på "seneste". Byg en regelmæssig genopbygningskadence for at holde dine billeder opdaterede.
Hardcoding hemmeligheder i Dockerfiles og Compose Files
Legitimationsoplysninger skrevet ind i en Dockerfile ENV- eller ARG-instruktion, hårdkodet ind i en Compose-miljøblok, videregivet som build-argumenter eller gemt i en .env-fil, der er forpligtet til versionskontrol, forsvinder ikke, når du stopper containeren. De forbliver i billedlagshistorikken eller kildekontrollen, tilgængelige for alle, der kan nå enten.

Dette er en af de mest oversete Docker-sikkerhedsfejl, fordi det ikke forårsager synlige problemer under udvikling. En API-nøgle i en ENV-instruktion fungerer korrekt. Det er også i dit lager, indbygget i dit billede og distribueret overalt, hvor billedet rejser.
Modern Docker Compose understøtter en indbygget hemmelighedsmekanisme, der monterer legitimationsoplysninger under kørsel uden at bage dem ind i billedet. Docker's secrets API og eksterne hemmelighedsadministratorer følger samme princip. Dette er de muligheder, der holder legitimationsoplysninger helt ude af byggeartefakter og forpligtede filer.
Runtime-miljøvariabler er en forbedring i forhold til hårdkodede legitimationsoplysninger, men de er stadig afsløret gennem Docker-inspect-output, logfiler og crash-dumps. De er et skridt op fra indbagte hemmeligheder, ikke en færdig løsning.
Opdaterer ikke containerbilleder regelmæssigt
At køre det samme billede i flere måneder er en almindelig vane. Hver dag, der går efter, at en ny sårbarhed er afsløret, men før du genopbygger, har dine containere et eksponeringsvindue, der vokser uden nogen synlig ændring.
Byg en konsekvent genopbygningsplan. Automatiser denne proces, hvor det er muligt, og kør en sårbarhedsscanner med jævne mellemrum mod dine nuværende billeder. Målet er ikke perfektion. Det indsnævrer tiden mellem en patch frigives, og den bliver implementeret.
Adgangskontrol og overvågning kan blive deprioriteret i hurtige implementeringer. De er også de kategorier, hvor hændelser forbliver uopdaget længst.
Adgangskontrol og huller i synlighed
Når en container kører med en solid konfiguration og aktuelle billeder, er der to kategorier af fejl tilbage. Begge er usynlige af natur: du vil ikke bemærke et svagt adgangskontrolproblem, før nogen bruger det, og du vil ikke bemærke et overvågningsgab, før du skal undersøge aktivitet, der aldrig blev logget.
Det samme Red Hat 2024-forskning fandt, at 42 % af holdene manglede tilstrækkelige kapaciteter til at håndtere containersikkerhed og relaterede trusler.
Vi oplever, at overvågningshuller typisk dukker op under hændelsesundersøgelser, ikke før. Når synlighed bliver en prioritet, reagerer den ofte på noget i stedet for at forhindre det.
Svag autentificering og eksponerede administrationsdashboards
Et containerstyringsdashboard på en offentlig IP uden godkendelse kræver ikke en sofistikeret angriber. Det kræver, at de kender adressen. Det er en lavere bar end de fleste hold er klar over.

Selvhostede overvågnings- og administrationsværktøjer leveres typisk med en webgrænseflade, der er tilgængelig på alle netværksgrænseflader. At efterlade dem på en offentlig IP uden godkendelse foran dem svarer til en container, der svarer til at lade et adminpanel være ulåst.
Autentificering, en omvendt proxy og privat netværksplacering er basislinjen. Adgangskontrol er et konfigurationstrin, du tilføjer til enhver administrationsgrænseflade, ikke noget, der leveres aktiveret.
Det samme princip gælder for Docker CLI og GUI management; admin-niveau adgang til dæmonen indebærer den samme risiko uanset grænsefladen.
Overvåger ikke, hvad dine containere laver
Hvis en container kompromitteres, skaber angriberens aktivitet et spor: procesadfærdsændringer, usædvanlige netværksforbindelser og uventede filændringer. Uden logindsamling på plads eksisterer det spor ikke i en form, du kan handle på.
Centraliseret logindsamling, containerrevisionslogning og runtime-overvågningsværktøjer giver dig dataene til at detektere unormal aktivitet, før den sammensættes. Målet er ikke at analysere hver linje. Det er at have dataene tilgængelige, når du skal undersøge det.
Containeropsætninger, der kører lydløst i produktionen uden log-pipeline og ingen advarsler, er ikke vedligeholdelseskrævende. De er uinspicerede. Det er to forskellige operationelle tilstande.
Hvorfor infrastrukturmiljøet også betyder noget
Containersikkerhed starter med konfiguration, men konfiguration kører oven på infrastruktur. En vært med forkert konfigureret netværk, delte ressourcer eller ingen filtrering på netværksniveau skaber forhold, der påvirker hver container over den. At få containeropsætningen rigtigt og serverkonfigurationen rigtig er to separate opgaver.
Mange Docker-sikkerhedshuller forstærkes af forhold, som containerne selv arver:
- En server med delt lejemål uden hardwareisolering mellem lejere
- En værtskerne kører upatchet
- En vært uden indbygget filtrering på netværksniveau
Dette fjerner ikke behovet for konfigurationstrinene ovenfor, da korrekt beholderhærdning er vigtig uanset infrastrukturlaget. At starte på isoleret infrastruktur fjerner ét lag af bekymring fra ligningen.
Hos Cloudzy tilbyder vi to veje afhængigt af, hvad din opsætning kræver:
- Linux VPS: et rent miljø til selv at implementere Docker og anvende hærdningstrinene i denne artikel
- Portainer VPS: en mulighed med et enkelt klik med Portainer forudinstalleret; serveren starter, og du er allerede i dashboardet
Begge muligheder kører på den samme infrastruktur: KVM-virtualisering, AMD Ryzen 9 CPU'er med op til 5,7 GHz boost-clock, DDR5-hukommelse, NVMe SSD-lager, op til 40 Gbps netværk og gratis DDoS-beskyttelse via BuyVM-filtrering på tværs af 12 globale lokationer med en 99,95 % oppetid SLA.
For et dybere kig på at køre Portainer på en VPS, dækker vi det i en dedikeret artikel.
En praktisk sikkerhedstjekliste for Docker-implementeringer
Docker-sikkerhedsfejlene ovenfor kommer for det meste fra enkeltkonfigurationsbeslutninger, der er truffet én gang og aldrig genbesøgt. At køre denne tjekliste mod en eksisterende opsætning fanger disse huller. Det fungerer som en revision, ikke en implementeringsvejledning.
Disse Best Practices for Docker-sikkerhed dækker, hvordan du sikrer Docker-containere mod de mest almindelige konfigurationsfejl beskrevet ovenfor.
Hurtig reference: Alle 9 fejl
| Fejl | Kategori | One-line fix |
| Kører som root | Konfiguration | Tilføje BRUGER direktiv til din Dockerfile |
| Porte bundet til 0.0.0.0 | Konfiguration | Bind til 127.0.0.1 og rul gennem en omvendt proxy |
| Ingen netværksisolering | Konfiguration | Opdel tjenester på tværs af separate brugerdefinerede netværk baseret på adgangsbehov. |
| Docker fatning monteret | Konfiguration | Fjern beslaget; bruge scoped API'er eller alternativer |
| Upålidelige eller forældede billeder | Billede | Brug officielle billeder med fastgjorte versionstags |
| Hårdkodede hemmeligheder | Billede | Flyt legitimationsoplysninger til runtime env vars eller en hemmelighedsmanager |
| Ingen tidsplan for genopbygning af billeder | Billede | Indstil en månedlig genopbygningskadence; automatisere hvor det er muligt |
| Uautentificerede dashboards | Adgang | Tilføj godkendelse og flyt administrations-UI'er til private netværk |
| Ingen containerlogindsamling | Adgang | Opsæt centraliseret logning og runtime-overvågning |
Vi anbefaler at køre det mod eksisterende opsætninger først, da det er der, hvor hullerne med stor sandsynlighed allerede er til stede.
Containere, der kører som ikke-root: Tjek dine Dockerfiler for et BRUGERdirektiv. Hvis ingen eksisterer, kører containeren som root.
Portbindinger begrænset til localhost eller proxy: Kør docker ps og gennemse portbindinger. En 0.0.0.0:PORT-post kan være offentlig tilgængelig på værter, hvor ingen opstrøms sikkerhedsgruppe, ekstern firewall eller DOCKER-USER-kæderegel blokerer den.
Brugerdefinerede bro-netværk: Containere på Dockers standardbro kan frit nå hinanden. Containere på den samme brugerdefinerede bro kan stadig kommunikere med hinanden, så opdel tjenester på tværs af separate netværk efter tillidsgrænse for faktisk isolation.
Docker socket ikke monteret i containere: Marker Compose filer og kør argumenter. Hvis /var/run/docker.sock vises som et volumen, skal du bekræfte, at det er påkrævet og tilsigtet.
Base billeder fra bekræftede udgivere med fastgjorte versioner: En FROM ubuntu:nyeste trækker en uspecificeret, potentielt forældet version. Fastgør til en bestemt udgivelse.
Ingen hemmeligheder i Dockerfiles, Compose-filer eller build-argumenter: Billedlagshistorik bevarer legitimationsoplysninger efter containersletning. Brug Compose-hemmeligheder, Swarm-hemmeligheder, byg hemmelige mounts eller en ekstern hemmelighedsmanager. Runtime miljøvariabler er bedre end hårdkodede værdier, men vises stadig i inspektionsoutput og logfiler.
Billedgenopbygningsplan defineret: Gamle billeder akkumulerer sårbarheder. En månedlig genopbygningskadence holder eksponeringsvinduet håndterbart for de fleste opsætninger.
Administrationsgrænseflader bag godkendelse: Ethvert dashboard på en offentlig IP uden godkendelse er et åbent indgangspunkt. Privat netværksplacering er at foretrække, hvor det er muligt.
Containerlogfiler, der indsamles: Uden en log-pipeline afhænger hændelsesdetektion af synlig systempåvirkning. Det er et sent signal at handle på.
Konklusion
Dockers standardkonfiguration er bygget til bekvemmelighed, ikke sikkerhed. De fleste af de fejl, der er dækket i denne artikel, spores tilbage til indstillinger, der aldrig blev ændret efter den første implementering, ikke til sofistikerede angreb.
Rettelserne er for det meste engangskonfigurationsbeslutninger: et BRUGERdirektiv, en portbindingsændring, et brugerdefineret netværk, en genopbygningsplan. Ingen af dem kræver nyt værktøj til de fleste opsætninger.
At få containerkonfigurationen rigtigt er den første opgave. Infrastrukturen, den kører på, er den anden. Begge dele betyder noget, og ingen af dem erstatter den anden.