2016-11-05 42 views
3

我想將文件系統中的白名單文件夾複製到目標容器中。Docker COPY行爲不一致

基本上我想執行「複雜」操作cp -r app vendor target,其中target是一個Docker容器。

我有簡單的碼頭工人文件:

FROM alpine 

COPY app/* /www/ 
COPY vendor /www/ 

不知什麼原因的第一個命令不復制app目錄本身。看起來Docker並沒有區分appapp/之間的區別,這是相當令人惱火的。

出於測試目的,我創建了以下結構:

. 
├── app 
│   ├── foo 
│   └── second 
│    └── barf 
├── Dockerfile 
└── vendor 
    └── bar 

docker build -t test . && docker run -it test ash

結果?不保存目錄結構,不復制父目錄。

/www/ 
├── bar 
├── barf 
└── foo 

docker info

Server Version: 1.12.1 
Storage Driver: overlay2 
Backing Filesystem: extfs 

任何人都可以解釋我爲什麼泊塢窗的COPY . /targetCOPY app/* /target行爲不同?動機是什麼?爲什麼Docker不使用UNIX cp命令的標準語義?

回答

1

通常,COPY指令從「/ app」複製文件和/或目錄,並將它們添加到路徑爲「/ www /」的容器中。如果你想擁有「/網絡/」那麼你的COPY指令內部的「應用程序」目錄應該是這樣的:

COPY /app /www/app/ 


你可以documentation閱讀更多有關COPY指令。在這裏,我貼的這種行爲解釋從it

如果是一個目錄,目錄中的全部內容被複制,包括文件系統元數據。 注意:目錄本身不會被複制,只是它的內容。



關於你的更新:
COPY . /targetCOPY app /target行爲相同。它從源目錄(從app或從.目錄)需要整個內容並將其複製到/target目錄。


當你使用通配符時,你可以看到稍微不同的行爲,例如。 COPY app/* /www/。它將所有文件從app/複製到/www/,但它然後像app/一樣處理每個單獨的目錄,並將其內容複製到/www/

爲什麼在Docker COPY中的執行方式與在UNIX的cp命令中不同?我不知道,但如果你想要,你可以創建與自己的執行拉請求:)

+0

好的,但爲什麼'vendor'目錄被創建呢? – Tombart

+0

你可以從「./app」目錄中列出本地機器上的所有目錄嗎?我很確定你在「./app」 –

+0

裏有「vendor」目錄。這就是我原先想的。不,它不在那裏。當目標'/ app/vendor'已經存在於容器中時,docker可能會有不同的行爲? – Tombart

0

這似乎是一個known issue in Docker這將不會很快得到修復。

有幾個解決方法如何指定多個文件夾和複製文件夾本身和所需的內容。請注意,您不能使用星號(如app/*這將導致扁平化目錄結構。

COPY命令

RUN mkdir -p app bin config db lib public 
COPY app/ app 
COPY bin/ bin 
COPY config/ config 
COPY db/ db 
COPY lib/ lib 
COPY public/ public 

在某些情況下,這產生相當長的列表,並在每個命令創建一個單獨的層在圖像樹。

使用tar

使用tarMakefile的優點是它的行爲與正確的UNIX程序相同(您可以定義排除模式,斜線,*等)。

Makefile

all: 
    tar -cf files.tar app bin config db lib public 
    docker build -t image-name . 
    rm files.tar 

然後Dockerfile你必須以提取文件到所需的結構使用ADD命令:

ADD files.tar /www 

使用.dockerignore

Dockerfile簡單複製一切都在

COPY . /www 

.dockeringnore列表不應該複製的所有模式:

.git 
test/ 
doc/ 
log/ 
tmp/ 
Dockerfile 
Makefile 

注意,一旦你忽略父文件夾,有沒有辦法如何手動從已經在文件夾複製單個文件忽略(related Docker issue):

COPY doc/README /www 

只是不會執行。