Come generare un file Docker da un'immagine?


241

È possibile generare un file Docker da un'immagine? Voglio sapere per due motivi:

  1. Posso scaricare immagini dal repository ma vorrei vedere la ricetta che le ha generate.

  2. Mi piace l'idea di salvare le istantanee, ma una volta terminato sarebbe bello avere un formato strutturato per rivedere ciò che è stato fatto.


Puoi usare Portainer.io portainer.io È un'app Web che viene eseguita all'interno di un contenitore docker utilizzato per gestire tutte (quasi) le informazioni sui tuoi contenitori. Anche le immagini ricevono.
Vincent,

Risposte:


98

Come generare o invertire un file Docker da un'immagine?

Puoi.

alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"
dfimage -sV=1.36 nginx:latest

Verrà automaticamente estratta l'immagine della finestra mobile di destinazione ed esportata Dockerfile. Il parametro -sV=1.36non è sempre richiesto.

Riferimento: https://hub.docker.com/repository/docker/alpine/dfimage

di seguito è la vecchia risposta, non funziona più.

$ docker pull centurylink/dockerfile-from-image
$ alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm centurylink/dockerfile-from-image"
$ dfimage --help
Usage: dockerfile-from-image.rb [options] <image_id>
    -f, --full-tree                  Generate Dockerfile for all parent layers
    -h, --help                       Show this message

3
Questo è il modo Docker e dovrebbe essere contrassegnato come risposta scelta.
kytwb,

2
@jenson non è esattamente lo stesso, può coprire il 95%. Ma non funziona con l'immagine schiacciata.
BMW

5
@BMW Potresti aiutare a risolvere questo problema eseguendo l'immagine dal tuo esempio? /usr/lib/ruby/gems/2.2.0/gems/excon-0.45.4/lib/excon/unix_socket.rb:14:in `connect_nonblock ': Connessione rifiutata - connect (2) per / var / run / docker .sock (Errno :: ECONNREFUSED) (Excon :: Errori :: SocketError)
lungo

8
centurylink / dockerfile-from-image non funziona con la nuova finestra mobile versione. Questo funziona per me: hub.docker.com/r/chenzj/dfimage
aleung

6
imagelayers.io sembra essere rotto. Non riesce a trovare alcuna immagine, comprese quelle demo
Robert Lugg, del

165

Per capire come è stata creata un'immagine docker, utilizzare il docker history --no-trunccomando

È possibile creare un file docker da un'immagine, ma non conterrà tutto ciò che si desidera comprendere appieno come è stata generata l'immagine. Ciò che è possibile estrarre è ragionevolmente le parti MAINTAINER, ENV, EXPOSE, VOLUME, WORKDIR, ENTRYPOINT, CMD e ONBUILD del file docker.

Il seguente script dovrebbe funzionare per te:

#!/bin/bash
docker history --no-trunc "$1" | \
sed -n -e 's,.*/bin/sh -c #(nop) \(MAINTAINER .*[^ ]\) *0 B,\1,p' | \
head -1
docker inspect --format='{{range $e := .Config.Env}}
ENV {{$e}}
{{end}}{{range $e,$v := .Config.ExposedPorts}}
EXPOSE {{$e}}
{{end}}{{range $e,$v := .Config.Volumes}}
VOLUME {{$e}}
{{end}}{{with .Config.User}}USER {{.}}{{end}}
{{with .Config.WorkingDir}}WORKDIR {{.}}{{end}}
{{with .Config.Entrypoint}}ENTRYPOINT {{json .}}{{end}}
{{with .Config.Cmd}}CMD {{json .}}{{end}}
{{with .Config.OnBuild}}ONBUILD {{json .}}{{end}}' "$1"

Lo uso come parte di uno script per ricostruire i contenitori in esecuzione come immagini: https://github.com/docbill/docker-scripts/blob/master/docker-rebase

Il Dockerfile è utile soprattutto se si desidera essere in grado di riconfezionare un'immagine.

La cosa da tenere a mente è che un'immagine docker può effettivamente essere solo il backup tar di una macchina reale o virtuale. Ho realizzato diverse immagini docker in questo modo. Anche la cronologia di compilazione mi mostra come importare un enorme file tar come primo passo nella creazione dell'immagine ...


1
Mi fa venire: json: impossibile annullare la divisione dell'array nel valore Go di tipi di tipi.ContainerJSON
Mohsen

Puoi descrivere il tuo ultimo commento in modo più dettagliato? Tutto è / è tarato normalmente? O ci sono casi speciali?
Robert Lugg,

Suppongo che questa sia una risposta di 6 anni, ma sto ricevendoError response from daemon: page not found
João Ciocca

53

In qualche modo ho assolutamente perso il comando effettivo nella risposta accettata, quindi eccolo di nuovo, un po 'più visibile nel suo stesso paragrafo, per vedere quante persone sono come me

$ docker history --no-trunc <IMAGE_ID>

1
Allora perché ne abbiamo bisogno ub.docker.com/r/chenzj/dfimage? È anche una risposta più recente.
lucid_dreamer,

3
Immagino perché docker historystampa le righe del Dockerfile in un ordine inverso e rilascia le RUNistruzioni (ottieni solo il comando stesso, non il RUNkeyworkd davanti ad esso) e altre cose, quindi devi modificarlo manualmente per arrivare a un Dockerfile costruibile. L'altro strumento potrebbe eseguire questa modifica automaticamente per te (non l'ho provato, quindi non lo so.)
user7610,

@utente7610 il tuo comando mostra solo la cronologia dell'immagine estratta dall'hub. Come posso vedere i miei comandi sulle immagini della finestra mobile?
BarzanHayati,

@BarzanHayati Puoi fare una nuova domanda e collegarla qui? Sii molto preciso quando chiedi. Mostra il comando per avviare l'immagine, quindi invia alcuni comandi che desideri visualizzare in seguito, ad esempio, quindi arresta il contenitore (se è quello che fai effettivamente nella realtà), quindi chiedi come recuperare i comandi emessi. Grazie.
user7610

1
@ user7610 Potrei chiederlo, ma non appena l'ho chiesto, devo eliminarlo perché altri utenti mi danno meno punti per una domanda ripetuta.
BarzanHayati,

35

Una soluzione bash:

docker history --no-trunc $argv  | tac | tr -s ' ' | cut -d " " -f 5- | sed 's,^/bin/sh -c #(nop) ,,g' | sed 's,^/bin/sh -c,RUN,g' | sed 's, && ,\n  & ,g' | sed 's,\s*[0-9]*[\.]*[0-9]*\s*[kMG]*B\s*$,,g' | head -n -1

Spiegazioni dettagliate:

tac : reverse the file
tr -s ' '                                       trim multiple whitespaces into 1
cut -d " " -f 5-                                remove the first fields (until X months/years ago)
sed 's,^/bin/sh -c #(nop) ,,g'                  remove /bin/sh calls for ENV,LABEL...
sed 's,^/bin/sh -c,RUN,g'                       remove /bin/sh calls for RUN
sed 's, && ,\n  & ,g'                           pretty print multi command lines following Docker best practices
sed 's,\s*[0-9]*[\.]*[0-9]*\s*[kMG]*B\s*$,,g'      remove layer size information
head -n -1                                      remove last line ("SIZE COMMENT" in this case)

Esempio:

 ~  dih ubuntu:18.04
ADD file:28c0771e44ff530dba3f237024acc38e8ec9293d60f0e44c8c78536c12f13a0b in /
RUN set -xe
   &&  echo '#!/bin/sh' > /usr/sbin/policy-rc.d
   &&  echo 'exit 101' >> /usr/sbin/policy-rc.d
   &&  chmod +x /usr/sbin/policy-rc.d
   &&  dpkg-divert --local --rename --add /sbin/initctl
   &&  cp -a /usr/sbin/policy-rc.d /sbin/initctl
   &&  sed -i 's/^exit.*/exit 0/' /sbin/initctl
   &&  echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
   &&  echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean
   &&  echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean
   &&  echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean
   &&  echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages
   &&  echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes
   &&  echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests
RUN rm -rf /var/lib/apt/lists/*
RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list
RUN mkdir -p /run/systemd
   &&  echo 'docker' > /run/systemd/container
CMD ["/bin/bash"]

1
La soluzione più semplice. Grazie!
user3576508

Ciò non aggiunge una barra rovesciata finale quando interrompe le istruzioni RUN su più righe. Ho aggiunto la mia risposta ispirata da questo.
Scott Centoni,

tac non è disponibile su Mac, quindi puoi scegliere Awk come di seguito: | awk '{stampa NR, $ 0}' | ordina -nr | sed 's / ^ [0-9] * //' |
phulei

11

A questo punto non è possibile (a meno che l'autore dell'immagine non abbia esplicitamente incluso il Dockerfile).

Tuttavia, è sicuramente qualcosa di utile! Ci sono due cose che aiuteranno a ottenere questa funzione.

  1. Build affidabili (dettagliati in questa discussione docker-dev
  2. Metadati più dettagliati nelle immagini successive prodotte dal processo di compilazione. A lungo termine, i metadati dovrebbero indicare quale comando build ha prodotto l'immagine, il che significa che sarà possibile ricostruire il file Docker da una sequenza di immagini.

8

Aggiorna dicembre 2018 alla risposta di BMW

docker pull chenzj/dfimage
alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm chenzj/dfimage"
dfimage IMAGE_ID > Dockerfile

6

Questo deriva dalla risposta di @ fallino, con alcune regolazioni e semplificazioni utilizzando l'opzione del formato di output per la cronologia docker . Poiché macOS e Gnu / Linux hanno diverse utilità da riga di comando, per Mac è necessaria una versione diversa. Se hai solo bisogno dell'uno o dell'altro, puoi semplicemente usare quelle linee.

#!/bin/bash
case "$OSTYPE" in
    linux*)
        docker history --no-trunc --format "{{.CreatedBy}}" $1 | # extract information from layers
        tac                                                    | # reverse the file
        sed 's,^\(|3.*\)\?/bin/\(ba\)\?sh -c,RUN,'             | # change /bin/(ba)?sh calls to RUN
        sed 's,^RUN #(nop) *,,'                                | # remove RUN #(nop) calls for ENV,LABEL...
        sed 's,  *&&  *, \\\n \&\& ,g'                           # pretty print multi command lines following Docker best practices
    ;;
    darwin*)
        docker history --no-trunc --format "{{.CreatedBy}}" $1 | # extract information from layers
        tail -r                                                | # reverse the file
        sed -E 's,^(\|3.*)?/bin/(ba)?sh -c,RUN,'               | # change /bin/(ba)?sh calls to RUN
        sed 's,^RUN #(nop) *,,'                                | # remove RUN #(nop) calls for ENV,LABEL...
        sed $'s,  *&&  *, \\\ \\\n \&\& ,g'                      # pretty print multi command lines following Docker best practices
    ;;
    *)
        echo "unknown OSTYPE: $OSTYPE"
    ;;
esac

5

docker pull chenzj/dfimage


alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm chenzj/dfimage"

dfimage image_id

di seguito è riportato il comando dfimage: -

$ dfimage 0f1947a021ce

Nodo FROM: 8 WORKDIR / usr / src / app

File COPIA: e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c in ./

RUN / bin / sh -c npm install

COPY dir: a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a6974a274b2184a in.

ESPOSI 8080

CMD ["npm" "start"]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.