Dockerfile'da COPY ve ADD Komutları: Hangisini Kullanmalısınız?

Dockerfile'da COPY ve ADD komutlarının farklarını, kullanım senaryolarını ve en iyi uygulamaları detaylıca öğrenin.

I
ITWISE
2 görüntülenme
Dockerfile'da COPY ve ADD Komutları: Hangisini Kullanmalısınız?

Giriş

Docker imajları oluştururken uygulama kodlarını, yapılandırma dosyalarını veya dağıtım arşivlerini imaja eklemek için COPY ve ADD komutları kullanılabilir. Basit yerel dosyalar için her iki komut aynı sonucu üretirken, arşiv dosyaları, uzak kaynaklar veya çok aşamalı yapılar söz konusu olduğunda davranışları farklılık gösterir. Bu kılavuz, her iki komutun detaylarını karşılaştırarak hangi durumda hangisini kullanmanız gerektiğini açıklamaktadır.

COPY Komutu Nasıl Çalışır?

COPY komutu, yerel dosya sistemi veya başka bir imajdan (build stage) dosya ve dizinleri Docker imajının belirli bir konumuna kopyalar. Temel kullanım şekli aşağıdaki gibidir:

COPY kaynak_dosya hedef_konum
COPY kaynak_dizin hedef_dizin/

Örnekler:

# Tek bir dosyayı kopyala
COPY app.py /app/

# Bir dizini ve içindeki tüm dosyaları kopyala
COPY src/ /app/src/

# Çok aşamalı yapıdan dosya kopyala
COPY --from=builder /app/build/output /usr/local/bin/app

COPY Komutunun Avantajları

  • Basit ve tahmin edilebilir: Sadece dosya/dizin kopyalama işlemi yapar, arşiv dosyalarını otomatik olarak çıkartmaz.
  • Yüksek performans: Sadece gerekli dosyaları kopyalar, ekstra işlemler (çıkartma, indirme) yapmaz.
  • Çok aşamalı yapılarla uyum: --from seçeneğiyle başka bir imajdan veya build aşamasından dosya kopyalama imkanı sunar.
  • İzin ve sahiplik kontrolü: --chown ve --chmod seçenekleriyle dosya izinlerini ve sahipliğini ayarlayabilirsiniz.
# Dosya sahipliğini ve izinlerini ayarla
COPY --chown=appuser:appgroup --chmod=644 config.yml /app/

# Build aşamasından dosya kopyala
COPY --from=builder /app/target/app /usr/local/bin/app

⚠️ Önemli Not: COPY komutu arşiv dosyalarını (örn. .tar.gz) olduğu gibi kopyalar. Eğer arşivin içeriğini çıkartmak istiyorsanız, ADD komutunu kullanmalısınız.

ADD Komutu Nasıl Çalışır?

ADD komutu, yerel dosyaları kopyalarken aynı zamanda arşiv dosyalarını otomatik olarak çıkartabilir, uzak kaynaklardan (HTTP/HTTPS/Git) dosya indirebilir ve hatta bunları imaja ekleyebilir. Temel kullanım şekli COPY ile aynıdır:

ADD kaynak_dosya hedef_konum
ADD kaynak_dizin hedef_dizin/

ADD Komutunun Özel Davranışları

1. Arşiv Dosyalarını Otomatik Çıkartma

ADD, yerel arşiv dosyalarını (tar, gzip, bzip2, xz) otomatik olarak çıkartır. Örneğin:

# .tar.gz arşivini çıkart ve / dizinine yerleştir
ADD rootfs.tar.gz /

# .tar.xz arşivini çıkart ve /opt dizinine yerleştir
ADD app-1.4.2-dist.tar.xz /opt/app/

💡 İpucu: Dosyanın arşiv olup olmadığına isimden değil, içeriğinden karar verilir. Eğer arşiv olarak tanınmayan bir dosya ADD ile kullanılırsa, hata oluşmaz ve dosya olduğu gibi kopyalanır.

2. Uzak Kaynaklardan Dosya İndirme

ADD, HTTP/HTTPS URL'lerinden dosya indirebilir. BuildKit ile birlikte --checksum seçeneği kullanılarak indirilen dosyanın SHA-256 hash değeri doğrulanabilir. Örneğin:

# syntax=docker/dockerfile:1
ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d \
     https://example.com/app.tar.gz /tmp/app.tar.gz

⚠️ Uyarı: Uzak arşiv dosyaları varsayılan olarak indirilir fakat çıkartılmaz. Dockerfile syntax 1.17 ve üzeri için --unpack=true seçeneğiyle hem indirme hem de çıkartma işlemi tek adımda yapılabilir.

3. Git Depolarını Klonlama

ADD, Git depolarını klonlayabilir. Belirli bir dal, etiket, commit veya alt dizin seçilebilir. Örneğin:

# Belirli bir branch'i klonla
ADD --keep-git-dir=true https://github.com/user/repo.git#main /app/repo

# Belirli bir commit'i klonla ve checksum ile doğrula
ADD --checksum=sha1:abc123... https://github.com/user/repo.git#v1.0.0 /app/repo

COPY ve ADD Arasındaki Temel Farklar

Kaynak veya Davranış COPY ADD
Yerel dosya ve dizinler Kopyalar Kopyalar
Yerel arşiv dosyaları Arşivi olduğu gibi kopyalar Varsayılan olarak arşivden çıkarır
Uzak HTTP/HTTPS URL Desteklenmez Dosyayı indirir
Uzak Git deposu Desteklenmez Depoyu klonlar
Uzak kaynak checksum doğrulaması Uygulanamaz --checksum seçeneği
Uzak arşivin otomatik çıkartılması Desteklenmez --unpack=true
Build aşaması, isimli kontekst veya imaj --from seçeneği Desteklenmez

Hangi Durumda Hangi Komutu Kullanmalısınız?

COPY Komutunu Kullanmanız Gereken Durumlar

  1. Uygulama kodları ve yapılandırma dosyaları: Uygulamanızın kaynak kodunu, Dockerfile'ınızın bulunduğu dizinden imaja kopyalarken COPY kullanın.
    COPY src/ /app/src/
    COPY config.yml /app/config/
  2. Çok aşamalı build işlemleri: Derlenmiş ikili dosyaları (binary) üretim imajına kopyalarken COPY --from kullanın.
    # Derleyici aşamasından çıktıyı üretim imajına kopyala
    COPY --from=builder /app/target/app /usr/local/bin/app
  3. Statik dosyalar ve kaynaklar: Web uygulamalarındaki statik dosyaları (JS, CSS, HTML) kopyalarken COPY tercih edilmelidir.
    COPY static/ /usr/share/nginx/html/
  4. Arşiv dosyalarını olduğu gibi saklamak: Eğer arşiv dosyasını imaja eklemek ve daha sonra elle çıkartmak istiyorsanız, COPY kullanın.
    COPY app-1.4.2.tar.gz /opt/app/
    # Daha sonra RUN komutunda elle çıkart
    RUN tar -xzf /opt/app/app-1.4.2.tar.gz -C /opt/app/

💡 En İyi Uygulama: Docker topluluğu, COPY komutunu arşiv dosyaları için tercih etmenizi önermektedir. Bu sayede arşivin bütünlüğü korunur ve gereksiz otomatik çıkartma işlemlerinden kaçınılmış olur.

ADD Komutunu Kullanmanız Gereken Durumlar

  1. Arşiv dosyalarının otomatik çıkarılması: Uygulama arşivini doğrudan imaja eklemek ve içeriklerini çıkartmak istiyorsanız ADD kullanın.
    # Uygulama arşivini çıkar ve /opt/app dizinine yerleştir
    ADD app-1.4.2-dist.tar.gz /opt/app/
  2. Uzak kaynaklardan dosya indirme: Build sürecinde doğrudan bir URL'den dosya indirmek istiyorsanız ADD kullanın. Özellikle BuildKit ile checksum doğrulaması yapabilirsiniz.
    # syntax=docker/dockerfile:1
    ADD --checksum=sha256:abc123... https://example.com/app.tar.gz /tmp/app.tar.gz
  3. Git depolarını klonlama: Uzak bir Git deposunu doğrudan Dockerfile'a eklemek ve klonlamak istiyorsanız ADD komutunu kullanın.
    ADD https://github.com/user/repo.git#main /app/repo
  4. Root dosya sistemi oluşturma: Linux sistemlerinin root dosya sistemini oluşturmak için arşiv dosyalarını çıkartırken ADD kullanışlıdır.
    ADD alpine-minirootfs-3.18.0-x86_64.tar.gz /

⚠️ Dikkat Edilmesi Gerekenler: Uzak kaynaklardan dosya indirirken, indirilen dosyanın geçerliliğini doğrulamak için --checksum kullanın. Ayrıca, indirilen dosyaların imaj katmanlarında kalıcı olmasını istemiyorsanız, RUN komutunda geçici dizinlere indirip işledikten sonra silin.

Pratik Örnekler

Örnek 1: Yerel Dosya Kopyalama (COPY)

Basit bir Node.js uygulaması için Dockerfile örneği:

# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app

# Uygulama kodunu kopyala
COPY package*.json ./
RUN npm install

# Kaynak kodunu kopyala
COPY src/ ./src

# Uygulamayı çalıştır
CMD ["node", "src/index.js"]

Örnek 2: Arşiv Dosyasını Çıkartma (ADD)

Bir Python uygulamasının arşiv halindeki bağımlılıklarını çıkartıp kullanma örneği:

# syntax=docker/dockerfile:1
FROM python:3.11-slim
WORKDIR /app

# Arşiv dosyasını çıkar ve bağımlılıkları yükle
ADD requirements.tar.gz /tmp/
RUN pip install -r /tmp/requirements.txt

# Uygulama kodunu kopyala
COPY app.py .

CMD ["python", "app.py"]

Örnek 3: Uzak Kaynaklardan Dosya İndirme (ADD)

Build sürecinde doğrudan bir URL'den dosya indirme ve doğrulama örneği:

# syntax=docker/dockerfile:1
FROM alpine:latest

# Doğrulanmış bir arşiv dosyasını indir ve çıkar
ADD --checksum=sha256:abc123... https://example.com/tool-v1.0.0.tar.gz /opt/tool/

# Aracı çalıştırılabilir yap
RUN chmod +x /opt/tool/tool && \
    ln -s /opt/tool/tool /usr/local/bin/tool

Sonuç

COPY ve ADD komutları arasındaki seçim, kullanım amacınıza bağlıdır. Genel kural olarak:

  • Yerel dosyalar ve çok aşamalı build işlemleri için COPY kullanın. Bu komut daha basit, tahmin edilebilir ve performanslıdır.
  • Arşiv dosyalarının otomatik çıkarılması, uzak kaynaklardan dosya indirme veya Git depolarını klonlama için ADD kullanın.

COPY komutu, Docker imajlarınızın katman sayısını ve karmaşıklığını azaltırken, ADD komutu özel durumlar için esneklik sağlar. Dockerfile yazarken her iki komutun da avantajlarını ve sınırlamalarını göz önünde bulundurarak en uygun olanı seçin.

Daha fazla bilgi için Docker belgelerine ve Dockerfile en iyi uygulamalarına göz atabilirsiniz:

Kaynak

Linuxize