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.

pengguna1026169
sumber
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
BMW
sumber
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 ...

pengguna6856
sumber
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>
pengguna7610
sumber
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"]
fallino
sumber
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.
jpetazzo
sumber
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
AndrewD
sumber
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
Scott Centoni
sumber
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"]

pengguna128364
sumber