2014-11-01 12 views
11

Ho bisogno del contenuto di un grande file *.zip (5 GB) nel mio contenitore Docker per compilare un programma. Il file *.zip si trova sul mio computer locale. La strategia per questo sarebbe:Come aggiungere un file a un'immagine in Dockerfile senza utilizzare la direttiva ADD o COPY

COPY program.zip /tmp/ 
RUN cd /tmp \ 
&& unzip program.zip \ 
&& make 

Dopo aver fatto questo vorrei rimuovere la directory decompressi e il file originale *.zip perché non sono più necessarie. Il problema è che la direttiva COPY (e anche la direttiva ADD) aggiungerà un livello all'immagine che conterrà il file program.zip che è problematico in quanto l'immagine potrebbe avere una dimensione di almeno 5 GB. C'è un modo per aggiungere un file a un contenitore senza utilizzare la direttiva COPY o ADD? wget non funzionerà in quanto il file menzionato *.zip si trova sul mio computer locale e curl file://localhost/home/user/program.zip -o /tmp/program.zip non funzionerà neanche.

+0

Non puoi semplicemente decomprimerlo prima sul tuo computer locale? E poi aggiungi le cose che ti servono? – Nick

+0

Sì, ma voglio anche eliminare la cartella decompressa in quanto sarà ancora superiore a 5 GB. Ma ho trovato un modo per fare ciò che voglio. La risposta è sulla sua strada. –

+0

e un file make.sh che crea e rimuove il file? – Rondo

risposta

17

Non è semplice ma può essere effettuato tramite wget o curl con un piccolo supporto da python. (Tutti e tre gli strumenti di solito dovrebbe essere disponibile su un sistema *nix.)

wget non funziona quando nessun url è dato e

curl file://localhost/home/user/program.zip -o /tmp/ 

non funziona all'interno di un RUN istruzioni s' Dockerfile. Quindi, avremo bisogno di un server che sia wget e curl possa accedere e scaricare program.zip da.

Per fare ciò installiamo un piccolo server python che serve le nostre richieste http. Per questo utilizzeremo il modulo http.server da python. (È possibile utilizzare python o python 3. Funzionerà con entrambi.).

python -m http.server --bind 192.168.178.20 8000 

Il server python servirà tutti i file nella directory viene avviato in. Quindi, è necessario assicurarsi che si avvia il server sia nella directory del file che si desidera scaricare durante il vostro costruire un'immagine risiede o creare una directory temporanea che contiene il tuo programma. A scopo illustrativo creiamo il file foo.txt che verrà in seguito scaricare via wget nel nostro Dockerfile:

echo "foo bar" > foo.txt 

Quando si avvia il server http, è importante che noi specificare l'indirizzo IP della nostra macchina locale sulla LAN. Inoltre, apriremo Port 8000. Dopo aver fatto questo si dovrebbe vedere il seguente output:

python3 -m http.server --bind 192.168.178.20 8000 
Serving HTTP on 192.168.178.20 port 8000 ... 

Ora costruiamo una Dockerfile per illustrare come funziona.(Si assume che il file foo.txt deve essere scaricato in /tmp):

FROM debian:latest 
RUN apt-get update -qq \ 
&& apt-get install -y wget 
RUN cd /tmp \ 
&& wget http://192.168.178.20:8000/foo.txt 

Ora si comincia la costruzione con

docker build -t test . 

Durante la compilazione si vedrà il seguente output sul nostro server python:

172.17.0.21 - - [01/Nov/2014 23:32:37] "GET /foo.txt HTTP/1.1" 200 - 

e l'uscita di costruzione della nostra immagine sarà:

0.123.
Step 2 : RUN cd /tmp && wget http://192.168.178.20:8000/foo.txt 
---> Running in 49c10e0057d5 
--2014-11-01 22:56:15-- http://192.168.178.20:8000/foo.txt 
Connecting to 192.168.178.20:8000... connected. 
HTTP request sent, awaiting response... 200 OK 
Length: 25872 (25K) [text/plain] 
Saving to: `foo.txt' 

    0K .......... .......... .....       100% 129M=0s 

2014-11-01 22:56:15 (129 MB/s) - `foo.txt' saved [25872/25872] 

---> 5228517c8641 
Removing intermediate container 49c10e0057d5 
Successfully built 5228517c8641 

È quindi possibile verificare se davvero lavorato avviando e inserendo un contenitore dal immagine appena costruire:

docker run -i -t --rm test bash 

Si può quindi cercare in /tmp per foo.txt.

Ora possiamo aggiungere qualsiasi file al nostro image senza creare un nuovo livello. Supponendo che si desidera aggiungere un programma di circa 5 GB come indicato nella domanda che potremmo fare:

FROM debian:latest 
RUN apt-get update -qq \ 
&& apt-get install -y wget 
RUN cd /tmp \ 
&& wget http://conventiont:8000/program.zip \ 
&& unzip program.zip \ 
&& cd program \ 
&& make \ 
&& make install \ 
&& cd /tmp \ 
&& rm -f program.zip \ 
&& rm -rf program 

In questo modo non saremo lasciati con 10 GB di cruft.

+0

intelligente! Bisogno di ospitare questo su qualcosa come aws se si vuole fare una build affidabile. – retrohacker

+0

Ottima risposta! Grazie. – mkoertgen

+0

Questo approccio è ottimo, ma richiede all'host di avere un IP stabile, altrimenti è necessario continuare a cambiare l'indirizzo IP utilizzato nel wget nel guest. Sarebbe bello avere una soluzione per affrontare anche questo (non ho ancora avuto buone idee!). –

2

Impossibile eseguire il mapping di una cartella locale al contenitore quando viene avviato e quindi copiare i file necessari.

sudo docker run -d -P --name myContainerName -v /localpath/zip_extract:/container/path/ yourContainerID 

https://docs.docker.com/userguide/dockervolumes/

+0

Probabilmente dovrei decomprimere e compilare il programma ogni volta che il contenitore si avvia (oppure farlo almeno una volta all'avvio del contenitore e quindi eseguirlo). Volevo una singola soluzione basata su 'Dockerfile'. –

+0

Ah, avendo letto la tua risposta, ora vedo cosa stavi cercando di fare. Bella soluzione La mappatura del volume – Emile

+0

può essere eseguita solo durante "esegui" non durante "build". Quando aggiungi volumi su build alcuni strumenti (compresi vagabondi) auto-aggiungi/copia. Non lo vuoi perché ogni istruzione aggiuntiva verrà compilata su un livello di deltay nell'immagine finale della finestra mobile. – mkoertgen

Problemi correlati