“İmaj” ve “container” kelimeleri günlük konuşmada sık sık birbirinin yerine kullanılır, ama aslında farklı şeylerdir. Bu farkı baştan doğru kavramak; docker rm ile docker rmi arasındaki farktan, “neden imajı sildim de yer açılmadı?” sorusuna kadar bir sürü kafa karışıklığını önler.

Kısa cevap: tarif ve yemek

Programlamadan bir benzetme: imaj bir sınıf (class) gibidir, container onun çalışan bir örneği (instance). İmaj salt okunur bir şablondur; container ise o şablondan başlatılmış, üzerine kendi yazılabilir katmanını eklemiş canlı bir süreçtir.

İmaj (image) Container
Ne? Uygulama + bağımlılıkları + dosya sistemi şablonu İmajdan başlatılmış çalışan (veya durmuş) örnek
Değişir mi? Hayır — salt okunur, değişmez (immutable) Evet — üstüne yazılabilir bir katman eklenir
Kaç tane? Bir imaj, bir kez indirilir Aynı imajdan istediğiniz kadar container başlatılabilir
Silme komutu docker rmi docker rm

İmaj, üst üste binmiş katmanlardan oluşur

Bir Dockerfile’daki her dosya değiştiren talimat (RUN, COPY, ADD) imaja yeni bir katman ekler. docker history bu katmanları ve her birinin boyutunu gösterir:

FROM temel-imaj
RUN echo a > /a
RUN echo b > /b
COPY . /app

$ docker history katmanli:1 --format '{{.Size}}  {{.CreatedBy}}'
16.4kB  COPY . /app # buildkit
8.19kB  RUN /bin/sh -c echo b > /b # buildkit
8.19kB  RUN /bin/sh -c echo a > /a # buildkit
14.9MB

En alttaki satır temel imajın kendisidir; üstündeki her satır, bir talimatın eklediği farktır. Bu yapının iki önemli sonucu var: katmanlar paylaşılır (aynı temel imajı kullanan on imaj, o katmanı diskte bir kez tutar) ve katmanlar önbelleğe alınır (değişmeyen talimatlar yeniden çalıştırılmaz — bkz. Build Cache ve BuildKit).

Etiket (tag) bir isimdir, imaj değildir

Bir imaja istediğiniz kadar etiket verebilirsiniz; hepsi aynı imajı işaret eder:

$ docker tag temel:1 temel:v1
$ docker tag temel:1 temel:latest
$ docker images temel --format '{{.Repository}}:{{.Tag}} {{.ID}}'
temel:1       da40800f731b
temel:latest  da40800f731b
temel:v1      da40800f731b

Üç etiketin aynı kimliği (ID) taşıdığına dikkat edin. İki yaygın yanlış anlama:

  • :latest “en yeni” demek değildir. Sadece etiket belirtmediğinizde kullanılan varsayılan isimdir; birinin onu güncelleyip güncellemediğini garanti etmez. Üretimde sabit sürüm etiketi kullanın.
  • Bir etiket zamanla başka bir imaja işaret edebilir. Gerçekten değişmez bir referans istiyorsanız içerik özetini (digest) kullanın: imaj@sha256:...

Container’ın yaşam döngüsü

Bir container birkaç durumdan geçer. docker run aslında create + start işlemlerinin kısayoludur; bunları ayrı ayrı çalıştırınca durumlar net görünür:

$ docker create --name c1 temel:1 /bin/sh -c 'echo merhaba'
$ docker ps -a --filter name=c1 --format '{{.Names}} {{.Status}}'
c1 Created

$ docker start -a c1
merhaba
$ docker ps -a --filter name=c1 --format '{{.Names}} {{.Status}}'
c1 Exited (0) Less than a second ago
Durum Anlamı Geçiş komutu
Created Oluşturuldu, henüz çalışmadı docker start
Up (running) Çalışıyor docker stop / docker kill
Exited (kod) Süreç bitti; çıkış kodu 0 başarıyı gösterir docker start / docker rm

docker stop önce SIGTERM gönderir, container belirtilen süre içinde (varsayılan 10 saniye) kapanmazsa SIGKILL ile sonlandırır. SIGTERM’e tepki vermeyen bir süreçte bu 10 saniyenin tamamını beklersiniz ve çıkış kodu 137 (128 + 9) olur — container’larınız “yavaş kapanıyor” ise sorun genellikle uygulamanın sinyali yakalamamasıdır.

Silerken: rm mı rmi mi?

Bir imajı, onu kullanan bir container (durmuş olsa bile) varken silemezsiniz:

$ docker rmi temel:1
Error response from daemon: conflict: unable to delete temel:1 (must be forced)
 - container 7237f9f8a629 is using its referenced image 7096a6e93088

Önce container’ı (docker rm), sonra imajı (docker rmi) silin. Birden fazla etiketli bir imajda docker rmi etiket yalnızca o etiketi kaldırır (Untagged: temel:v1); imajın verisi son etiket de gidene kadar diskte kalır.

i

Container içinde yazdığınız her şey, container silindiğinde yazılabilir katmanıyla birlikte gider. Kalıcı olması gereken veri için volume kullanın.

Hızlı özet

  • İmaj = salt okunur şablon (katmanlı); container = onun çalışan örneği.
  • Etiketler aynı imaja işaret eden isimlerdir; :latest özel bir anlam taşımaz.
  • Container yaşam döngüsü: Created → Up → Exited; docker run = create + start.
  • Container’ı docker rm, imajı docker rmi ile silersiniz.

Sıradaki adım: kendi imajınızı yazmak için Dockerfile Yazmaya Giriş yazısına geçebilir, ya da hiç başlamadıysanız Docker Nedir? yazısıyla temelleri tazeleyebilirsiniz.