Hacker News

BuildKit: la joia oculta de Docker que pot construir gairebé qualsevol cosa

Comentaris

18 min read Via tuananh.net

Mewayz Team

Editorial Team

Hacker News

BuildKit: la joia oculta de Docker que pot construir gairebé qualsevol cosa

La majoria de desenvolupadors coneixen Docker com el temps d'execució del contenidor que va canviar la manera com s'envia el programari. Molts menys saben sobre el motor que taulen en silenci sota la superfície de cada construcció moderna de Docker: BuildKit, el sistema de construcció de nova generació que s'ha enviat amb Docker des de la versió 18.09 i es va convertir en el backend predeterminat a Docker 23.0. Mentre els enginyers discuteixen sense parar sobre les configuracions de Kubernetes i els patrons de microserveis, BuildKit ha anat evolucionant constantment cap a un dels sistemes de construcció més potents i flexibles de l'ecosistema DevOps. Si l'heu tractat com una construcció de docker més ràpida, esteu deixant una capacitat enorme sobre la taula. Les empreses que executen pipelines CI/CD d'alt rendiment han reduït els temps de construcció entre un 50 i un 70% simplement entenent què ofereix realment BuildKit, i això només és el principi.

Què fa que BuildKit sigui fonamentalment diferent del Classic Builder

El motor de compilació de Docker original executava instruccions de Dockerfile de manera seqüencial, una capa a la vegada, sense saber quin treball podia passar de manera segura en paral·lel. BuildKit substitueix aquest model d'execució lineal per un gràfic acíclic dirigit (DAG): un gràfic de dependència que entén quins passos de construcció depenen els uns dels altres i quins no. Les etapes independents s'executen simultàniament, les etapes no utilitzades es salten completament i la compilació sencera es converteix en una descripció declarativa del que voleu en lloc d'una seqüència imperativa de passos que heu de recitar en l'ordre correcte.

Aquest canvi arquitectònic té conseqüències pràctiques que van més enllà de la velocitat. Quan un Dockerfile de diverses etapes compila un binari Go en una etapa, baixa les dependències de Node.js en una altra i munta una imatge de producció en una tercera, BuildKit pot executar les dues primeres etapes simultàniament. Una construcció que abans trigava quatre minuts a un potent corredor CI ara es completa en menys de noranta segons. Stripe, Shopify i molts altres equips d'enginyeria a gran escala han documentat guanys similars en les seves retrospectives internes d'eines. El model DAG també significa que BuildKit pot generar metadades de compilació molt precises, una base per a funcions com ara les certificacions de procedència i la generació de la llista de materials de programari (SBOM) que són molt importants per a la seguretat de la cadena de subministrament.

També hi ha un canvi conceptual en com funciona la invalidació de la memòria cau. El constructor clàssic va invalidar totes les capes per sota de qualsevol instrucció modificada. BuildKit fa un seguiment dels hash de contingut a cada entrada, de manera que canviar un comentari en un Dockerfile no elimina una entrada de memòria cau que representa trenta minuts de compilació. Quan la vostra memòria cau de compilació és la diferència entre un bucle de comentaris de cinc minuts i un de quaranta minuts per al vostre equip d'enginyeria, aquesta precisió importa molt més del que podria semblar inicialment.

Construccions multiplataforma: una comanda, cada arquitectura

La marca --platform de

BuildKit i la integració de QEMU transformen el que abans va ser un dolorós problema de coordinació multisistema en una única comanda. L'execució de docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 . produeix tres imatges preparades per a la producció en paral·lel a partir d'una única invocació de compilació. Aquesta capacitat s'ha tornat fonamental a mesura que la indústria passa cap a ARM: les instàncies d'AWS Graviton3 ofereixen constantment un 40% de millor rendiment en càrregues de treball com ara el servei web i el processament de dades, i Apple Silicon ha fet d'ARM la màquina de desenvolupament predeterminada per a milions d'enginyers.

Abans que el suport multiplataforma de BuildKit maduri, mantenir canalitzacions de compilació separades per a diferents arquitectures era un veritable centre de costos. Els equips van mantenir diversos Dockerfiles, van executar canalitzacions CI separades en corredors d'arquitectura diferent o simplement van enviar imatges x86 a tot arreu i van pagar la penalització de rendiment a la infraestructura ARM. Amb BuildKit, definiu la vostra compilació una vegada i deixeu que el sistema gestioni la compilació específica de l'arquitectura de manera transparent. Projectes Rust que requereixen una compilació creuada, projectes Go amb dependències CGO, paquets Python amb extensions C: BuildKit gestiona la capa d'emulació sense requerir que entenguis els detalls de cada plataforma objectiu.

El valor comercial pràctic aquí és mesurable. Un equip que executa 200 contenidors a instàncies AWS Graviton a 0,04 dòlars per hora de vCPU en comparació amb la instància x86 equivalent a 0,056 dòlars per hora de vCPU estalvia aproximadament 11.520 dòlars anuals per cada 100 vCPU, només per triar l'arquitectura adequada. Fer que aquesta elecció sigui accessible sense un esforç de reenginyeria és exactament el tipus d'optimització de la infraestructura que es compensa immediatament.

Gestió secreta sense filtrar capes d'imatge

Una de les funcions de BuildKit més poc apreciades és la seva API de secrets. El creador clàssic de Docker no tenia cap manera neta de passar credencials a una compilació sense que aquestes credencials acabessin potencialment en una capa d'imatge. Els desenvolupadors van treballar per això amb compilacions en diverses etapes, instruccions ARG i ordres acurats, però el risc d'enfornar accidentalment una clau API o una clau privada SSH en una imatge enviada es va mantenir incòmode. Els escàners de seguretat troben habitualment credencials codificades en imatges de contenidors publicades als registres públics, i moltes d'aquestes filtracions es remunten directament a la manipulació maldestra de secrets durant les compilacions.

La marca --secret de

BuildKit munta les dades confidencials a l'entorn de compilació com una ruta temporal del sistema de fitxers que només existeix durant la durada de la instrucció específica RUN que la necessita i mai no toca cap capa d'imatge. Una instrucció de Dockerfile com RUN --mount=type=secret,id=npmrc cat /run/secrets/npmrc > ~/.npmrc && npm install dóna accés al procés de construcció a les credencials privades de npm sense que aquestes credencials apareguin mai a la imatge final ni a cap capa intermèdia. El mateix patró funciona per a les credencials de PyPI, la configuració de Maven, les claus SSH per als dipòsits privats de Git i qualsevol altre material sensible que requereixi el vostre procés de creació.

Per als equips que creen programari que toca indústries regulades (plataformes sanitàries, productes fintech, programari de recursos humans), la diferència entre "les credencials poden estar a la imatge" i "les credencials no poden estar a la imatge" és la diferència entre passar una auditoria de seguretat i passar tres setmanes per corregir les troballes. Plataformes com Mewayz, que impulsen les operacions empresarials de més de 138.000 usuaris en sectors com ara nòmina, recursos humans i facturació, depenen exactament d'aquest tipus de postura de seguretat demostrable en els seus canals de creació i desplegament per mantenir la confiança que aquests clients tenen a les seves dades financeres i personals sensibles.

Exportacions de memòria cau: fer que les pipelines CI siguin realment ràpides

Les canalitzacions de CI són on més importa el rendiment de la creació i on l'experiència de compilació predeterminada de Docker ha estat històricament més dolorosa. Els corredors de CI nous solen començar amb memòria cau buides, és a dir, cada execució de pipeline recompila tot des de zero. Per a un servei Java amb centenars de dependències de Maven, un projecte Rust o una aplicació Python amb grans extensions natives, això significa temps de construcció mesurats en desenes de minuts en lloc de segons. El cost empresarial de l'IC lent és enorme: la freqüència de desplegament reduïda, els bucles de retroalimentació més llargs i els enginyers estan inactius esperant que finalitzin les canonades abans de poder fusionar-se i seguir endavant.

La funció d'exportació de memòria cau de BuildKit soluciona això amb manifests de memòria cau exportables. Utilitzant --cache-to type=registry,ref=myregistry/myapp:cache i --cache-from type=registry,ref=myregistry/myapp:cache, BuildKit envia una instantània detallada de la memòria cau a un registre després de cada compilació i l'extrau al començament de la següent. La memòria cau s'adreça al contingut, de manera que només es tornen a recuperar les capes realment canviades. Els equips que utilitzen aquest patró a GitHub Actions, GitLab CI i CircleCI redueixen habitualment els temps de canalització de quinze minuts a menys de tres en execucions posteriors. La pròpia documentació de GitHub sobre els fluxos de treball avançats de compilació de Docker recomana aquest patró exactament per aquest motiu.

La compilació més ràpida és la que no haureu de tornar a executar. El sistema de memòria cau en capes i adreçat al contingut de BuildKit no només accelera les compilacions, sinó que fa que tot el concepte de "construcció" sigui més intel·ligent, convertint una compilació repetida en una diferència incremental del que ha canviat exactament.

Les exportacions de memòria cau també s'integren clarament amb els fluxos de treball de desenvolupament basats en branques. Podeu configurar la vostra canalització CI per retrocedir des d'una memòria cau específica de la branca a la memòria cau de la branca principal quan no hi hagi cap memòria cau de la branca, el que significa que les noves branques es beneficien immediatament de la memòria cau calenta acumulada per la vostra línia de desenvolupament principal. Els enginyers reben comentaris ràpids des de la primera vegada que es comprometen a una nova sucursal en lloc d'esperar una penalització d'arrencada en fred.

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Start Free →

Interfaces de BuildKit: construcció més enllà dels fitxers Docker

Potser la capacitat menys coneguda de BuildKit és que els Dockerfiles són només un format d'entrada possible, no l'únic. BuildKit té una arquitectura frontal connectable que permet llenguatges i formats de definició de compilació totalment personalitzats. L'interfície s'especifica per la directiva # syntax= a la part superior del fitxer de compilació, que diu a BuildKit que extreu una imatge d'interfície concreta i l'utilitzi per analitzar i executar la resta del fitxer.

Aquesta arquitectura ha permès diversos projectes atractius. La integració de Buildpacks permet a BuildKit crear imatges de contenidors a partir del codi font de l'aplicació sense cap fitxer Dockerfile: detecta l'idioma, tria imatges base adequades i munta automàticament un contenidor llest per a la producció. HPC i les comunitats d'informàtica científica han utilitzat interfícies personalitzades per descriure les compilacions en llenguatges específics del domini que es compilen fins a la representació interna de LLB (Low-Level Build) de BuildKit. La interfície de sintaxi docker/dockerfile:labs experimenta amb funcions com ara el suport heredoc, el control --network per instrucció i consells de memòria cau millorats abans que arribin a una sintaxi estable de Dockerfile.

La possibilitat de definir la vostra pròpia interfície també significa que les organitzacions amb requisits de creació inusuals no han de triar entre "aplicar-ho tot a la sintaxi de Dockerfile" i "abandonar els contenidors completament". Un microprogramari FPGA de creació d'equips, imatges de sistemes incrustats o contenidors de models ML especialitzats poden descriure la seva construcció en termes que tinguin sentit per al seu domini, alhora que produeixen imatges de contenidors estàndard compatibles amb OCI que es despleguen a qualsevol lloc on s'executen els contenidors. Aquesta extensibilitat és un autèntic avantatge arquitectònic respecte als sistemes de construcció que tracten el seu format d'entrada com a fix.

Procedència i SBOM: Construcció per al món post-SolarWinds

La seguretat de la cadena de subministrament de programari va passar de la preocupació teòrica a la prioritat a nivell de la junta després de l'incompliment de SolarWinds el 2020 i la vulnerabilitat de Log4Shell el 2021. L'Ordre executiva 14028 del govern dels EUA sobre ciberseguretat, emesa el maig de 2021, va obligar als contractistes federals de material de programari. Les certificacions de procedència de BuildKit i les funcions de generació de SBOM són una resposta directa a aquest panorama regulador i de seguretat.

Amb els senyaladors --provenance=true i --sbom=true, BuildKit genera testimonis signats criptogràficament que descriuen exactament què va entrar a una imatge de contenidor: quines imatges base es van utilitzar, quines instruccions Dockerfile van executar, quins fitxers font estaven presents i quines dependències externes es van obtenir. Aquestes certificacions segueixen el marc SLSA (Supply-chain Levels for Software Artifacts) i el format d'atestació integral, cosa que els fa verificables per màquina per motors de polítiques com Cosign i OPA (Open Policy Agent) de Sigstore.

El flux de treball pràctic que permet això és el següent:

  1. El desenvolupador envia codi; El pipeline CI activa una compilació BuildKit amb la procedència activada.
  2. BuildKit genera un SBOM signat que enumera tots els components i les seves versions.
  3. El SBOM es publica al registre de contenidors juntament amb el manifest de la imatge.
  4. Els controladors d'admissió del clúster de Kubernetes verifiquen la procedència abans de permetre el desplegament.
  5. Els escàners de vulnerabilitats consulten el SBOM per identificar les imatges afectades quan es revelen nous CVE.

Els equips que implementen aquesta canalització completa poden respondre a les revelacions de vulnerabilitats en hores en lloc de dies, perquè disposen d'un mapa precís i llegible per màquina de cada component de cada contenidor en execució. Per a empreses com Mewayz que s'integren profundament en els fluxos de treball operatius dels clients (execució de nòmines, gestió de dades de la flota, processament de factures), la capacitat de demostrar una cadena de subministrament rigorosa i auditable és cada cop més un requisit previ per a les converses de vendes de l'empresa, no només una cosa agradable.

Com començar: des de les compilacions predeterminades fins a les canalitzacions avançades

BuildKit ja s'està executant al vostre entorn Docker si feu servir una versió recent: Docker 23.0 i posterior, activeu-lo de manera predeterminada. El primer pas pràctic per a la majoria dels equips és habilitar el connector Docker Buildx, que exposa tot el conjunt de funcions de BuildKit mitjançant la subordre docker buildx. L'execució de docker buildx create --use configura una instància del constructor BuildKit amb més capacitat que el controlador predeterminat. A partir d'aquí, l'adopció gradual de funcions avançades té sentit en lloc d'intentar adoptar-ho tot alhora.

Un camí d'adopció raonable per a un equip que actualment fa invocacions bàsiques de construcció de docker sembla afegir primer exportacions de memòria cau a CI; això ofereix millores de velocitat immediates i mesurables amb un canvi de configuració mínim. Les compilacions multiplataforma es tornen valuoses quan l'equip comença a orientar-se a la infraestructura ARM. Val la pena adoptar el muntatge secret cada cop que apareixen registres de paquets privats o claus SSH en el context de compilació. Les certificacions de procedència tenen sentit activar-les quan els requisits de compliment o les demandes dels clients de l'empresa fan necessària la documentació de la cadena de subministrament.

La lliçó més profunda de BuildKit tracta de construir deliberadament. Tant si envieu un contenidor per a un microservei, un punt final d'inferència d'aprenentatge automàtic o una plataforma complexa com la suite de 207 mòduls empresarials de Mewayz, el procés de creació no és una formalitat que us afanyeu en el camí del desplegament: és un artefacte d'enginyeria que reflecteix la qualitat, la postura de seguretat i la maduresa operativa de tot el que s'envia. BuildKit us ofereix les eines per fer que aquest artefacte sigui excel·lent. La pregunta és simplement si et prens el temps per utilitzar-los.

Preguntes més freqüents

Què és BuildKit i en què es diferencia del sistema de compilació clàssic de Docker?

BuildKit és el motor de compilació de nova generació de Docker, introduït a Docker 18.09 i que s'ha convertit per defecte a Docker 23.0. A diferència del constructor clàssic, BuildKit admet l'execució de capes paral·leles, estratègies avançades de memòria cau, muntatge de secrets i compilacions multiplataforma. Tracta el procés de creació com un gràfic acíclic dirigit (DAG), que permet una resolució de dependències més intel·ligent i temps de compilació molt més ràpids per a fitxers Dockerfiles complexos i de diverses etapes.

Necessito instal·lar alguna cosa addicional per començar a utilitzar BuildKit amb Docker?

No cal cap instal·lació addicional si esteu executant Docker 23.0 o posterior: BuildKit està habilitat per defecte. A les versions anteriors, podeu activar-lo configurant la variable d'entorn DOCKER_BUILDKIT=1 abans d'executar les vostres ordres de compilació. Per a casos d'ús avançats, com ara memòria cau de compilació remota o compilacions multiplataforma, és possible que vulgueu configurar una instància de constructor de Buildx dedicada mitjançant docker buildx create.

Es pot utilitzar BuildKit per crear artefactes més enllà d'imatges de contenidors estàndard?

Sí, i aquesta és una de les capacitats menys apreciades de BuildKit. Utilitzant interfícies personalitzades i la marca --output, BuildKit pot produir binaris en brut, tarballs, llocs web estàtics i altres artefactes de fitxer arbitraris, no només imatges OCI. Això el converteix en un motor de compilació de propòsit general que s'adapta de manera natural a monorepos políglots i canalitzacions CI complexes on diferents equips necessiten diferents formats de sortida d'una cadena d'eines unificada.

Com s'adapta BuildKit a una plataforma DevOps més àmplia juntament amb eines com Mewayz?

BuildKit gestiona la capa de compilació de baix nivell, però els equips de desenvolupament moderns també han de gestionar els fluxos de treball empresarials, el lliurament dels clients i els processos operatius. Plataformes com Mewayz, un sistema operatiu empresarial de 207 mòduls a partir de 19 dòlars al mes, complementen les eines d'infraestructura i cobreixen la part operativa de les empreses de programari. L'associació de canalitzacions de construcció eficients impulsades per BuildKit amb una plataforma tot en un com Mewayz ofereix als equips una pila completa, des de l'artefacte de codi fins al lliurament al client.