ბიბლიოთეკა
00/08 · ~40 წთ
GUIDEDECK · პროგრამისთვის, რომელიც ყველგან მუშაობს

Docker & კონტეინერები
შეფუთეთ გარემო,
და არა მხოლოდ კოდი.

40-წუთიანი სამუშაო სესია კონტეინერებზე — პრობლემიდან "ჩემს მანქანაზე მუშაობს", იმიჯებზე, Dockerfile-ებსა და შრეებზე, ვოლუმებზე, ქსელსა და Compose-ზე გავლით, შემდეგ ინსტრუმენტებზე, რომელთა შორისაც აირჩევთ, და ბოლოს რეალურ ცუდი → კარგი აწყობამდე, რომელიც შეგიძლიათ დააკოპიროთ.

~40 წთინჟინრებიინსტრუმენტ-ნეიტრალური
გადაახვიეთ
01 · პრობლემა, რომელსაც ხსნიან 4 წთ

"ჩემს მანქანაზე მუშაობს"
ეს გარემოს ბაგია.

კოდი იშვიათად ტყდება მარტო — ის იმიტომ ტყდება, რომ გარშემო მანქანა სხვაა: Node-ის სხვა ვერსია, აკლია სისტემური ბიბლიოთეკა, კონფიგი, რომელიც მხოლოდ ვიღაცის ლეპტოპზე არსებობს. კონტეინერები ამას ასწორებენ იმით, რომ გარემოს კოდთან ერთად აგზავნიან.

კონტეინერი — იზოლირებული, შეფუთული პროცესი — თქვენს აპლიკაციას აერთიანებს ყველაფერთან, რაც გასაშვებად სჭირდება (runtime, ბიბლიოთეკები, ფაილები, env) ერთ ერთეულში, რომელიც ერთნაირად იქცევა ლეპტოპზე, CI-ში და პროდაქშენში. ერთი და იგივე იმიჯი შედის — ერთი და იგივე ქცევა გამოდის.
3

გარემო, სადაც ერთნაირად უნდა იქცეოდეს: dev, CI, prod.

1

არტეფაქტი ყველასთვის — იმიჯი, რომელსაც ერთხელ აგებთ.

ms

გაშვება, არა წუთები — კონტეინერები ჰოსტის ბირთვს იზიარებენ.

MB

და არა GB — სრული სტუმარი OS არ იგზავნება.

ხელით აწყობა — დროთან ერთად ცდება
# Getting started (good luck) # 1. install Node 18 (NOT 20, it breaks) # 2. brew install postgres@15, then createdb app # 3. set 7 env vars (ask Sam which ones) # 4. nvm use; npm i; ./scripts/seed.sh # …works for Sam. Not for you. Not in CI.
კონტეინერში — რეპროდუცირებადი
# Getting started (actually) docker compose up # the image pins the runtime, libs, and config. # identical on every laptop, in CI, in prod. # onboarding goes from a day to a minute.

VM vs. კონტეინერი

  • ვირტუალური მანქანა ავირტუალებს აპარატურას — თითოეულ VM-ს სრული სტუმარი OS მიაქვს. მძიმეა: GB-ები, იტვირთება წამებში-წუთებში.
  • კონტეინერი ავირტუალებს ოპერაციულ სისტემას — ყველა კონტეინერი იზიარებს ჰოსტის ბირთვს (OS-ის გული, რომელიც აპარატურას ესაუბრება) და მხოლოდ პროცესს იზოლირებს.
  • შედეგი: კონტეინერები პატარაა და მყისიერად ეშვება, ამიტომ ერთ ჰოსტზე ბევრის გაშვება და მუდმივად ხელახლა აგება შეგიძლიათ.
აპი
სტუმარი OS
აპი
სტუმარი OS
აპი
სტუმარი OS
აპი
+ ბიბლ.
აპი
+ ბიბლ.
აპი
+ ბიბლ.
ჰიპერვიზორი
Docker Engine
ჰოსტის OS
ჰოსტი OS · საერთო ბირთვი
აპარატურა
აპარატურა
ვირტუალური მანქანები
კონტეინერები
სრული OS თითო აპზე → GB
ერთი ბირთვი ყველას → MB

VM-ები ავირტუალებენ აპარატურას (თითოეულს სრული OS აქვს); კონტეინერები ავირტუალებენ OS-ს (ერთი საერთო ბირთვი) — ამიტომ MB-ებში იგზავნება და მილიწამებში ეშვება.

02 · სააზროვნო მოდელი 6 წთ

იმიჯი არის ნახაზი;
კონტეინერი კი მისი ერთი გაშვებული ასლი.

ეს ერთი განსხვავება რომ გაიგოთ, დანარჩენი Docker თავისით ჯდება ადგილზე. კავშირი ზუსტად ისეთია, როგორიც კლასი → ობიექტი: შაბლონს ერთხელ აგებთ, შემდეგ კი იმდენ ცოცხალ ასლს უშვებთ, რამდენიც გინდათ.

იმიჯი არის მხოლოდ-კითხვადი, შრეებიანი შაბლონი — ფაილური სისტემის სნეპშოტი პლუს მეტამონაცემები (გასაშვები ბრძანება, პორტები, env-ი). კონტეინერი არის უკვე გაშვებული იმიჯი: მომუშავე პროცესი, რომელსაც ზემოდან საკუთარი თხელი ჩაწერადი შრე აქვს. ერთი იმიჯი → ბევრი კონტეინერი.

სასიცოცხლო ციკლი ბრძანებებში

  • docker build Dockerfile-ს იმიჯად აქცევს.
  • docker pull უკვე აგებულ იმიჯს რეგისტრიდან ჩამოტვირთავს (მაგ. Docker Hub).
  • docker run იმიჯიდან კონტეინერს უშვებს.
  • docker ps ჩამოთვლის მომუშავე კონტეინერებს; stop / rm აჩერებს და შლის მათ.
  • docker build
  • docker pull
  • docker run
  • docker ps
  • docker stop
  • docker rm

კონტეინერები იზიარებენ იმიჯის შრეებს, რომლებიც read-only-ა; თითოეული ზემოდან საკუთარ თხელ ჩაწერად შრეს ამატებს.

შინაური — მომუშავე კონტეინერს ვცვლით
docker exec -it web bash apt-get install imagemagick # fix it live… vim /app/config.json # tweak by hand # changes live only in this container. # rebuild or restart → all of it vanishes.
პირუტყვი — ვცვლით იმიჯს, ხელახლა დეპლოი
# put the change in the Dockerfile / config docker build -t myapp:1.1 . docker run myapp:1.1 # the fix is versioned, reviewable, repeatable. # any container from this image is identical.

კონტეინერები ერთჯერად და უცვლელ ერთეულებად მიიჩნიეთ: მომუშავეს არასოდეს დაუწყოთ ჩასწორება. თუ ცვლილება გჭირდებათ, შეცვალეთ იმიჯი და გაუშვით ახალი კონტეინერი. პირუტყვი და არა pet-ები — ავადმყოფ კონტეინერს ხელით არ მკურნალობთ; მას განახლებული იმიჯიდან აგებული ახლით ცვლით.

03 · იმიჯების აგება 7 წთ

Dockerfile არის რეცეპტი.
ყოველი ხაზი — ქეშირებული შრე.

Docker იმიჯს ისე აგებს, რომ თქვენს Dockerfile-ს ზემოდან ქვემოთ ასრულებს და ყოველ ინსტრუქციას შრედ ქეშირებს. ამ ქეშის გაგება არის განსხვავება 2-წამიან და 5-წუთიან ხელახალ აგებას შორის — და 1.2GB-იან და 90MB-იან იმიჯს შორის.

Dockerfile-ი არის აგების ნაბიჯების უბრალო ტექსტური სია. ყოველი ინსტრუქცია (FROM, COPY, RUN…) ერთ უცვლელ შრეს ქმნის. Docker-ი შრის ქეშს მანამ იყენებს ხელახლა, სანამ ეს ნაბიჯი და ყველაფერი მის ზემოთ უცვლელია — ამიტომ თანმიმდევრობას უზარმაზარი მნიშვნელობა აქვს.

Dockerfile-ის ინსტრუქციები, რომლებსაც ყოველდღე იყენებთ

  • FROM — საბაზო იმიჯი, საიდანაც იწყებთ.
  • WORKDIR — სამუშაო დირექტორიის დაყენება.
  • COPY — ფაილების კოპირება თქვენი კონტექსტიდან იმიჯში.
  • RUN — ბრძანების შესრულება აგების დროს (დამოკიდებულებების დაყენება, კომპილაცია).
  • EXPOSE — დოკუმენტირება, რომელ პორტს უსმენს აპლიკაცია.
  • CMD — ნაგულისხმევი ბრძანება, რომელიც გაშვების დროს სრულდება. დაწერეთ სიად — ["node","server.js"], ეს არის exec ფორმა — რომ როცა Docker კონტეინერს აჩერებს, სიგნალი "გთხოვ, გაითიშე" პირდაპირ თქვენს აპლიკაციას მიუვიდეს და მან სუფთად დაასრულოს. უბრალო სტრიქონის shell ფორმა (node server.js) თქვენს აპლიკაციას shell-ის უკან მალავს, ამიტომ ის უხეშად კვდება.
FROM node:20-slim # პატარა ბაზა WORKDIR /app COPY package*.json ./ # ჯერ deps… RUN npm ci # …ქეშირდება, სანამ არ შეიცვლება COPY . . # შემდეგ წყარო EXPOSE 3000 CMD ["node", "server.js"] # exec ფორმა

deps წყაროზე ადრე კოპირდება: შეცვლით როუტს და მხოლოდ ბოლო ორი შრე აიგება ხელახლა.

FROM node:20-slim WORKDIR /app COPY package*.json RUN npm ci COPY . . ← edited CMD ["node"…] cached ✓ rebuilt ✕ (this layer + everything below)

ქეშის მოხვედრა პირველ შეცვლილ შრეზე ჩერდება; მის ქვემოთ ყველაფერი ხელახლა იგება. ზემოთ ის დადეთ, რაც ყველაზე იშვიათად იცვლება.

Dockerfile-ის #1 შეცდომა

კოდი დამოკიდებულებებამდე
FROM node:20 # ~1GB base COPY . . # any edit busts cache RUN npm install # reruns EVERY build CMD npm start # shell form, no signals
deps ქეშში, მსუბუქი ბაზა
FROM node:20-slim COPY package*.json ./ RUN npm ci # cached on code edits COPY . . CMD ["node","server.js"]

ორი ხერხი, რომელიც თავს იმართლებს

მრავალეტაპიანი აგება

აგე მძიმედ, გააგზავნე მსუბუქად

ერთ ეტაპზე სრული ინსტრუმენტებით დააკომპილირეთ, შემდეგ კი მხოლოდ შედეგი გადაიტანეთ პაწაწინა runtime იმიჯში. თქვენი კომპილატორი, dev დამოკიდებულებები და წყარო პროდაქშენამდე არასოდეს აღწევს.

FROM node:20 AS build WORKDIR /app COPY . . RUN npm ci && npm run build # runtime ეტაპი — მხოლოდ აგებული ფაილები FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html

თითქოს  სრულ სამზარეულოში ამზადებთ, შემდეგ კი მხოლოდ გაწყობილ კერძს გადასცემთ — და არა ქვაბებსა და ტაფებს.

.dockerignore

ნაგავი აგებაში არ შეუშვათ

აგების კონტექსტი არის ყველაფერი, რასაც Docker აგებამდე ატვირთავს. .dockerignore გამორიცხავს იმას, რაც იმიჯს ასუქებს და ქეშს აფუჭებს — და საიდუმლოებებს შემოპარვის საშუალებას არ აძლევს.

node_modules .git .env # საიდუმლოებები იმიჯში არასოდეს ჩააცხოთ *.log dist Dockerfile

თითქოს  .gitignore თქვენი იმიჯისთვის — პატარა, სწრაფი და უსაფრთხო აგება.

04 · მონაცემები რჩება 5 წთ

კონტეინერის ფაილური სისტემა ერთჯერადია.
მონაცემები Docker-ის ვოლუმებში ცხოვრობს.

იმიჯის თავზე მდებარე თხელი ჩაწერადი შრე კონტეინერთან ერთად კვდება. წაშალეთ კონტეინერი — ან ხელახლა დაადეპლოეთ ახალი იმიჯი — და შიგნით ჩაწერილი ყველაფერი ქრება. მონაცემთა ბაზებისთვის, ატვირთვებისა და მდგომარეობისთვის გჭირდებათ საცავი, რომელიც პროცესს გადაურჩება.

ვოლუმი არის Docker-ის მიერ მართული საცავი, რომელიც კონტეინერის ჩაწერადი შრის გარეთ ცხოვრობს. კონტეინერები მოდიან და მიდიან; ვოლუმი — და თქვენი მონაცემები — რჩება. დაამაუნთეთ ის კონტეინერის შიგნით არსებულ გზაზე და იქ ჩაწერილი გადარჩება გადატვირთვას, ხელახლა აგებას და წაშლას.

ჩანაწერები დამაუნთებულ გზაზე ვოლუმში ხვდება და არა ერთჯერად ჩაწერად შრეში — ამიტომ ისინი კონტეინერს გადაურჩება.

ვოლუმის გარეშე — ქრება
docker run --name db postgres:16 # write 10,000 rows… docker rm -f db # every row is gone. forever.
სახელიანი ვოლუმი — რჩება
docker volume create pgdata docker run --name db \ -v pgdata:/var/lib/postgresql/data \ postgres:16 # rm + recreate → rows are still there.

საცავის დამაუნთების სამი გზა

სახელიანი ვოლუმი

Docker მართავს

საცავის ადგილს Docker ფლობს. ნაგულისხმევი არჩევანი პროდაქშენის მონაცემებისთვის — ბაზები, ატვირთვები. პორტატულია, სარეზერვო ასლს იღებს და ჰოსტის გზაზე მიბმული არაა.

-v pgdata:/var/lib/postgresql/data
ბაინდ-მაუნთი

ჰოსტის დირექტორია ცოცხლად

თქვენს მანქანაზე არსებულ ნამდვილ დირექტორიას კონტეინერში ასახავს. იდეალურია ლოკალური დეველოპმენტისთვის — წყაროს ჰოსტზე ცვლით, კონტეინერი მას მაშინვე ხედავს (hot reload).

-v $(pwd)/src:/app/src
tmpfs

მხოლოდ მეხსიერებაში

ინახება RAM-ში, არასოდეს დისკზე, და ქრება კონტეინერის გაჩერებისას. საიდუმლოებისთვის ან დროებითი მონაცემებისთვის, რომელთა შენახვაც შეგნებულად არ გინდათ.

--tmpfs /tmp/cache

თითქოს  საერთო მაგიდების ოფისი: მაგიდა (კონტეინერი) ყოველ ღამე იწმინდება, მაგრამ თქვენი კარადა (ვოლუმი) ნივთებს დღეებს შორის ინახავს.

05 · საუბარი გარესამყაროსთან 5 წთ

კონტეინერები ნაგულისხმევად იზოლირებულია.
მათ დასაკავშირებლად პორტებს აქვეყნებთ და ქსელებს უერთდებით.

თავიდან ორი კითხვა აბნევს ყველას: როგორ აღწევს გარე სამყარო კონტეინერამდე? (გამოაქვეყნეთ პორტი) და როგორ აღწევენ კონტეინერები ერთმანეთამდე? (დააყენეთ ისინი ერთსა და იმავე ქსელში და სერვისების სახელები გამოიყენეთ). ეს რომ გაიგოთ, Compose თავისთავად ცხადი ხდება.

პორტის გამოქვეყნება -p HOST:CONTAINER-ით თქვენს მანქანაზე არსებულ პორტს კონტეინერის შიგნით არსებულზე გადამისამართებს. მომხმარებლის შექმნილი ქსელი არის პრივატული ხიდი, რომელიც მასზე მყოფ კონტეინერებს ერთმანეთის სახელით პოვნის საშუალებას აძლევს, Docker-ის ჩაშენებული DNS-ით — IP-ების გარეშე, --link-ის გარეშე.

გარედან → შიგნით გამოქვეყნებული პორტით; შიგნიდან → შიგნით სერვისის სახელით db საერთო ქსელში.

როგორ წავიკითხოთ -p 8080:3000

  • მარცხნივ არის ჰოსტის პორტი (რასაც ბრაუზერში კრეფთ), მარჯვნივ — კონტეინერის პორტი (რომელსაც აპლიკაცია უსმენს).
  • localhost:8080 თქვენს მანქანაზე ახლა აღწევს აპლიკაციამდე, რომელიც შიგნით :3000-ზეა მიბმული.
  • -p-ის გარეშე პორტი ხელმისაწვდომია ქსელში სხვა კონტეინერებისთვის, მაგრამ არა ჰოსტისთვის.
  • ქსელის შიგნით კონტეინერები პირდაპირ კონტეინერის პორტზე საუბრობენ — publish-ი საჭირო არაა.
ჩაშენებული IP და ძველი --link
# container IPs change on every restart DB_HOST="172.17.0.3" # --link is deprecated and brittle docker run --link db:db web
საერთო ქსელი + DNS სახელით
docker network create app-net docker run --network app-net --name db postgres:16 docker run --network app-net web # web connects to "db:5432" — stable forever
06 · მრავალსერვისიანი აწყობა 6 წთ

ერთი ფაილი. ერთი ბრძანება.
მთელი სტეკი ფეხზეა.

რეალური აპლიკაციები ერთი კონტეინერი არაა — ეს არის ვებსერვისი, მონაცემთა ბაზა, შესაძლოა ქეშიც და რიგიც, ერთმანეთთან შეერთებული. ყოველ ჯერზე გრძელი docker run-ების სწორი თანმიმდევრობით აკრეფა შეცდომების რეცეპტია. Compose-ი სტეკს დეკლარაციულს ხდის.

Docker Compose ერთ YAML ფაილში აღწერს მრავალკონტეინერიან აპლიკაციას. თქვენ აცხადებთ სერვისებს, მათ იმიჯებს, პორტებს, ვოლუმებს, env-ს და დამოკიდებულებებს; docker compose up ქმნის ქსელს და ყველაფერს უშვებს. ეს ფაილი თავად არის დოკუმენტაცია.
services: web: build: . ports: ["8080:3000"] environment: DATABASE_URL: postgres://db:5432/app depends_on: db: { condition: service_healthy } db: image: postgres:16 volumes: ["pgdata:/var/lib/postgresql/data"] healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] volumes: pgdata:

ყველაფერი 2–5 სექციიდან ერთ ადგილას: იმიჯი, პორტი, env, ვოლუმი, დამოკიდებულებების თანმიმდევრობა.

რას გაძლევთ ეს ერთი ფაილი

  • ავტომატურად იქმნება პრივატული ქსელი — web სახელით აღწევს db-მდე, კონფიგის გარეშე.
  • depends_on + healthcheck უშვებს ბაზას და ელოდება, სანამ ის ნამდვილად მზად იქნება web-ის გაშვებამდე.
  • სახელიანი volume Postgres-ის მონაცემებს down/up ციკლებს შორის ინახავს.
  • build: . web-ს თქვენი Dockerfile-იდან აგებს; image: ბაზას მზა სახით ჩამოიტანს.
  • compose up -d
  • compose down
  • compose logs -f
  • compose ps
  • compose build
იმპერატიული — რიგი და ფლაგები ხელით
docker network create app-net docker volume create pgdata docker run -d --name db --network app-net \ -v pgdata:/var/lib/postgresql/data postgres:16 # now sleep and hope the db is ready… docker run -d --name web --network app-net \ -p 8080:3000 -e DATABASE_URL=... myapp
დეკლარაციული — ფაილი არის ჭეშმარიტება
docker compose up -d # network, volume, build, healthcheck-gated # startup order — all from compose.yaml. # tear it all down with one command: docker compose down
  • Compose არის ერთი ჰოსტისთვის — ლოკალური დეველოპმენტი, CI, მარტივი ერთმანქანიანი დეპლოი. სწორედ ამაში ფანტასტიკურია.
  • როცა ბევრ მანქანაზე გაშვება გჭირდებათ, თანდათანობითი დეპლოით, თვითაღდგენითა და ავტომასშტაბირებით, ორკესტრატორზე გადადიხართ — Kubernetes (ან Nomad / ECS).
  • სააზროვნო მოდელი გადმოჰყვება: სერვისები, იმიჯები, ქსელები და ვოლუმები იგივე ცნებებია, უბრალოდ კლასტერზე განაწილებული.
07 · აირჩიეთ ინსტრუმენტი 4 წთ

კონტეინერების სამყარო
Docker-ზე დიდია.

Docker-მა კონტეინერები გაავრცელა, მაგრამ ყოველ ნაბიჯზე — სად ინახავთ იმიჯებს, რითი აგებთ მათ, რომელი ბაზიდან იწყებთ და როგორ უშვებთ მათ მასშტაბურად — რეალური ალტერნატივებია. აი, წამყვანები: თითოეულს ერთი გულწრფელი დადებითი და უარყოფითი მხარით, და არჩევის მოკლე წესით.

ოთხი გადაწყვეტილება, ინსტრუმენტების ოთხი ნაკრები. რეგისტრი არის ღრუბლოვანი ბიბლიოთეკა, სადაც იმიჯებს ტვირთავთ და საიდანაც მათ იღებთ (როგორც npm ან GitHub, ოღონდ იმიჯებისთვის). ბილდის ძრავა არის პროგრამა, რომელიც თქვენს Dockerfile-ს იმიჯად აქცევს. საბაზო იმიჯი არის საწყისი FROM შრე, რომელზეც ყველაფერი დანარჩენი ეწყობა. ორკესტრატორი თქვენს კონტეინერებს ერთ ან ბევრ მანქანაზე უშვებს.

პაიპლაინი, რომელიც ქვემოთ ყველა ინსტრუმენტს აქვს საერთო: ააგე იმიჯი, ატვირთე რეგისტრში, ჩამოიტანე და გაუშვი სხვაგან. ვენდორები უბრალოდ ყოველ ისარზე იცვლება.

როგორ წავიკითხოთ ეს ტაბები

  • თითოეული ბარათი ასახელებს რეალურ, ფართოდ გავრცელებულ ვარიანტს ერთი ნამდვილი ძლიერი მხარითა და ერთი ნამდვილი კომპრომისით.
  • დადებითი / უარყოფითი წყვილი შეგნებულად პირდაპირია — აქ ყოველი ინსტრუმენტი რომელიღაც გუნდისთვის გონივრული ნაგულისხმევი არჩევანია.
  • თითოეული ტაბის ბოლოს წაიკითხეთ ხაზი საუკეთესოა, რომ პირდაპირ თქვენზე მორგებულ არჩევანზე გადახვიდეთ.

სად ცხოვრობს თქვენი იმიჯები

Docker Hub

ნაგულისხმევი ბიბლიოთეკა

  • დადებითი — ყველაზე დიდი საჯარო კატალოგი და ადგილი, სადაც docker pull პირველად იყურება, ამიტომ თითქმის ყოველი საბაზო იმიჯი ერთი ბრძანების დაშორებითაა.
  • უარყოფითი — უფასო ანგარიშებს pull-ის მკაცრი სიხშირის ლიმიტები ხვდება, ამიტომ დატვირთული CI პაიპლაინები შეიძლება ჩავარდეს შეცდომით "too many requests."
GitHub · GHCR

თქვენს კოდთან ახლოს

  • დადებითი — უფასოა საჯარო იმიჯებისთვის და ზის თქვენი რეპოზიტორიისა და GitHub Actions-ის გვერდით, ამიტომ აგებასა და გამოქვეყნებას უფლებების ერთი ნაკრები აქვს.
  • უარყოფითი — წვდომა GitHub-ის ანგარიშებსა და გუნდებზეა მიბმული, და საჯარო აღმოჩენის ჰაბად Hub-ზე ნაკლებად გამოდგება.
AWS · ECR

პრივატული, თქვენს ღრუბელში

  • დადებითი — სწრაფი და პრივატულია, მჭიდროდ არის შეკერილი AWS-ის უფლებებსა და გამშვებებში (ECS / EKS), ამიტომ დეპლოი ერთი ანგარიშის შიგნით რჩება.
  • უარყოფითი — მხოლოდ AWS-ია, ანგარიშსწორება შენახულ GB-ზეა, და შესვლას მოკლევადიანი ტოკენები და სწორად დაყენებული რეგიონი სჭირდება.

საუკეთესოა  საჯარო იმიჯებისა და სწავლისთვის → Hub; უკვე GitHub-ზე ცხოვრობთ → GHCR; AWS-ზე მუშაობთ და ყველაფერი პრივატული გინდათ → ECR.

რა აქცევს Dockerfile-ს იმიჯად

Docker

სტანდარტი

  • დადებითი — ის, რაც ყველამ იცის, ყველაზე დიდი ეკოსისტემით; მისი თანამედროვე ბილდერი (BuildKit) სწრაფ, კარგად ქეშირებულ აგებას თავიდანვე იძლევა.
  • უარყოფითი — ფონურ სერვისს root-ის სახელით უშვებს, და დიდ კომპანიებში Docker Desktop-ს ფასიანი ლიცენზია სჭირდება.
Podman · Buildah

დემონის & root-ის გარეშე

  • დადებითი — ფონური სერვისის გარეშე მუშაობს და ნაგულისხმევად root-ის გარეშე (უფრო უსაფრთხოა), მისი CLI კი docker-ს თითქმის ბრძანება-ბრძანებით იმეორებს.
  • უარყოფითი — უფრო პატარა ეკოსისტემა; Compose-ისა და Desktop-ის ზოგი მოხერხებულობა ჩამორჩება ან ოდნავ სხვაგვარად იქცევა.
Kaniko · Buildpacks

აგება CI-ში, დემონის გარეშე

  • დადებითი — იმიჯებს CI-ში ან Kubernetes კლასტერში აგებთ საერთოდ Docker დემონის გარეშე; Buildpacks-ს Dockerfile-ის სრულად გამოტოვებაც კი შეუძლია.
  • უარყოფითი — ხელით დაწერილ Dockerfile-ზე ნაკლებად მოქნილია, და თითოეული საკუთარ ცნებებს ამატებს შესასწავლად.

საუკეთესოა  უმეტესობისთვის → Docker; უსაფრთხოება ან root-ის გარეშე გარემო → Podman; კლასტერში ან პაიპლაინში აგება → Kaniko / Buildpacks.

FROM, საიდანაც იწყებთ

სრული · node:20

ყველაფერი კომპლექტში

  • დადებითი — ყველა shell და ინსტრუმენტი უკვე იქაა, ამიტომ მასში ჩხრეკა და დებაგი ყველაზე ადვილია.
  • უარყოფითი — ხშირად 1GB+ და უფრო დიდი თავდასხმის ზედაპირი (რაც მეტი პროგრამაა დაყენებული, მით მეტ რამეს შეიძლება ჰქონდეს უსაფრთხოების ხვრელი).
Slim · Alpine

პატარა და სწრაფი

  • დადებითი — ათეულობით MB გიგაბაიტის ნაცვლად, ამიტომ იმიჯები შესამჩნევად სწრაფად ჩამოიტვირთება და ეშვება.
  • უარყოფითი — Alpine სხვა სისტემურ C ბიბლიოთეკას იყენებს (musl, და არა ჩვეულ glibc), რამაც ნატიური დანამატები შეიძლება გატეხოს; ნაკლები ჩაშენებული დებაგ-ინსტრუმენტი.
Distroless

აპლიკაცია და მეტი არაფერი

  • დადებითი — მხოლოდ თქვენს აპლიკაციასა და მის runtime-ს აგზავნის — არც shell, არც პაკეტების მენეჯერი — ამიტომ თავდასხმის ზედაპირი მაქსიმალურად პატარაა.
  • უარყოფითი — shell არ არის, რომ exec-ით შეხვიდეთ, ამიტომ დებაგი რთულდება; აგება სხვაგან უნდა მოახდინოთ და შედეგი შიგნით გადმოაკოპიროთ (მრავალეტაპიანი).

საუკეთესოა  სწრაფი ლოკალური ცდებისთვის → სრული; ყოველდღიური პროდაქშენისთვის → slim; ჩაკეტილი პროდაქშენისთვის → distroless.

კონტეინერების გაშვება მასშტაბურად

Docker Compose

ერთი მანქანა, ერთი ფაილი

  • დადებითი — ძალიან მარტივია: ერთი YAML ფაილი მთელ სტეკს ფეხზე აყენებს. იდეალურია ლოკალური დეველოპმენტის, CI-სა და პატარა ერთსერვერიანი დეპლოისთვის.
  • უარყოფითი — მხოლოდ ერთ მანქანას მართავს: ჩავარდნაზე ავტომატური გადატვირთვის, ავტომასშტაბირებისა და უწყვეტი განახლებების გარეშე.
Kubernetes

კლასტერის სტანდარტი

  • დადებითი — ინდუსტრიის ნაგულისხმევი არჩევანი ბევრი მანქანისთვის: ჩავარდნილ კონტეინერებს გადატვირთავს, მასშტაბს ზრდის და ამცირებს, ახალ ვერსიებს კი შეფერხების გარეშე გამოსცემს.
  • უარყოფითი — ციცაბო სასწავლი მრუდი და რეალური ყოველდღიური საოპერაციო სამუშაო; პატარა აპლიკაციისთვის ნამდვილად ზედმეტია.
ECS · Cloud Run · Nomad

მართული ოქროს შუალედი

  • დადებითი — რთულ საკონტროლო შრეს ღრუბელი თქვენ მაგივრად უძღვება, ამიტომ მასშტაბირებასა და თვითაღდგენას სუფთა Kubernetes-თან შედარებით გაცილებით ნაკლები საოპერაციო ტვირთით იღებთ.
  • უარყოფითი — ერთ ვენდორზეა უფრო მიბმული და ნაკლებად პორტატულია, ნაკლები სახელურით, ვიდრე საკუთარი Kubernetes.

საუკეთესოა  დეველოპმენტი და ერთი სერვერი → Compose; ბევრი სერვერი და პლატფორმის გუნდი → Kubernetes; მასშტაბი საოპერაციო ტვირთის გარეშე → მართული სერვისი.

გულწრფელი ნაგულისხმევი არჩევანი უმეტესი გუნდისთვის: Docker-ი ასაგებად, მსუბუქი ბაზა, თქვენი პლატფორმის რეგისტრი და Compose-ი მანამ, სანამ ერთი მანქანა ნამდვილად აღარ იქნება საკმარისი. მძიმე ვარიანტებს მაშინ მიმართეთ, როცა რეალური საჭიროება გაჩნდება.

08 · რეალური აწყობა, შეჯამება 3 წთ

მყიფე იმიჯიდან
ისეთამდე, რომელსაც prod-ში გაუშვებდით.

ყველაფერი ერთ ადგილას: ერთი და იგივე ვებსერვისი, ჯერ ისე გაკეთებული, რომ მოგკბენთ, შემდეგ კი ისე, რომ გაუძლებს. ბოლოს — ხუთი წესი, რომელსაც თან წაიღებთ.

რა მიდის ცუდად

FROM node:20 # 1GB+ ბაზა COPY . . # node_modules, .git, .env და ყველაფერი RUN npm install # გადაეშვება კოდის ყოველ ცვლილებაზე EXPOSE 3000 CMD npm start # shell ფორმა → სუფთა გამორთვა არაა # ეშვება root-ით · საიდუმლოებები ჩაცხობილია · 1.3GB იმიჯი · ნელი აგება
სიმპტომები
წუთებიანი ხელახალი აგება, უზარმაზარი იმიჯები, გაჟონილი .env და პროცესი, რომელიც დეპლოიზე SIGTERM-ს უგულებელყოფს.
ძირეული მიზეზი
ქეშის მშლელი შრეების თანმიმდევრობა, .dockerignore არ არის, მძიმე ბაზა, shell-ფორმის CMD.

როგორ გამოიყურება კარგი

FROM node:20-slim AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:20-slim # სუფთა runtime ეტაპი WORKDIR /app COPY --from=build /app/dist ./dist COPY --from=build /app/node_modules ./node_modules USER node # ვტოვებთ root-ს EXPOSE 3000 CMD ["node", "dist/server.js"] # exec ფორმა → სუფთა სიგნალები
მოგებული
ქეშირებული deps, მსუბუქი მრავალეტაპიანი იმიჯი, არა-root მომხმარებელი (რომ კომპრომეტირებულმა აპლიკაციამ ყოვლისშემძლე root-ის ანგარიშით ვერ იმოქმედოს), exec-ფორმის CMD, საიდუმლოებები გარეთ დატოვებული .dockerignore-ით.
დააწყვილეთ ამასთან
compose.yaml ბაზისთვის + ვოლუმისთვის + ქსელისთვის, რომ compose up-მა მთელი სტეკი ერთად ააშვას.

ხუთი წესი, რომელსაც თან წაიღებთ

1გააგზავნეთ გარემო და არა ინსტრუქციები. არტეფაქტი იმიჯია — იდენტური dev-ში, CI-სა და prod-ში.
2იმიჯი = ნახაზი, კონტეინერი = ასლი. კონტეინერები ერთჯერადად მიიჩნიეთ; შეცვალეთ იმიჯი და მომუშავე კონტეინერი არასოდეს ჩაასწოროთ.
3შრეები დაალაგეთ იმის მიხედვით, რამდენად ხშირად იცვლება. deps წყაროზე ადრე, მსუბუქი ბაზები, მრავალეტაპიანი აგება, .dockerignore.
4მდგომარეობა ვოლუმებში ცხოვრობს. ჩაწერადი შრე ერთჯერადია — ყველაფერს, რისი დაკარგვაც არ შეგიძლიათ, Docker-ის ვოლუმი სჭირდება.
5ერთი ქსელი, სახელები და არა IP-ები; ერთი Compose ფაილი. გამოაცხადეთ სტეკი და ერთი ბრძანებით ააშვით.

გააგრძელეთ

  • docs.docker.com — ოფიციალური გზამკვლევები & Dockerfile-ის ცნობარი
  • Dockerfile best practices — აგების ქეშისა & იმიჯის ზომის ჩეკლისტი
  • Play with Docker — უფასო სავარჯიშო გარემო ბრაუზერში, ცოცხლად საცდელად
  • Kubernetes — შემდეგი ნაბიჯი, როცა ერთი host-ი აღარ ყოფნის

ერთი წინადადება დასამახსოვრებლად

"ააგე ერთხელ, გაუშვი ყველგან — რადგან გარემო კოდთან ერთად იგზავნება."

— კონტეინერების მთელი აზრი

ცოდნის შემოწმება

დაგამახსოვრდათ?

ხუთი სწრაფი კითხვა იმიჯებზე, შრეებზე, ვოლუმებზე, ქსელსა და Compose-ზე — მყისიერი პასუხი, ავტორიზაციის გარეშე.

შეაფასეთ ეს დასტა
იყავით პირველი

ნავიგაცია ← → ან სქროლით · უკან ბიბლიოთეკაში