Prejsť na hlavný obsah
Python Tooling2026-11-01 · 11 min čítania

Docker pre Python v roku 2026: Moderný uv + viacstupňový sprievodca zostavením

Otvorte ľubovoľný päťročný návod „Dockerize your Python app“ a nájdete rovnaké štyri riadky: FROM python:3.11-slim, COPY requirements.txt ., RUN pip install -r requirements.txt, COPY . .. funguje to. Dodáva tiež obraz s veľkosťou viac ako 200 MB, prestavuje sa pomaly, pretože každá inštalácia závislosti je plná vyrovnávacia pamäť, keď sa zmení jeden riadok kódu aplikácie, a potichu vtiahne kompilátor C a hlavičkové súbory, ktorých sa váš spustený kontajner po dokončení zostavy už nikdy nedotkne.

Nič z toho už nie je potrebné. Medzi uv (správcom a inštalátorom balíkov založeným na Rust od spoločnosti Astral), pripojeniami vyrovnávacej pamäte BuildKit a základnými obrazmi distroless je predvolené nastavenie 2026 pre produkčný kontajner Python viacstupňové zostavenie, ktoré dodáva iba interpret Pythonu, vaše virtuálne prostredie a váš kód, nič iné. Táto príručka vás prevedie starým vzorom, novým vzorom a súborom Dockerfile, ktorý môžete dnes skopírovať do skutočného projektu.

Starý vzor a prečo je drahý

DOCKERFILE
FROM python:3.13-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "app.py"]

Tento model má tri náklady, ktoré sa zvyšujú s rastom projektu. Po prvé, python:3.13-slim sa už dodáva s veľkosťou približne 150 až 200 MB komprimovaný pred pridaním jednej závislosti, pretože „slim“ stále obsahuje úplnú používateľskú oblasť Debianu, apt a rozšírenia C štandardnej knižnice Pythonu. Po druhé, každá vrstva RUN pip install sa uloží do vyrovnávacej pamäte pomocou hash obsahu predchádzajúcich vrstiev Dockera, takže v app.py zmeňte jeden riadok pred COPY . . neruší nič upstream, ale zmena súboru requirements.txt zruší celý krok inštalácie a znova stiahne každé koleso. Po tretie, ak nejaká závislosť potrebuje natívne zostavenie (chýbajúce koleso manylinux, neobvyklá verzia balíka), pip potichu stiahne nástroje na zostavenie, ktoré potom navždy ostanú v konečnom obraze, pretože je len jedna fáza, do ktorej to môžete zahodiť.

Nový vzor: UV staviteľ plus záverečný stupeň bez distroly

Oprava je viacstupňová zostava: jedna fáza má kompilátor, uv a váš lockfile a druhá, oveľa menšia fáza, ktorá kopíruje iba hotové virtuálne prostredie a váš zdrojový strom. V poslednej fáze sa nikdy nezobrazí kompilátor pip, uv, apt alebo C.

DOCKERFILE
FROM python:3.13-slim AS builder COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=never WORKDIR /app RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv sync --frozen --no-install-project --no-dev COPY . /app RUN --mount=type=cache,target=/root/.cache/uv uv sync --frozen --no-dev FROM gcr.io/distroless/python3-debian12 COPY --from=builder /app /app WORKDIR /app ENV PATH="/app/.venv/bin:$PATH" ENTRYPOINT ["/app/.venv/bin/python", "-m", "app"]

gcr.io/distroless/python3-debian12 nemá žiadny shell, správcu balíkov ani pip, čo je presne to, čo chcete v produkcii: v kontajneri nezostane nič, čo by útočník, ktorý spustí kód, mohol použiť na stiahnutie ďalších nástrojov. Konečným obrazom sú balíky stránok vášho virtuálneho prostredia plus váš kód, ktorý pre typickú službu FastAPI pristane pod 50 MB namiesto 200 MB plus.

Pripojenia vyrovnávacej pamäte BuildKit: nikdy znova nesťahujte to isté koleso dvakrát

Riadok --mount=type=cache,target=/root/.cache/uv tu robí skutočnú prácu. Bez neho si každý „docker build“ na novom runneri znovu stiahne každé koleso z PyPI, pretože vyrovnávacia pamäť vrstiev prežije iba vtedy, ak sú predchádzajúce vrstvy vrátane „COPY uv.lock“ bajtovo identické. Pripojenie vyrovnávacej pamäte BuildKit je trvalý zväzok mimo grafu vrstvy: prežije naprieč zostavami na tom istom hostiteľovi alebo, s backendom vyrovnávacej pamäte registra, medzi spúšťačmi CI, aj keď sa súbor uzamknutia zmení. Spárujte ho s uv sync --frozen, ktorý sa odmieta dotknúť lockfile a hlasno zlyhá, ak pyproject.toml a uv.lock nie sú synchronizované, namiesto tichého riešenia iného stromu závislostí, než proti ktorému bežali vaše testy.

Oddelenie kroku uv sync --no-install-project od posledného uv sync je druhou polovicou triku: prvé volanie nainštaluje iba závislosti tretích strán (uložené do vyrovnávacej pamäte, pokiaľ sa uv.lock nezmení) a druhé volanie spustíme po COPY . /app, nainštaluje váš vlastný projekt bez opätovného zásahu do balíkov tretích strán. Zmeňte jeden riadok kódu aplikácie a vrstva závislosti zostane vo vyrovnávacej pamäti.

Natívne závislosti: numpy, vankúš a mnoholinuxový problém

Balíky ako numpy a Pillow dodávajú predpripravené mnoho linuxových kolies pre bežné platformy, takže na linux/amd64 alebo linux/arm64 uv sync normálne stiahne koleso a nikdy sa nedotkne kompilátora. Režim zlyhania sa objaví, keď používate neobvyklú architektúru, pripnete úplne nové vydanie skôr, ako sa dobehnú kolesá, alebo keď závisíte od balíka, ktorý dodáva iba zdrojovú distribúciu. V takom prípade fáza staviteľa potrebuje stavebné nástroje, posledná fáza nesmie nikdy vidieť:

DOCKERFILE
FROM python:3.13-slim AS builder RUN apt-get update && apt-get install -y --no-install-recommends build-essential \ && rm -rf /var/lib/apt/lists/* # uv + sync steps as in the stage above

build-essential (hlavičky gcc, make, libc) žije iba vo fáze vytvárača. Konečná fáza bez distroly kopíruje už skompilovaný .venv, nikdy nie kompilátor, ktorý ho vytvoril. Ak si chcete vyskúšať zostavenie a prepravu skutočnej kontajnerovej služby od konca do konca, kurz FastAPI prejde presne týmto druhom API, od prvého koncového bodu až po nasadenie v tvare produkcie.

Python spravovaný uv: zastavte sa v závislosti od akéhokoľvek interpreta, ktorý bol dodaný so základným obrazom

python:3.13-slim vám poskytne akékoľvek vydanie opravy, ktoré sa Debian rozhodol dodať tento týždeň. uv môže namiesto toho spravovať samotný interpret: uv python install 3.13.1 stiahne špecifickú, reprodukovateľnú zostavu CPythonu z projektu python-build-standalone a pripne ju do .python-version, takže vaša fáza zostavovateľa a váš laptop budú spúšťať presne ten istý interpret až po verziu opravy. V kombinácii s UV_PYTHON_DOWNLOADS=never v súbore Dockerfile, takže nesprávne pripnutá verzia nahlas zlyhá pri zostavovaní namiesto tichého sťahovania niečoho iného, ​​čím sa zatvorí medzera „funguje na mojom počítači, zlyhá na bežcovi“, ktorú plávajúca značka základného obrázka ponecháva otvorenú.

Ladenie kontajnera bez shellu

Jediná skutočná cena distroless: neexistuje žiadny shell, takže docker exec -it container sh nefunguje. Pre lokálne ladenie vytvorte rovnaký súbor Dockerfile s cieľom, ktorý sa zastaví vo fáze tvorcu (docker build --target=builder -t myapp:debug .), ktorý má stále úplnú užívateľskú krajinu a shell python:3.13-slim. Udržujte tento cieľ ladenia mimo vášho kanála nasadenia; existuje pre váš terminál, nie pre výrobu.

Šablóna s jedným súborom

DOCKERFILE
FROM python:3.13-slim AS builder COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=never WORKDIR /app RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv sync --frozen --no-install-project --no-dev COPY . /app RUN --mount=type=cache,target=/root/.cache/uv uv sync --frozen --no-dev FROM gcr.io/distroless/python3-debian12 COPY --from=builder /app /app WORKDIR /app ENV PATH="/app/.venv/bin:$PATH" ENTRYPOINT ["/app/.venv/bin/python", "-m", "app"]

Skopírujte toto, zmeňte názov modulu ENTRYPOINT tak, aby zodpovedal rozloženiu vášho projektu, a máte zostavu, ktorá je menšia, rýchlejšia pri opakovaných zostavách a ťažšie napadnuteľná ako vzor pip install -r requirements.txt, ktorý väčšina tutoriálov stále učí. Ste pripravení precvičiť si backend, ktorý sa nachádza vo vnútri tohto kontajnera? Začať s FastAPI.

Časté otázky

Potrebujem povolenú sadu BuildKit, aby pripojenie vyrovnávacej pamäte fungovalo?

Áno, --mount=type=cache je len funkcia BuildKit. Bol predvoleným tvorcom v Docker Desktop a nedávnych vydaniach Docker Engine, ale na starších CI runneroch možno budete musieť explicitne nastaviť DOCKER_BUILDKIT=1 alebo docker buildx build namiesto obyčajného docker build.

Prečo nepoužiť python:3.13-alpine na menší obrázok?

Musl libc od Alpine porušuje predpoklad manylinux wheel, na ktorý sa spoliehajú numpy, Pillow a väčšina kompilovaných balíkov, takže prídete o vopred zostavené kolesá a buď kompilujete zo zdroja, alebo narazíte na jemné runtime chyby. distroless-glibc sa tejto pasci vyhýba.

Nahrádza uv pip a poéziu úplne?

Pre väčšinu nových projektov áno. uv rieši a inštaluje rýchlejšie, číta rovnaký pyproject.toml a generuje lockfile, ale ak tím už závisí od pluginov Poetry alebo workflow uv ešte nepokrýva, nie je naliehavé migrovať v polovici projektu. Najprv vyskúšajte UV na novej službe.

Čo ak môj základný obrázok potrebuje bezpečnostnú opravu po tom, čo som už vytvoril obrázok?

Prestavať. Pripnite súhrn, nie len značku, pre python:3.13-slim vo fáze zostavovania a prestavba podľa plánu, týždenná je pre väčšinu tímov primeraná, takže opravený základný obrázok sa vleje do novej zostavy namiesto toho, aby niekoľko mesiacov ležal zastaraný.

Môžem použiť tento vzor pre projekt Django namiesto FastAPI?

Áno, súboru Dockerfile nezáleží na tom, ktorý rámec používate; zmení sa iba posledný VSTUP (napríklad gunicorn myproject.wsgi:application). Kurz FastAPI je rýchly spôsob, ako si precvičiť vzor od konca po koniec, ak začínate novú službu.

Je pripravená výroba bez distroless alebo je stále experimentálna?

Je široko používaný vo výrobe; Google ho spravuje a mnoho tímov ho dodáva ako svoju predvolenú základňu Python. Kompromisom za prijatie je absencia shellu, čo je zámerná bezpečnostná voľba, nie chyba.

Chcete to vyskúšať?

15 lekcií zdarma po bezplatnej registrácii – žiadna karta. Otestujte platformu a potom sa rozhodnite.

Začnite zadarmo →

Or unlock every lesson

Pro — $12/mo, unlimited AI, cancel any time. Refund within 14 days worldwide.

See Pro plans →

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.