Bagaimana cara menghasilkan Dockerfile dari suatu gambar?


241

Apakah mungkin membuat Dockerfile dari sebuah gambar? Saya ingin tahu karena dua alasan:

  1. Saya dapat mengunduh gambar dari repositori tetapi ingin melihat resep yang dihasilkannya.

  2. Saya menyukai gagasan menyimpan foto, tetapi begitu saya selesai, akan lebih baik jika memiliki format terstruktur untuk meninjau apa yang telah dilakukan.


Anda dapat menggunakan Portainer.io portainer.io Ini adalah aplikasi web yang berjalan di dalam wadah buruh pelabuhan yang digunakan untuk mengelola semua (hampir) hal-hal tentang wadah Anda. Bahkan gambar pun meresap.
Vincent

Jawaban:


98

Bagaimana cara menghasilkan atau membalikkan Dockerfile dari gambar?

Kamu bisa.

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

Ini akan menarik gambar buruh pelabuhan target otomatis dan ekspor Dockerfile. Parameter -sV=1.36tidak selalu diperlukan.

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

di bawah ini adalah jawaban lama, tidak berfungsi lagi.

$ 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
Ini adalah cara Docker dan harus ditandai sebagai jawaban yang dipilih.
kytwb

2
@ jenson itu tidak persis sama, dapat mencakup 95%. Tetapi tidak bekerja dengan gambar terjepit.
BMW

5
@BMW Bisakah Anda membantu menyelesaikan masalah ini dengan menjalankan gambar dari contoh Anda? /usr/lib/ruby/gems/2.2.0/gems/excon-0.45.4/lib/excon/unix_socket.rb:14:in `connect_nonblock ': Sambungan ditolak - koneksi (2) untuk / var / run / docker .sock (Errno :: ECONNREFUSED) (Excon :: Kesalahan :: SocketError)
panjang

8
centurylink / dockerfile-from-image tidak berfungsi dengan buruh pelabuhan versi baru. Yang ini berfungsi untuk saya: hub.docker.com/r/chenzj/dfimage
aleung

6
imagelayers.io tampaknya rusak. Tidak dapat menemukan gambar apa pun termasuk yang demo
Robert Lugg

165

Untuk memahami bagaimana gambar buruh pelabuhan dibangun, gunakan docker history --no-truncperintah.

Anda dapat membuat file buruh pelabuhan dari suatu gambar, tetapi itu tidak akan memuat semua yang Anda ingin pahami sepenuhnya bagaimana gambar itu dihasilkan. Apa yang bisa Anda ekstrak adalah bagian PEMELIHARAAN, ENV, EXPOSE, VOLUME, WORKDIR, ENTRYPOINT, CMD, dan ONBUILD pada dockerfile.

Script berikut ini bisa digunakan untuk Anda:

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

Saya menggunakan ini sebagai bagian dari skrip untuk membangun kembali wadah yang sedang berjalan sebagai gambar: https://github.com/docbill/docker-scripts/blob/master/docker-rebase

Dockerfile terutama berguna jika Anda ingin dapat mengemas ulang suatu gambar.

Yang perlu diingat, adalah gambar buruh pelabuhan sebenarnya hanya bisa menjadi cadangan tar dari mesin nyata atau virtual. Saya telah membuat beberapa gambar buruh pelabuhan dengan cara ini. Bahkan riwayat pembuatan menunjukkan saya mengimpor file tar besar sebagai langkah pertama dalam membuat gambar ...


1
Itu membuat saya: json: tidak dapat menghapus array ke nilai Go dari jenis type.ContainerJSON
Mohsen

Bisakah Anda menggambarkan komentar terakhir Anda dengan lebih detail? Apakah semuanya dalam / hanya tar sebagai normal? Atau ada kasus khusus?
Robert Lugg

Saya rasa ini adalah jawaban 6yo, tapi saya dapatError response from daemon: page not found
João Ciocca

53

Saya entah bagaimana benar-benar kehilangan perintah yang sebenarnya dalam jawaban yang diterima, jadi ini dia lagi, sedikit lebih terlihat dalam paragrafnya sendiri, untuk melihat berapa banyak orang seperti saya

$ docker history --no-trunc <IMAGE_ID>

1
Jadi mengapa kita perlu ub.docker.com/r/chenzj/dfimage? Itu bahkan jawaban yang lebih baru.
lucid_dreamer

3
Saya kira karena docker historymencetak garis Dockerfile dalam urutan terbalik dan itu menjatuhkan RUNinstruksi (Anda hanya mendapatkan perintah itu sendiri, bukan RUNkeyworkd di depannya) dan hal-hal lain, jadi Anda perlu mengeditnya secara manual untuk sampai ke Dockerfile yang dapat dibangun. Alat lain itu dapat melakukan pengeditan ini secara otomatis untuk Anda (saya tidak mencobanya, jadi saya tidak tahu.)
user7610

@ user7610 perintah Anda cukup tampilkan riwayat gambar yang ditarik dari hub. Bagaimana saya bisa melihat perintah saya pada gambar buruh pelabuhan?
BarzanHayati

@BarzanHayati Bisakah Anda menanyakannya sebagai pertanyaan baru dan menautkannya di sini? Sangat spesifik saat bertanya. Perlihatkan perintah untuk memulai gambar, kemudian keluarkan beberapa perintah yang ingin Anda lihat nanti, sebagai contoh, kemudian hentikan wadah (jika itu yang sebenarnya Anda lakukan dalam kenyataan), dan kemudian tanyakan bagaimana cara mengambil perintah yang dikeluarkan. Terima kasih.
user7610

1
@ user7610 Saya bisa menanyakannya, tetapi begitu saya menanyakannya, saya harus menghapusnya karena pengguna lain memberi saya poin minus untuk pertanyaan berulang.
BarzanHayati

35

Solusi 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

Penjelasan langkah demi langkah:

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)

Contoh:

 ~  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
Solusi paling mudah. Terima kasih!
user3576508

Ini tidak menambahkan garis miring terbalik ketika memecah pernyataan RUN multiline. Saya telah menambahkan jawaban saya sendiri yang terinspirasi oleh ini.
Scott Centoni

tac tidak tersedia di mac, jadi Anda bisa mencari awk seperti di bawah ini: | awk '{print NR, $ 0}' | sort -nr | sed 's / ^ [0-9] * //' |
phulei

11

Saat ini tidak memungkinkan (kecuali pembuat gambar secara eksplisit menyertakan Dockerfile).

Namun, itu pasti sesuatu yang bermanfaat! Ada dua hal yang akan membantu untuk mendapatkan fitur ini.

  1. Bangunan tepercaya (dirinci dalam diskusi buruh pelabuhan ini
  2. Metadata yang lebih rinci dalam gambar berurutan yang dihasilkan oleh proses build. Dalam jangka panjang, metadata harus menunjukkan perintah build mana yang menghasilkan gambar, yang berarti akan mungkin merekonstruksi Dockerfile dari urutan gambar.

8

Perbarui Des 2018 untuk jawaban 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

Ini berasal dari jawaban @ fallino, dengan beberapa penyesuaian dan penyederhanaan dengan menggunakan opsi format output untuk riwayat buruh pelabuhan . Karena macOS dan Gnu / Linux memiliki utilitas baris perintah yang berbeda, versi yang berbeda diperlukan untuk Mac. Jika Anda hanya membutuhkan satu atau yang lain, Anda bisa menggunakan garis itu.

#!/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 bawah ini adalah ouput dari perintah dfimage: -

$ dfimage 0f1947a021ce

DARI simpul: 8 WORKDIR / usr / src / app

File COPY: e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c di ./

RUN / bin / sh-c npm install

Dir COPY: a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a6974a274b2184a di.

EXPOSE 8080

CMD ["npm" "start"]

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.