ЁЯП╖я╕П рдзрдбрд╛ 08 тАФ рдЗрдореЗрдЬрдЪреА рд╕реНрд╡рдЪреНрдЫрддрд╛: рдбрдмреНрдпрд╛рдВрд╡рд░ рд▓реЗрдмрд▓ рд▓рд╛рд╡рд╛, рдХрд┐рд▓реНрд▓реНрдпрд╛ рдкреЕрдХ рдХрд░реВ рдирдХрд╛
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 08 тАФ рднрд╛рдЧ 1 рдЪрд╛ рд╢реЗрд╡рдЯ! ┬╖ рдорд╛рдЧреЗ: lesson-07-multi-stage ┬╖ рдкреБрдвреЗ: lesson-09-registries
ЁЯФЧ AWS рд╢реА рд╕рдВрдмрдВрдз: IAM рдЖрдгрд┐ least privilege тАФ container рд╣реА рд╕реБрджреНрдзрд╛ рдПрдХ рдУрд│рдЦ (identity) рдЖрд╣реЗ, рдЬрд┐рдЪреНрдпрд╛рдХрдбреЗ рдХрдореАрдд рдХрдореА рдЕрдзрд┐рдХрд╛рд░ рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗрдд (AWS рд╢рд╛рд│рд╛, рдзрдбреЗ 03 рдЖрдгрд┐ 05).
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ07, рдЖрдгрд┐ рддреНрдпрд╛рд╢рд┐рд╡рд╛рдп: image рд▓рд╛ production-grade рдмрдирд╡рдгрд╛рд▒реНрдпрд╛ рдЪрд╛рд░ рд╕рд╡рдпреА. рдЦрд▒реНрдпрд╛ files:
- app/.dockerignore тАФ build-context рдЪреНрдпрд╛ рджрд╛рд░рд╛рд╡рд░рдЪрд╛ рд░рдЦрд╡рд╛рд▓рджрд╛рд░
- app/Dockerfile тАФ
USER nodeрдЖрдгрд┐ pin рдХреЗрд▓реЗрд▓рд╛ base, рдЖрдзреАрдЪ рдЬрд╛рдЧреЗрд╡рд░
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдбрдмреНрдпрд╛рдВрд╕рд╛рдареА рд╢рд╛рд│реЗрдЪреЗ рдЪрд╛рд░ рдирд┐рдпрдо:
- рдбрдмреНрдпрд╛рдВрд╡рд░ рдиреАрдЯ рд▓реЗрдмрд▓ рд▓рд╛рд╡рд╛ ЁЯП╖я╕П тАФ рдлрдХреНрдд "рд╕рд░реНрд╡рд╛рдд рдирд╡рд╛" рдирд╛рд╣реА, рддрд░ "рдРрд╢реНрд╡рд░реНрдпрд╛, рдордВрдЧрд│рд╡рд╛рд░, рд╡рд░рдг-рднрд╛рдд"
рдЕрд╕реЗ рд▓рд┐рд╣рд╛. рдХрд╛рд░рдг "рд╕рд░реНрд╡рд╛рдд рдирд╡рд╛" рдЪрд╛ рдЕрд░реНрде рд░реЛрдЬ рдмрджрд▓рддреЛ! Docker рдордзреНрдпреЗ:
hello-school:v1рдХрд┐рдВрд╡рд╛:abc123(рдПрдХ git commit), production рдордзреНрдпреЗ рдХрдзреАрд╣реА:latestрд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рд░рд╛рд╣реВ рдирдХрд╛ тАФ "latest" рдХрдбреЗ rollback рдХрд░рддрд╛ рдпреЗрдд рдирд╛рд╣реА, рдЖрдгрд┐ рдХрд╛рд▓ рддреЗ рдХрд╛рдп рд╣реЛрддреЗ рддреЗ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрдзреАрдЪ рдХрд│рдд рдирд╛рд╣реА. (k8s рдЖрдгрд┐ ArgoCD рджреЛрдиреНрд╣реА рдХреЛрд░реНрд╕ рдпрд╛ рдирд┐рдпрдорд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЖрд╣реЗрдд.) - рдШрд░рд╛рдЪреНрдпрд╛ рдХрд┐рд▓реНрд▓реНрдпрд╛ рдкреЕрдХ рдХрд░реВ рдирдХрд╛ ЁЯЩИ тАФ рдбрдмреНрдпрд╛рдд рдХрд╛рдп рдЬрд╛рддреЗ рддреЗ рдЖрдИ рддрдкрд╛рд╕рддреЗ.
.dockerignore.git,.env, secrets рдЖрдгрд┐ рдХрдЪрд░рд╛COPYрдЪреНрдпрд╛ рдЖрд╡рд╛рдХреНрдпрд╛рдмрд╛рд╣реЗрд░ рдареЗрд╡рддреЗ. рдзрдбрд╛ 02 рдЖрдард╡рд╛: рдерд░рд╛рдд рдЬреЗ рдЬрд╛рддреЗ рддреЗ рдХреЗрдХрдордзреНрдпреЗ рдХрд╛рдпрдордЪреЗ рд░рд╛рд╣рддреЗ тАФ "delete рдХреЗрд▓реЗрд▓реНрдпрд╛" files рд╕реБрджреНрдзрд╛ рдЖрдзреАрдЪреНрдпрд╛ рдерд░рд╛рдВрдд рдЬрд┐рд╡рдВрдд рд░рд╛рд╣рддрд╛рдд. - рдбрдмрд╛ рдореБрд▓реАрдЪрд╛ рдЖрд╣реЗ, рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХрд╛рдВрдЪрд╛ рдирд╛рд╣реА ЁЯСд тАФ
USER node. рдПрдЦрд╛рджрд╛ рдЧреБрдВрдб root container рдордзреНрдпреЗ рдШреБрд╕рд▓рд╛, рддрд░ рддреЛ рддреНрдпрд╛ рдбрдмреНрдпрд╛рдЪрд╛ (рдЖрдгрд┐ рдХрджрд╛рдЪрд┐рдд рд╢рд╛рд│реЗрдЪрд╛рд╣реА) рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрдХ рдмрдирддреЛ.node-user рдбрдмреНрдпрд╛рдд рдШреБрд╕рд▓рд╛? рддреЛ рдлрдХреНрддтАж рдмрд╛рдХрд╛рд╡рд░ рдмрд╕рд▓реЗрд▓реЗ рдПрдХ рдореВрд▓ рдЕрд╕рддреЛ. - рдлрдХреНрдд рдЫреЛрдЯреЗ рдбрдмреЗ ЁЯк╢ тАФ рдкреВрд░реНрдг
node:20рдРрд╡рдЬреАnode:20-alpine/-slimрд╡рд╛рдкрд░рд╛. рд▓рд╣рд╛рди base image рдореНрд╣рдгрдЬреЗ рдХрдореА pull, рдХрдореА patch, рдЖрдгрд┐ рд╢рдХреНрдпрддреЛ рд╣рд▓реНрд▓реНрдпрд╛рдЪреА рдЬрд╛рдЧрд╛ рдХрдореА (рдЦрд░реЗ рдЖрдХрд╛рд░docker imagesрдиреЗ рддрдкрд╛рд╕рд╛ тАФ рддреЗ releases рдиреБрд╕рд╛рд░ рдмрджрд▓рддрд╛рдд). Versions pin рдХрд░рд╛:FROM node:20-alpine, рдХрдзреАрд╣реА рдлрдХреНрддFROM nodeрдирд╛рд╣реА.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart TB
subgraph rules["ЁЯП╖я╕П the hygiene checklist"]
r1["1 real tags: v1, git-sha<br/>never :latest in prod"]
r2["2 .dockerignore:<br/>.git, .env, node_modules<br/>COPY can't leak what it can't see"]
r3["3 USER node<br/>root container = root problems"]
r4["4 small, pinned bases<br/>alpine/slim, versioned"]
end
good["тЬЕ boring, predictable,<br/>production-grade image"]
r1 --> good
r2 --> good
r3 --> good
r4 --> good
тЭУ рдХрд╛рдп
- Tags рд╣реЗ mutable pointers рдЖрд╣реЗрдд тАФ
:latestрдореНрд╣рдгрдЬреЗ рдХреЛрдгреАрддрд░реА рд╢реЗрд╡рдЯреА рд╣рд▓рд╡рд▓реЗрд▓рд╛ рдлрдХреНрдд рдПрдХ tag. Deploys рдиреЗ рдиреЗрдордХреНрдпрд╛ version рдЪрд╛ рд╕рдВрджрд░реНрдн рджреНрдпрд╛рдпрд▓рд╛ рд╣рд╡рд╛ (ECR рддрд░ tag overwrites рдордирд╛рдИ рд╣реА рдХрд░реВ рд╢рдХрддреЗ тАФIMMUTABLE, рдзрдбрд╛ 10). - Build context = COPY рд▓рд╛ рдЬреЗ рджрд┐рд╕реВ рд╢рдХрддреЗ рддреЗ рд╕рдЧрд│реЗ.
.dockerignoreрддреЗ рд▓рд╣рд╛рди рдХрд░рддреЗ: рдЬрд▓рдж builds, рдЪреБрдХреВрди secrets рдирд╛рд╣реАрдд, рдХрдЪрд▒реНрдпрд╛рдЪреНрдпрд╛ files рдореБрд│реЗ cache рддреБрдЯрдд рдирд╛рд╣реА. - Secrets рдХрдзреАрд╣реА рдерд░рд╛рдВрдд рдЬрд╛рдд рдирд╛рд╣реАрдд тАФ
COPYрдордзреНрдпреЗ рдирд╛рд╣реА,ENVрдордзреНрдпреЗ рдирд╛рд╣реА, "рдирдВрддрд░ delete рдХреЗрд▓реЗ" рдЕрд╕реЗрд╣реА рдирд╛рд╣реА. Runtime env vars (-e, k8s Secrets) рдиреЗрдордХреЗ рдпрд╛рдЪрд╕рд╛рдареА рдЖрд╣реЗрдд. - Default рдиреЗ non-root:
nodeimages рд╕реЛрдмрдд рддрдпрд╛рд░nodeuser рдпреЗрддреЛ; рдЕрдиреЗрдХ images рдордзреНрдпреЗ рдЕрд╕реЗрдЪ рдХрд╛рд╣реАрддрд░реА рдЕрд╕рддреЗ, рдирд╛рд╣реАрддрд░adduserрдиреЗ рд╕реНрд╡рддрдГрдЪрд╛ рдЬреЛрдбрд╛.
ЁЯза рд╣рд╛ рднрд╛рдЧ 1 рдЪрд╛ security рдзрдбрд╛ рдЖрд╣реЗ
Image рд▓рд╛ incident рдмрдирдгреНрдпрд╛рдкрд╛рд╕реВрди рд░реЛрдЦрдгрд╛рд░реА рдпрд╛рджреА:
- рд╕рдЧрд│реЗ рдЦрд╛рдЬрдЧреА
.dockerignoreрдордзреНрдпреЗ тАФ build context рдореНрд╣рдгрдЬреЗCOPYрд▓рд╛ рджрд┐рд╕рдгрд╛рд░реЗ рд╕рдЧрд│реЗ .env, SSH keys, cloud credentials рдХрдзреАрд╣реА copy рдХрд░реВ рдирдХрд╛ тАФ рдерд░рд╛рддрд▓реЗ secret image рдордзреНрдпреЗ рдХрд╛рдпрдордЪреЗ рд░рд╛рд╣рддреЗ, рдирдВрддрд░рдЪреНрдпрд╛ рдерд░рд╛рдиреЗ рддреЗ "delete" рдХреЗрд▓реЗ рддрд░реАрд╣реА- AWS credentials images рдордзреНрдпреЗ bake рдХрд░реВ рдирдХрд╛ тАФ рдорд╢реАрдирдирд╛ roles рдорд┐рд│рддрд╛рдд (AWS рд╢рд╛рд│рд╛, рдзрдбрд╛ 05), keys рдХрдзреАрдЪ рдирд╛рд╣реА
ARG/ENVрдордзреНрдпреЗ secrets рдирд╛рд╣реАрдд тАФ рджреЛрдиреНрд╣реА image metadata рдордзреНрдпреЗ рдЬрд╛рддрд╛рдд (docker historyрддреЗ рджрд╛рдЦрд╡рддреЗ)- non-root рдореНрд╣рдгреВрди рдЪрд╛рд▓рд╡рд╛ (
USER node) тАФ рдЖрдд root рдордзреНрдпреЗ рдШреБрд╕рдЦреЛрд░реА рдореНрд╣рдгрдЬреЗ host рдЪреНрдпрд╛ user namespace рдордзреНрдпреЗ рдШреБрд╕рдЦреЛрд░реА - base images рд╡рд┐рдЪрд╛рд░рдкреВрд░реНрд╡рдХ рдирд┐рд╡рдбрд╛ рдЖрдгрд┐ pin рдХрд░рд╛ тАФ
node:20-alpine,nodeрдирд╛рд╣реА - images scan рдХрд░рд╛ (ECR scan-on-push, рдзрдбрд╛ 11;
docker scout) рдЖрдгрд┐ рдЧрд░рдЬ рдирд╕рд▓реЗрд▓реЗ packages рдХрд╛рдврд╛
тЭМ COPY . . тЖТ accidentally copies .env and .git
тЬЕ .dockerignore: .env .git node_modules *.pem тЖТ COPY can't leak what it can't see
ЁЯдФ рдХрд╛
рдЗрдерд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдо рдПрдЦрд╛рджреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЦрд░реА рдШрдЯрдирд╛ рдЯрд╛рд│рддреЛ: rollback рди рдХрд░рддрд╛ рдпреЗрдгрд╛рд░реЗ deploys (:latest), leak рдЭрд╛рд▓реЗрд▓реЗ credentials (image рдордзреНрдпреЗ context/git), container-escape рдЪрд╛ blast radius (root), рдЖрдгрд┐ CVEs рд╕рд╛рдард╡рдгрд╛рд▒реНрдпрд╛ gigabyte images. рднрд╛рдЧ 2 images рдЕрд╢рд╛ registry рдХрдбреЗ рдкрд╛рдард╡рддреЛ рдЬреНрдпрд╛рд╡рд░ рдЗрддрд░ рдорд╢реАрди рд╡рд┐рд╢реНрд╡рд╛рд╕ рдареЗрд╡рддрд╛рдд тАФ hygiene рдореБрд│реЗрдЪ рддреЛ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдпреЛрдЧреНрдп рдард░рддреЛ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
# 1) prove .dockerignore works тАФ try to leak a "secret":
echo "SECRET_KEY=dont-pack-me" > app/.env
docker build -t hygiene-test app/
docker run --rm hygiene-test ls -a # no .env in the box ЁЯЩЕ (it's ignored)
rm app/.env
# 2) prove we're not root:
docker run --rm hello-school:v1 whoami # node ЁЯСд
# 3) feel the tag rule:
docker tag hello-school:v1 hello-school:latest
docker tag hello-school:v1 hello-school:2026-09-09
docker image ls hello-school # 3 labels, ONE image (same ID) тАФ
# tags are stickers, not copies
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
.env(рдХрд┐рдВрд╡рд╛ рд╕рдВрдкреВрд░реНрдг repo) image рдордзреНрдпреЗ copy рдХрд░рдгреЗ тАФ рддреЗ рдерд░рд╛рдд рдХрд╛рдпрдордЪреЗ рд░рд╛рд╣рддреЗARG/ENVрдордзреНрдпреЗ secrets bake рдХрд░рдгреЗ тАФ рддреЗdocker historyрдиреЗ рд╡рд╛рдЪрддрд╛ рдпреЗрддрд╛рдд- рдХрд╢рд╛рд▓рд╛рд╣реА рдЧрд░рдЬ рдирд╕рддрд╛рдирд╛ production containers root рдореНрд╣рдгреВрди рдЪрд╛рд▓рд╡рдгреЗ
:latestdeploy рдХрд░рдгреЗ тАФ рд╣рд▓рддреНрдпрд╛ tag рдХрдбреЗ rollback рдХрд░рддрд╛ рдпреЗрдд рдирд╛рд╣реА
тПня╕П рдкреБрдвреЗ тАФ рднрд╛рдЧ 2 рд╕реБрд░реВ тШБя╕П
рддреБрдордЪреА image рд▓рд╣рд╛рди, рд╕реНрд╡рдЪреНрдЫ, рд▓реЗрдмрд▓ рд▓рд╛рд╡рд▓реЗрд▓реА рдЖрд╣реЗтАж рдЖрдгрд┐ рддреБрдордЪреНрдпрд╛ laptop рд╡рд░ рдЕрдбрдХрд▓реЗрд▓реА рдЖрд╣реЗ. рдЖрддрд╛ рддреА рдЕрд╢рд╛ рдард┐рдХрд╛рдгреА рдкрд╛рдард╡реВрдпрд╛ рдЬрд┐рдереВрди рдкреНрд░рддреНрдпреЗрдХ рдорд╢реАрди pull рдХрд░реВ рд╢рдХреЗрд▓: registries.
git checkout lesson-09-registries