Dockerfile'da Koşullu KOPYALAMA / EKLEME?


105

Dockerfiles dosyalarımın içinde, eğer mevcutsa imajıma bir dosya KOPYALAMAK istiyorum, pip için requirements.txt dosyası iyi bir aday gibi görünüyor ama bu nasıl başarılabilir?

COPY (requirements.txt if test -e requirements.txt; fi) /destination
...
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

veya

if test -e requirements.txt; then
    COPY requiements.txt /destination;
fi
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

Lütfen buraya bakın: docs.docker.com/reference/builder
Tuan

4
@Tuan - Bu bağlantıda özellikle ne yardımcı olur?
ToolmakerSteve

Yanıtlar:


26

Bu şu anda desteklenmiyor (aynı Dockerfile, varlığına bağlı olarak dosyayı kopyalayıp kopyalayamayacağı için yeniden üretilemeyen görüntüye yol açacağından şüphelendiğim için).

Bu hala joker karakterler kullanılarak 13045 sayısında istenmektedir : " COPY foo/* bar/" not work if no file in foo" (Mayıs 2015).
Şimdilik (Temmuz 2015) Docker'da uygulanmayacak, ancak bocker gibi başka bir derleme aracı bunu destekleyebilir.


35
iyi cevap, ancak liman işçisi mantığı, IMO, kusurlu. Aynı dockerfile'ı farklı bir yapı bağlamıyla çalıştırırsanız, farklı bir görüntü elde edersiniz. beklenen bir şey. aynı yapı bağlamını kullanmak aynı görüntüyü verecektir. ve aynı yapı bağlamına koşullu KOPYALA / EKLE talimatlarını eklerseniz, aynı görüntüyü elde edersiniz. böylece kontrol edilir. bu sadece benim 2 sentim.
nathan g

Docker, değişmez altyapıyla ilgilidir. Geliştirme, hazırlık ve üretim ortamlarınız aynı değilse de mümkün olduğu kadar% 99,99 oranında yakın olmalıdır. Ortam değişkenlerini kullanın.
AndrewMcLagan

3
@AndrewMcLagan, örneğin, bir ön uç devortamı bir web paketi dev sunucusuyla prodçalışıyorsa ve eşdeğer ortam /diststatik bir klasörle çalışıyorsa? Günümüzde çoğu ön uç kurulumunda durum budur ve açıkçası devve prodburada aynı olamaz. Peki bununla nasıl başa çıkılır?
Jivan

Düğüm ön uçlarımı geliştirmek için docker kullanmıyorum. Normal web paketi localhost: 3000 vs. Örneğin API'ler, redis, MySQL, mongo, elastik arama ve diğer mikro hizmetler. Bir kapta .. bir web paketi geliştirme ortamı çalıştırabilirsiniz. Ama bunun çok uzak olduğunu hissediyorum ...
AndrewMcLagan

@Jivan Genel talimatları tanımlamak için bir onbuild imajı kullanmaya ve ardından geliştirme ve prod için özel imajlar oluşturmaya ne dersiniz? Docker Hub Düğüm deposu, her Node sürümü için onbuild görüntüleri içeriyor gibi görünür: hub.docker.com/_/node . Ya da kendi başınıza dönebilirsiniz.
david_i_smith

86

İşte basit bir çözüm:

COPY foo file-which-may-exist* /target

Makyaj emin fooberi var olan COPYihtiyaçları en az bir geçerli kaynağı.

Varsa file-which-may-exist, o da kopyalanacaktır.

NOT: Joker karakterinizin, kopyalamak istemediğiniz diğer dosyaları almamasına dikkat etmelisiniz. Daha dikkatli olmak için file-which-may-exist?bunun yerine kullanabilirsiniz ( ?yalnızca tek bir karakterle eşleşir).

Daha da iyisi, yalnızca bir dosyanın eşleşebilmesini sağlamak için bunun gibi bir karakter sınıfı kullanın:

COPY foo file-which-may-exis[t] /target

1
Aynı şeyi bir klasörle yapabilir misin?
Benjamin Toueg

1
@BenjaminToueg: Evet, belgelere göre dosyaları ve klasörleri kopyalayabilirsiniz.
jdhildeb

2
Bu harika çalışıyor. Birden çok hedefi olan dosyalar için, geçici bir dizine kopyaladım ve ardından bunları gereken yere taşıdım. COPY --from=docker /usr/bin/docker /usr/lib/libltdl.so* /tmp/docker/ RUN mv /tmp/docker/docker /usr/bin/docker RUN mv /tmp/docker/libltdl.so.7 /usr/lib/libltdl.so.7 || true(paylaşılan kitaplığın bilinmeyen varlık olduğu yerde.)
Adam K Dean

Birden fazla mevcut dosyayı kopyalarken, hedef bir dizin olmalıdır. Hem foo hem de var olan dosyanız * varken bu nasıl çalışır?
melchoir55

1
Öyleyse cevap 'bir dosya olduğundan emin olun' ve ardından COPY operatörünün nasıl kullanılacağına dair bir gösteri mi? Bunun orijinal soruyla nasıl bir ilgisi olduğunu göremiyorum.
2018

29

Bu yorumda belirtildiği gibi , Santhosh Hirekerur'un cevabı hala dosyayı kopyalıyor, gerçek bir koşullu kopyayı arşivlemek için bu yöntemi kullanabilirsiniz.

ARG BUILD_ENV=copy

FROM alpine as build_copy
ONBUILD COPY file /file

FROM alpine as build_no_copy
ONBUILD RUN echo "I don't copy"

FROM build_${BUILD_ENV}
# other stuff

ONBUILDTalimatları "dal" tarafından seçilirse dosya sadece kopyalanmış olmasını sağlar BUILD_ENV. Çağrmadan önce küçük bir komut dosyası kullanarak bu değişkeni ayarlayındocker build


2
Bu yanıtı beğendim çünkü gözlerimi sadece çok kullanışlı olan ONBUILD'e değil, aynı zamanda iletilen diğer değişkenlerle entegrasyonu en kolay gibi görünüyor, örneğin etiketi BUILD_ENV'ye göre ayarlamak veya bazı durumları saklamak istiyorsanız ENV.
DeusXMachina

Bunun gibi bir şey denedim ve şunu aldım: daemon'dan gelen hata yanıtı: Dockerfile ayrıştırma hata satırı 52: inşa aşaması için geçersiz ad: "site_builder _ $ {host_env}", ad bir sayı ile başlayamaz veya semboller içeremez
paulecoyote

10

Çözüm Bulma

ENV Değişkenlerine göre FOLDER'ı sunucuya kopyalamam gerekiyordu. Boş sunucu imajını aldım. yerel klasörde gerekli dağıtım klasörü yapısını oluşturdu. daha sonra DockerFile'a satırın altına eklendi , klasörü konteynere kopyalayın. Ben liman işçisi sunucusunu başlamadan önce n son satırı eklendi giriş noktası init file.sh yürütmek.

#below lines added to integrate testing framework
RUN mkdir /mnt/conf_folder
ADD install /mnt/conf_folder/install
ADD install_test /mnt/conf_folder/install_test
ADD custom-init.sh /usr/local/bin/custom-init.sh
ENTRYPOINT ["/usr/local/bin/custom-init.sh"]

Ardından aşağıdaki gibi bir komut dosyasıyla yerel olarak custom-init.sh dosyasını oluşturun

#!/bin/bash
if [ "${BUILD_EVN}" = "TEST" ]; then
    cp -avr /mnt/conf_folder/install_test/* /mnt/wso2das-3.1.0/
else
    cp -avr /mnt/conf_folder/install/* /mnt/wso2das-3.1.0/
fi;

In liman işçisi-oluşturma hatları aşağıda dosyası.

ortam: - BUILD_EVN = TEST

Bu değişiklikler, docker oluşturma sırasında klasörü kapsayıcıya kopyalar. docker-compose up'ı çalıştırdığımızda , sunucu başlamadan önce asıl gerekli klasörü sunucuya kopyalar veya dağıtır.


8
Ancak docker görüntüleri katmanlıdır. ADD, bahsettiğiniz if ifadesine bakılmaksızın bunları resme kopyalar ...
MyUserInStackOverflow

@MyUserInStackOverflow - Sanırım bu "geçici çözüm", hem install hem de install_test'in görüntüye kopyalanması, ancak görüntü çalıştırıldığında, bu klasörlerden yalnızca birinin son konuma kopyalanmasıdır. Her ikisinin de resimde bir yerde olması sorun değilse, bu makul bir teknik olabilir.
ToolmakerSteve

5

Tüm dosyaları bir atılabilir dizine kopyalayın, istediğinizi elle seçin, gerisini atın.

COPY . /throwaway
RUN cp /throwaway/requirements.txt . || echo 'requirements.txt does not exist'
RUN rm -rf /throwaway

cpKoşullu kopyalamayı kullanarak aynı çözüme dayanan derleme aşamalarını kullanarak benzer bir şey elde edebilirsiniz . Bir derleme aşaması kullandığınızda, son görüntünüz baştaki tüm içeriği içermeyecektir COPY.

FROM alpine as copy_stage
COPY . .
RUN mkdir /dir_for_maybe_requirements_file
RUN cp requirements.txt /dir_for_maybe_requirements_file &>- || true

FROM alpine
# Must copy a file which exists, so copy a directory with maybe one file
COPY --from=copy_stage /dir_for_maybe_requirements_file /
RUN cp /dir_for_maybe_requirements_file/* . &>- || true
CMD sh

Bu teknik olarak sorunu çözerken, görüntünün boyutunu küçültmez. Koşullu olarak çok büyük bir şeyi kopyalamaya çalışıyorsanız (derin bir ağ modeli gibi), overlay fs'nin çalışma şekli nedeniyle hala görüntünün boyutunu şişirmiş olursunuz.
DeusXMachina

@DeusXMachina, docker'ın hangi sürümünü kullanıyorsunuz? Dokümanlar söylediklerinizle çelişiyor . Docs.docker.com/develop/develop-images/multistage-build/… . Katmanlar, nihai olmayan bir yapım aşamasından korunmamalıdır.
cdosborn

@cdosburn - Bunu 18.09.2020 tarihinde gözlemledim. Çoğunlukla ilk örnek hakkında konuşuyordum, aşamalı yapılar bu sorundan kaçınmalıdır. Ve şimdi her FROM aşamasının yoğunlaştığını düşünüyorum, ama benim hatırladığımı ikinci kez tahmin ettim. Bazı şeyleri denemem gerekecek.
DeusXMachina

@DeusXMachina, doğru yalnızca ikinci çözüm görüntü boyutunu küçültür.
cdosborn

bu benim durumum için güzel bir çözüm. Bir kopyalıyorum cacheve önbelleğin ne olduğuna bağlı olarak komut dosyalarında ne yapacağımı seçiyorum!
Paschalis

1

Diğer fikirleri denedim, ancak hiçbiri ihtiyacımızı karşılamadı. Buradaki fikir, alt statik web uygulamaları için temel nginx görüntüsü oluşturmaktır. Güvenlik, optimizasyon ve standardizasyon nedenleriyle, temel görüntünün RUNalt görüntüler tarafından eklenen dizinlere komut verebilmesi gerekir . Temel görüntü, alt görüntüler tarafından hangi dizinlerin eklendiğini kontrol etmez. Varsayım, çocuk görüntülerinin COPYaltında bir yerde kaynak oluşturacağıdır COMMON_DEST_ROOT.

Bu yaklaşım bir hack'tir, ancak temel resim, COPYalt imaj tarafından eklenen 1'den N'ye kadar dizine yönelik talimatları destekleyecektir . ARG PLACEHOLDER_FILEve ENV UNPROVIDED_DESTtatmin etmek için kullanılır <src>ve <dest>herhangi gereksinimleri COPYtalimat değil gerekli.

#
# base-image:01
#
FROM nginx:1.17.3-alpine
ENV UNPROVIDED_DEST=/unprovided
ENV COMMON_DEST_ROOT=/usr/share/nginx/html
ONBUILD ARG PLACEHOLDER_FILE
ONBUILD ARG SRC_1
ONBUILD ARG DEST_1
ONBUILD ARG SRC_2
ONBUILD ARG DEST_2
ONBUILD ENV SRC_1=${SRC_1:-PLACEHOLDER_FILE}
ONBUILD ENV DEST_1=${DEST_1:-${UNPROVIDED_DEST}}
ONBUILD ENV SRC_2=${SRC_2:-PLACEHOLDER_FILE}
ONBUILD ENV DEST_2=${DEST_2:-${UNPROVIDED_DEST}}

ONBUILD COPY ${SRC_1} ${DEST_1}
ONBUILD COPY ${SRC_2} ${DEST_2}

ONBUILD RUN sh -x \
    #
    # perform operations on COMMON_DEST_ROOT
    #
    && chown -R limited:limited ${COMMON_DEST_ROOT} \
    #
    # remove the unprovided dest
    #
    && rm -rf ${UNPROVIDED_DEST}

#
# child image
#
ARG PLACEHOLDER_FILE=dummy_placeholder.txt
ARG SRC_1=app/html
ARG DEST_1=/usr/share/nginx/html/myapp
FROM base-image:01

Bu çözümün, desteklenen kukla PLACEHOLDER_FILEve sabit kodlanmış COPY yönergeleri sayısı gibi bariz eksiklikleri vardır. Ayrıca COPY komutunda kullanılan ENV değişkenlerinden kurtulmanın bir yolu yoktur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.