ЁЯз╣ рдзрдбрд╛ 11 тАФ Push, pull рдЖрдгрд┐ lifecycle: рдбрдмреЗ рдареЗрд╡рдгреЗ рдЖрдгрд┐ рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд░реА
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 11 ┬╖ рдорд╛рдЧреЗ: lesson-10-ecr-setup ┬╖ рдкреБрдвреЗ: lesson-12-ci-to-cloud
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ10, рдЖрдгрд┐ рддреНрдпрд╛рд╢рд┐рд╡рд╛рдп: ECR рдЪрд╛ рд░реЛрдЬрдЪрд╛ workflow тАФ рдкреВрд░реНрдг рдкрддреНрддреНрдпрд╛рдиреЗ tag рдХрд░рд╛, push рдХрд░рд╛, pull рдХрд░рд╛ тАФ рдЖрдгрд┐ рддреБрдордЪрд╛ locker рдЬреБрдиреНрдпрд╛ рдкреБрд░рд╛рдгреНрдпрд╛ рдЬреЗрд╡рдгрд╛рдиреЗ рднрд░реВ рди рджреЗрдгрд╛рд░реА lifecycle policy. рдЦрд░реА file:
- ecr/lifecycle-policy.json тАФ "рд╕рд░реНрд╡рд╛рдд рдирд╡реЗ 10 рдареЗрд╡рд╛, рдмрд╛рдХреАрдЪреЗ рдлреЗрдХреВрди рджреНрдпрд╛"
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдмрдБрдХреЗрдд рдбрдмрд╛ рдареЗрд╡рдгреНрдпрд╛рдЪрд╛ рдПрдХ рдирд┐рдпрдо рдЖрд╣реЗ рдЬреНрдпрд╛рд╡рд░ рд▓реЛрдХ рдиреЗрд╣рдореА рдЕрдбрдЦрд│рддрд╛рдд: рд▓реЗрдмрд▓рд╡рд░ рдкреВрд░реНрдг
рдкрддреНрддрд╛ рдЕрд╕рд╛рдпрд▓рд╛рдЪ рд╣рд╡рд╛ ЁЯП╖я╕П. рдлрдХреНрдд hello-school:v1 рд▓реЗрдмрд▓ рдЕрд╕рд▓реЗрд▓рд╛ рдбрдмрд╛ рдмрдБрдХ рд╕реНрд╡реАрдХрд╛рд░рдд рдирд╛рд╣реА
тАФ рдХреЛрдгрддреА рдмрдБрдХ? рдХреЛрдгрддреА рд╢рд╛рдЦрд╛? рдХреЛрдгрддрд╛ locker? рд▓реЗрдмрд▓рд╡рд░ рдЕрд╕реЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рд╣рд╡реЗ:
123456789012.dkr.ecr.ap-south-1.amazonaws.com/hello-school:v1(рдмрдБрдХ ┬╖ рд╢рд╛рдЦрд╛ ┬╖ locker ┬╖ рдбрдмреНрдпрд╛рдЪреЗ рдирд╛рд╡)
docker tag рдиреЗрдордХреЗ рд╣реЗрдЪ рдХрд░рддреЗ тАФ рддреЗ рдХрд╛рд╣реАрд╣реА copy рдХрд░рдд рдирд╛рд╣реА, рдлрдХреНрдд рддреНрдпрд╛рдЪ рдбрдмреНрдпрд╛рд╡рд░
рджреБрд╕рд░реЗ, рдкреВрд░реНрдг рдкрддреНрддрд╛ рдЕрд╕рд▓реЗрд▓реЗ рд▓реЗрдмрд▓ рд▓рд┐рд╣рд┐рддреЗ. рдордЧ docker push рддреЗ рд▓реЗрдмрд▓ рд╡рд╛рдЪрддреЛ рдЖрдгрд┐
рдиреЗрдордХреЗ рдХреБрдареЗ рдкреЛрд╣реЛрдЪрд╡рд╛рдпрдЪреЗ рддреЗ рддреНрдпрд╛рд▓рд╛ рдХрд│рддреЗ.
рдЖрдгрд┐ рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд░реА ЁЯз╣: рдкреНрд░рддреНрдпреЗрдХ push рдПрдХ рдбрдмрд╛ рдЬреЛрдбрддреЛ, рдХрд╛рдпрдордЪрд╛. рд╡рд░реНрд╖рднрд░ рд░реЛрдЬ deploys = рдмрд╣реБрддреЗрдХ рдордореА рдЭрд╛рд▓реЗрд▓реНрдпрд╛ рдЬреЗрд╡рдгрд╛рдЪреЗ 365 рдбрдмреЗ, рдЖрдгрд┐ рдмрдБрдХ рдХрдкреНрдкреНрдпрд╛рдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрдВрдЯреАрдореАрдЯрд░рдЪреЗ рдкреИрд╕реЗ рдШреЗрддреЗ. lifecycle policy рдореНрд╣рдгрдЬреЗ рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд▒реНрдпрд╛рд▓рд╛ рджрд┐рд▓реЗрд▓реНрдпрд╛ рдХрд╛рдпрдордЪреНрдпрд╛ рд╕реВрдЪрдирд╛: "рд╕рд░реНрд╡рд╛рдд рдирд╡реЗ 10 рдбрдмреЗ рдареЗрд╡рд╛; рдмрд╛рдХреАрдЪреЗ рд╢рд╛рдВрддрдкрдгреЗ expire рдХрд░рд╛." рдПрдХрджрд╛ рд╕реЗрдЯ рдХрд░рд╛, рдХрд╛рдпрдо рдиреАрдЯрдиреЗрдЯрдХреЗ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
tag["ЁЯП╖я╕П full-address label<br/>docker tag hello-school:v1<br/>ACCOUNT.dkr.ecr.REGIONтАж/hello-school:v1"]
subgraph ecr["ЁЯПж ECR locker"]
v3["ЁЯУж v3 - newest"]
v2["ЁЯУж v2"]
old["ЁЯУж v-oldтАж expired ЁЯз╣"]
end
eks["тШ╕я╕П EKS deployment<br/>image: ACCOUNT.dkrтАж/hello-school:v3"]
jan["ЁЯз╣ lifecycle policy<br/>keep newest 10"]
tag -->|"1 docker push"| ecr
ecr -->|"2 pulled at deploy"| eks
jan -.->|"3 tidies automatically"| old
тЭУ рдХрд╛рдп
docker tag SOURCE FULL_ADDRESS:TAGтАФ рддреЛрдЪ image ID, рдирд╡реЗ рдкреВрд░реНрдг рдирд╛рд╡. Push рдХреБрдареЗ рдХрд░рд╛рдпрдЪрд╛ рддреЗ рдирд╛рд╡рд╛рддрдЪ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдЕрд╕рддреЗ тАФ рд╣реАрдЪ рд╕рдЧрд│реА рдпреБрдХреНрддреА.- Pushes рдерд░рд╛рдВрдмрд╛рдмрдд рд╣реБрд╢рд╛рд░ рдЕрд╕рддрд╛рдд: ECR рдХрдбреЗ рдирд╕рд▓реЗрд▓реЗ рдерд░рдЪ рдЬрд╛рддрд╛рдд (рдзрдбрд╛ 02 рдЖрдгрд┐ рдзрдбрд╛ 07 рдЪреЗ рдлрд│ рдорд┐рд│рддреЗ: рд▓рд╣рд╛рди рдерд░ = 2 рд╕реЗрдХрдВрджрд╛рдВрдЪреЗ pushes).
- EKS рдордзреВрди pull рдХрд░рдгреЗ: k8s рдХреЛрд░реНрд╕рдЪреНрдпрд╛
deployment.yamlрдордзрд▓рд╛IMAGE_PLACEHOLDERрдиреЗрдордХреНрдпрд╛ рдпрд╛рдЪ рдкрддреНрддреНрдпрд╛рдиреЗ рдмрджрд▓рд▓рд╛ рдЬрд╛рддреЛ тАФ nodes рдЖрдкрд▓реНрдпрд╛ IAM role рдиреЗ pull рдХрд░рддрд╛рдд, cluster рд╡рд░ docker login рдЪреА рдЧрд░рдЬ рдирд╛рд╣реА. - Lifecycle rules рд╕рдВрдЦреНрдпреЗрдиреБрд╕рд╛рд░ рдХрд┐рдВрд╡рд╛ рд╡рдпрд╛рдиреБрд╕рд╛рд░ рдЬреБрд│рддрд╛рдд, рдЖрдгрд┐ tag prefixes рд╕реБрд░рдХреНрд╖рд┐рдд рдареЗрд╡реВ рд╢рдХрддрд╛рдд
(рдЙрджрд╛.
release-*рдиреЗрд╣рдореА рдареЗрд╡рд╛). Git рдордзрд▓реЗ JSON тЖТ ecr/ecr.tf рдиреЗ рд▓рд╛рдЧреВ тАФ рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд▒реНрдпрд╛рдЪреНрдпрд╛ рдХрд░рд╛рд░рд╛рдЪрд╛ code-review рд╣реЛрддреЛ.
ЁЯза Tag рд╡рд┐рд░реБрджреНрдз digest тАФ рдЖрдгрд┐ lifecycle policy рдЪреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг
tag = human-friendly name my-app:v42 (mutable тАФ can be re-pointed)
digest = content identity sha256:abc123тАж (immutable тАФ the exact bytes)
my-app:v42 тФАтФАresolves today toтФАтФАтЦ╢ sha256:abc123тАж
Production deployments рдЕрдиреЗрдХрджрд╛ digest pin рдХрд░рддрд╛рдд (рдХрд┐рдВрд╡рд╛ immutable tags рд╡рд╛рдкрд░рддрд╛рдд)
рдХрд╛рд░рдг рддреБрдореНрд╣реА test рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ tag рд╡реЗрдЧрд│реНрдпрд╛ content рдХрдбреЗ рд╣рд▓рд╡рд▓рд╛ рдЬрд╛рдК рд╢рдХрддреЛ; digest
рдирд╛рд╣реА. рдореНрд╣рдгреВрдирдЪ Kubernetes image: repo@sha256:тАж рд╕реНрд╡реАрдХрд╛рд░рддреЗ.
ECR рдордзреНрдпреЗ default рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд░реА рдирд╛рд╣реА. Lifecycle policy рддреБрдореНрд╣реА рд▓рд┐рд╣рд╛рдпрдЪреА рдЕрд╕рддреЗ тАФ рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде: "рд╕рд░реНрд╡рд╛рдд рдирд╡реНрдпрд╛ 10 tagged images рдареЗрд╡рд╛; untagged images 7 рджрд┐рд╡рд╕рд╛рдВрдирдВрддрд░ expire рдХрд░рд╛." рддреБрдордЪреНрдпрд╛ rollback рдЪреНрдпрд╛ рдЧрд░рдЬрд╛рдВрдирд╛ рдЬреБрд│рдгрд╛рд░реЗ рдЖрдХрдбреЗ рдирд┐рд╡рдбрд╛.
ЁЯдФ рдХрд╛
рд╣рд╛ рдзрдбрд╛ рдореНрд╣рдгрдЬреЗрдЪ deploy рдЪрд╛ рдорд╛рд░реНрдЧ: рднрд╛рдЧ 1 рдиреЗ рдмрд╛рдВрдзрд▓реЗрд▓реЗ рд╕рдЧрд│реЗ рдЗрдереЗ cluster рд▓рд╛ рдЙрдкрд▓рдмреНрдз рд╣реЛрддреЗ. рдЖрдгрд┐ рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд░реА рджрд┐рд╕рддреЛ рддреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдорд╣рддреНрддреНрд╡рд╛рдЪрд╛ рдЖрд╣реЗ: рдорд░реНрдпрд╛рджрд╛ рдирд╕рд▓реЗрд▓реНрдпрд╛ registries рд▓рд╛ рдЦрд░реЗ рдкреИрд╕реЗ рд▓рд╛рдЧрддрд╛рдд, scans рд╣рд│реВ рд╣реЛрддрд╛рдд, рдЖрдгрд┐ рдХреЛрдгрддреНрдпрд╛ images рдЦрд░реЛрдЦрд░ рдорд╣рддреНрддреНрд╡рд╛рдЪреНрдпрд╛ рдЖрд╣реЗрдд рддреЗ рд▓рдкрддреЗ. "рд╕рд░реНрд╡рд╛рдд рдирд╡реЗ 10 + рд╕реБрд░рдХреНрд╖рд┐рдд releases" рд╣рд╛ рдХрдВрдЯрд╛рд│рд╡рд╛рдгрд╛, рдкрдг рдпреЛрдЧреНрдп default рдЖрд╣реЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
REPO=$(aws ecr describe-repositories --repository-names hello-school \
--query 'repositories[0].repositoryUri' --output text) # your locker address
# 1) file a box: full-address label тЖТ push
docker tag hello-school:v1 "$REPO:v1"
docker push "$REPO:v1" # watch layers upload (then re-push: instant)
# 2) prove it's really there тАФ pull it back as a stranger would:
docker rmi "$REPO:v1"
docker pull "$REPO:v1" && echo "round trip complete ЁЯОЙ"
# 3) test IMMUTABLE tags (lesson 10's promise):
docker push "$REPO:v1" 2>&1 | tail -1 # rejected? no тАФ identical bytes are fine.
# now change the app, rebuild, and try to REUSE v1:
echo "// changed" >> app/server.js && docker build -t "$REPO:v1" app/ && git checkout app/server.js
docker push "$REPO:v1" 2>&1 | tail -1 # тЭМ "tag invalid: The image tag 'v1' already exists"
# 4) read the janitor's contract:
aws ecr get-lifecycle-policy --repository-name hello-school --query lifecyclePolicyText --output text
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- tag рд▓рд╛ рд╣рдореА рд╕рдордЬрдгреЗ тАФ рдлрдХреНрдд digest рдиреЗрдордХрд╛ content рдУрд│рдЦрддреЛ
- ECR рдЖрдкреЛрдЖрдк рд╕рд╛рдлрд╕рдлрд╛рдИ рдХрд░рддреЗ рдЕрд╕реЗ рдЧреГрд╣реАрдд рдзрд░рдгреЗ тАФ lifecycle policy рд▓рд┐рд╣рд╛ (рдЖрдгрд┐ рдмрд┐рд▓ рд╡рд╛рдЪрд╛)
- production рд╕рдзреНрдпрд╛ рдЬреНрдпрд╛рд╡рд░ рдЪрд╛рд▓реВ рдЖрд╣реЗ рддреА image expire рдХрд░рдгрд╛рд░реА рдЖрдХреНрд░рдордХ policy
тПня╕П рдкреБрдвреЗ
рддреБрдореНрд╣реА рдЖрддреНрддрд╛ tag тЖТ login тЖТ push рд╣рд╛рддрд╛рдиреЗ рдХреЗрд▓реЗ. рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛ рд╣реЗ рд╕рдВрдкреВрд░реНрдг рдХрд╛рдо рдПрдХрд╛ robot рдХрдбреЗ рд╕реЛрдкрд╡рддреЛ тАФ рдЖрдгрд┐ рдкреБрдврдЪреНрдпрд╛ рджреЛрди рдХреЛрд░реНрд╕рдХрдбреЗ baton рджреЗрддреЛ.
git checkout lesson-12-ci-to-cloud