Bir görüntüden Docker dosyası nasıl oluşturulur?


241

Bir görüntüden Docker dosyası oluşturmak mümkün müdür? İki nedenden dolayı bilmek istiyorum:

  1. Depodan görüntü indirebilirim, ancak onları oluşturan tarifi görmek istiyorum.

  2. Anlık görüntüleri kaydetme fikrini seviyorum, ancak bir kez yapıldıktan sonra ne yapıldığını gözden geçirmek için yapılandırılmış bir biçime sahip olmak güzel olurdu.


Sen Portainer.io kullanabilirsiniz portainer.io bir liman işçisi kabın içine Çalıştırılan kapları hakkında tüm (neredeyse) şeyler yönetmek için kullanılan bir web uygulaması var. Hatta görüntüler resepsiyonu.
Vincent

Yanıtlar:


98

Bir görüntüden Docker dosyası nasıl oluşturulur veya tersine çevrilir?

Yapabilirsin.

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

Hedef docker görüntüsünü otomatik olarak çeker ve dışa aktarır Dockerfile. Parametre-sV=1.36 her zaman gerekli değildir.

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

aşağıda eski cevap, artık çalışmıyor.

$ 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
Bu Docker yoludur ve seçilen cevap olarak işaretlenmelidir.
kytwb

2
@ jenson tam olarak aynı değil,% 95'i kapsayabilir. Ancak ezilmiş görüntü ile çalışmaz.
BMW

5
@BMW Örneğinizdeki resmi çalıştırırken bu sorunu çözmenize yardımcı olabilir misiniz? /usr/lib/ruby/gems/2.2.0/gems/excon-0.45.4/lib/excon/unix_socket.rb:14:in `` connect_nonblock '': Bağlantı reddedildi - / var / run / docker için bağlan (2) .sock (Errno :: ECONNREFUSED) (excon :: Hatalar :: SocketError)
uzun

8
centurylink / dockerfile-from-image, yeni sürüm docker ile çalışmaz. Bu benim için çalışıyor: hub.docker.com/r/chenzj/dfimage
aleung

6
imagelayers.io bozuk görünüyor. Demo olanlar da dahil olmak üzere herhangi bir görüntü bulamıyor
Robert Lugg

165

Docker görüntüsünün nasıl oluşturulduğunu anlamak için docker history --no-trunckomutu kullanın.

Bir görüntüden bir liman işçisi dosyası oluşturabilirsiniz, ancak görüntünün nasıl oluşturulduğunu tam olarak anlamak istediğiniz her şeyi içermeyecektir. Makul olarak çıkarabileceğiniz şey, dockerfile'ın MAINTAINER, ENV, EXPOSE, VOLUME, WORKDIR, ENTRYPOINT, CMD ve ONBUILD parçalarıdır.

Aşağıdaki komut dosyasının sizin için çalışması gerekir:

#!/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"

Bu resim olarak çalışan kapsayıcılar yeniden oluşturmak için bir komut dosyası parçası olarak kullanın: https://github.com/docbill/docker-scripts/blob/master/docker-rebase

Dockerfile, esas olarak bir görüntüyü yeniden paketleyebilmek istiyorsanız kullanışlıdır.

Akılda tutulması gereken şey, bir docker görüntüsü aslında gerçek veya sanal bir makinenin tar yedeklemesi olabilir. Bu şekilde birkaç liman işçisi görüntü yaptım. Yapı geçmişi bile, görüntüyü oluşturmanın ilk adımı olarak büyük bir katran dosyasını içe aktarmamı gösteriyor ...


1
Beni alır: json: tür tiplerinin Go değerine dizilemez dizi.ContainerJSON
Mohsen

Son yorumunuzu daha ayrıntılı olarak açıklayabilir misiniz? Her şey normal gibi mi? Yoksa özel durumlar mı var?
Robert Lugg

Bu 6yo bir cevap olduğunu düşünüyorum, ama alıyorumError response from daemon: page not found
João Ciocca

53

Kabul edilen cevaptaki gerçek komutu bir şekilde kesinlikle kaçırdım, bu yüzden kaç kişi benim gibi olduğunu görmek için yine kendi paragrafında biraz daha görünür

$ docker history --no-trunc <IMAGE_ID>

1
Öyleyse neden ihtiyacımız var ub.docker.com/r/chenzj/dfimage? Hatta daha yeni bir cevap.
lucid_dreamer

3
Çünkü sanırım docker historybaskılar Dockerfile ters sırayla hatları ve damla RUNtalimatları (yalnızca komutu kendisi değil almak RUNve diğer şeyler önünde keyworkd) Düzenlemeye ihtiyaç yüzden elle buildable Dockerfile almak için. Bu diğer araç bu düzenlemeyi sizin için otomatik olarak yapabilir (denemedim, bu yüzden bilmiyorum.)
user7610

@ user7610 komutunuz sadece hub'dan çekilen resmin geçmişini gösterir. Docker görüntülerindeki komutlarımı nasıl görebilirim?
BarzanHayati

@BarzanHayati Yeni bir soru olarak sorabilir ve buraya bağlayabilir misiniz? Sorurken çok açık olun. Görüntüyü başlatma komutunu gösterin, sonra daha sonra görmek istediğiniz bazı komutları verin, örnek olarak, kapsayıcıyı durdurun (gerçekte yaptığınız buysa) ve verilen komutları nasıl alacağınızı sorun. Teşekkürler.
user7610

1
@ user7610 Ben sorabilirdim, ama sorduğumda, silmeliyim çünkü diğer kullanıcılar bana tekrarlanan soru için eksi puan veriyor.
BarzanHayati

35

Bir bash çözümü:

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

Adım adım açıklamalar:

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)

Misal:

 ~  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
En basit çözüm. Teşekkür ederim!
user3576508

Bu, çok satırlı RUN deyimlerini böldüğünde sondaki ters eğik çizgi eklemez. Bundan ilham alarak kendi cevabımı ekledim.
Scott Centoni

tac mac'ta mevcut değildir, bu nedenle aşağıdaki gibi awk için gidebilirsiniz: | awk '{baskı NR, $ 0}' | sıralama -nr | sed 's / ^ [0-9] * //' |
phulei

11

Bu noktada mümkün değildir (görüntünün yazarı Dockerfile'ı açıkça içermediği sürece).

Ancak, kesinlikle yararlı bir şey! Bu özelliğin elde edilmesine yardımcı olacak iki şey vardır.

  1. Güvenilen yapılar ( bu docker-dev tartışmasında ayrıntılı olarak açıklanmıştır)
  2. Derleme işlemi tarafından oluşturulan ardışık görüntülerde daha ayrıntılı meta veriler. Uzun vadede, meta veriler hangi build komutunun görüntüyü ürettiğini göstermelidir, bu da Dockerfile'ın bir dizi görüntüden yeniden yapılandırılmasının mümkün olacağı anlamına gelir.

8

Aralık 2018'i BMW'nin cevabına güncelleyin

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

Bu, docker geçmişi için çıktı biçimi seçeneğini kullanarak bazı ayarlamalar ve basitleştirmelerle @ fallino'nun yanıtından türetilmiştir . MacOS ve Gnu / Linux farklı komut satırı yardımcı programlarına sahip olduğundan, Mac için farklı bir sürüm gereklidir. Yalnızca birine veya diğerine ihtiyacınız varsa, bu satırları kullanabilirsiniz.

#!/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

dfimage komutunun çıktısı: -

$ dfimage 0f1947a021ce

Düğümden: 8 WORKDIR / usr / src / app

KOPYA dosyası: e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c in ./

RUN / bin / sh -c npm kurulumu

KOPYA dir: a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a6974a274b2184a.

EXPOSE 8080

CMD ["npm" "başlat"]

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.