Làm cách nào để tạo Dockerfile từ hình ảnh?


241

Có thể tạo Dockerfile từ hình ảnh không? Tôi muốn biết vì hai lý do:

  1. Tôi có thể tải hình ảnh từ kho lưu trữ nhưng muốn xem công thức tạo ra chúng.

  2. Tôi thích ý tưởng lưu ảnh chụp nhanh, nhưng một khi tôi đã hoàn thành, thật tuyệt khi có một định dạng có cấu trúc để xem lại những gì đã được thực hiện.


Bạn có thể sử dụng Portainer.io portainer.io Đó là một ứng dụng web chạy bên trong một container docker được sử dụng để quản lý tất cả (hầu hết) nội dung về các container của bạn. Ngay cả hình ảnh chiêu đãi.
Vincent

Câu trả lời:


98

Cập nhật:

Trích dẫn từ bình luận của @ aleung:

centurylink/dockerfile-from-imagekhông hoạt động với docker phiên bản mới. Cái này hoạt động với tôi:hub.docker.com/r/chenzj/dfimage

Làm cách nào để tạo Dockerfile từ hình ảnh?

Bạn có thể.

Cách thứ nhất

$ 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

Dưới đây là ví dụ để tạo Dockerfile từ một hình ảnh tồn tại selenium/node-firefox-debug

core@core-01 ~ $ docker pull centurylink/dockerfile-from-image
core@core-01 ~ $ alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm centurylink/dockerfile-from-image"
core@core-01 ~ $ dfimage selenium/node-firefox-debug
ADD file:b43bf069650bac07b66289f35bfdaf474b6b45cac843230a69391a3ee342a273 in /
RUN 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
RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list
CMD ["/bin/bash"]
MAINTAINER Selenium <selenium-developers@googlegroups.com>
RUN echo "deb http://archive.ubuntu.com/ubuntu trusty main universe\n" > /etc/apt/sources.list && echo "deb http://archive.ubuntu.com/ubuntu trusty-updates main universe\n" >> /etc/apt/sources.list
RUN apt-get update -qqy && apt-get -qqy --no-install-recommends install ca-certificates openjdk-7-jre-headless unzip wget && rm -rf /var/lib/apt/lists/* && sed -i 's/\/dev\/urandom/\/dev\/.\/urandom/' ./usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/java.security
RUN mkdir -p /opt/selenium && wget --no-verbose http://selenium-release.storage.googleapis.com/2.46/selenium-server-standalone-2.46.0.jar -O /opt/selenium/selenium-server-standalone.jar
RUN sudo useradd seluser --shell /bin/bash --create-home && sudo usermod -a -G sudo seluser && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers && echo 'seluser:secret' | chpasswd
MAINTAINER Selenium <selenium-developers@googlegroups.com>
ENV DEBIAN_FRONTEND=noninteractive
ENV DEBCONF_NONINTERACTIVE_SEEN=true
ENV TZ=US/Pacific
RUN echo "US/Pacific" | sudo tee /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata
RUN apt-get update -qqy && apt-get -qqy install xvfb && rm -rf /var/lib/apt/lists/*
COPY file:335d2f6f9bfe311d2b38034ceab3b2ae2a1e07b9b203b330cac9857d6e17c148 in /opt/bin/entry_point.sh
RUN chmod +x /opt/bin/entry_point.sh
ENV SCREEN_WIDTH=1360
ENV SCREEN_HEIGHT=1020
ENV SCREEN_DEPTH=24
ENV DISPLAY=:99.0
USER [seluser]
CMD ["/opt/bin/entry_point.sh"]
MAINTAINER Selenium <selenium-developers@googlegroups.com>
USER [root]
RUN apt-get update -qqy && apt-get -qqy --no-install-recommends install firefox && rm -rf /var/lib/apt/lists/*
COPY file:52a2a815e3bb6b85c5adfbceaabb5665b63f63ef0fb0e3f774624ee399415f84 in /opt/selenium/config.json
USER [seluser]
MAINTAINER Selenium <selenium-developers@googlegroups.com>
USER [root]
RUN apt-get update -qqy && apt-get -qqy install x11vnc && rm -rf /var/lib/apt/lists/* && mkdir -p ~/.vnc && x11vnc -storepasswd secret ~/.vnc/passwd
ENV LANGUAGE=en_US.UTF-8
ENV LANG=en_US.UTF-8
RUN locale-gen en_US.UTF-8 && dpkg-reconfigure --frontend noninteractive locales && apt-get update -qqy && apt-get -qqy --no-install-recommends install language-pack-en && rm -rf /var/lib/apt/lists/*
RUN apt-get update -qqy && apt-get -qqy --no-install-recommends install fonts-ipafont-gothic xfonts-100dpi xfonts-75dpi xfonts-cyrillic xfonts-scalable && rm -rf /var/lib/apt/lists/*
RUN apt-get update -qqy && apt-get -qqy install fluxbox && rm -rf /var/lib/apt/lists/*
COPY file:90e3a7f757c3df44d541b59234ad4ca996f799455eb8d426218619b244ebba68 in /opt/bin/entry_point.sh
RUN chmod +x /opt/bin/entry_point.sh
EXPOSE 5900/tcp

Cách thứ hai

Ở đây bạn không cần kéo hình ảnh về cục bộ và không cần chạy lệnh.

Sử dụng hình ảnh trên làm mẫu, bạn có thể nhận các lệnh Dockerfile thông qua url bên dưới:

https://imagelayers.io/?images=selenium%2Fnode-firefox-debug:latest

Đợi một lúc, sẽ có hai cửa sổ, cửa sổ lên liệt kê các lớp, cửa sổ xuống liệt kê lệnh trong Dockerfile

Ảnh chụp màn hình fantelayers.io

Định dạng URL là:

https://imagelayers.io/?images=<USER>%2F<IMAGE>:<TAG>

Trong thực tế, fantelayers.io được xây dựng bởi Centurylink


3
Đây là cách Docker và nên được đánh dấu là câu trả lời được chọn.
kytwb

2
@jenson nó không chính xác như nhau, có thể bao phủ 95%. Nhưng không hoạt động với hình ảnh bị đè bẹp.
BMW

5
@BMW Bạn có thể vui lòng giúp giải quyết vấn đề này khi chạy hình ảnh từ ví dụ của bạn không? /usr/lib/ruby/gems/2.2.0/gems/excon-0,45.4 / lib / excon / unix_socket.rb: 14: in ` .sock (Errno :: ECONNREFUSED) (Excon :: lỗi :: SocketError)
dài

8
centurylink / dockerfile-from-image không hoạt động với docker phiên bản mới. Cái này hoạt động với tôi: hub.docker.com/r/chenzj/dfimage
aleung 26/07/17

6
fantelayers.io dường như bị phá vỡ. Nó không thể tìm thấy bất kỳ hình ảnh nào kể cả những hình ảnh demo của nó
Robert Lugg

165

Để hiểu làm thế nào một hình ảnh docker được xây dựng, sử dụng docker history --no-trunclệnh.

Bạn có thể xây dựng một tệp docker từ một hình ảnh, nhưng nó sẽ không chứa mọi thứ bạn muốn để hiểu đầy đủ về cách hình ảnh được tạo ra. Một cách hợp lý những gì bạn có thể trích xuất là các phần MAINTAINER, ENV, EXPOSE, VOLUME, WORKDIR, ENTRYPOINT, CMD và ONBUILD của dockerfile.

Kịch bản sau sẽ phù hợp với bạn:

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

Tôi sử dụng điều này như một phần của tập lệnh để xây dựng lại các container đang chạy dưới dạng hình ảnh: https://github.com/docbill/docker-scripts/blob/master/docker-rebase

Dockerfile chủ yếu hữu ích nếu bạn muốn có thể đóng gói lại hình ảnh.

Điều cần lưu ý, là một hình ảnh docker thực sự có thể chỉ là bản sao lưu tar của một máy thật hoặc ảo. Tôi đã thực hiện một số hình ảnh docker theo cách này. Ngay cả lịch sử xây dựng cũng cho thấy tôi nhập một tệp tar lớn như bước đầu tiên trong việc tạo hình ảnh ...


1
Nó đưa tôi: json: không thể sắp xếp mảng thành giá trị Go của loại loại.ContainerJSON
Mohsen

Bạn có thể mô tả bình luận cuối cùng của bạn chi tiết hơn? Có phải mọi thứ trong / chỉ là bình thường? Hoặc có những trường hợp đặc biệt?
Robert Lugg

Tôi cho rằng đây là câu trả lời 6yo, nhưng tôi nhận đượcError response from daemon: page not found
João Ciocca

53

Tôi bằng cách nào đó đã hoàn toàn bỏ lỡ lệnh thực tế trong câu trả lời được chấp nhận, vì vậy đây là một lần nữa, hiển thị rõ hơn một chút trong đoạn văn của chính nó, để xem có bao nhiêu người giống tôi

$ docker history --no-trunc <IMAGE_ID>

1
Vậy tại sao chúng ta cần ub.docker.com/r/chenzj/dfimage? Nó thậm chí là một câu trả lời gần đây hơn.
lucid_dreamer

3
Tôi đoán bởi vì docker historyin các dòng Dockerfile theo thứ tự ngược lại và nó bỏ các RUNhướng dẫn (bạn chỉ nhận được lệnh chứ không phải RUNkeyworkd trước nó) và các công cụ khác, vì vậy bạn cần chỉnh sửa thủ công để có được Dockerfile có thể xây dựng được. Công cụ khác đó có thể tự động chỉnh sửa cho bạn (Tôi đã không thử nó, vì vậy tôi không biết.)
user7610

@ user7610 lệnh của bạn chỉ hiển thị lịch sử hình ảnh được kéo từ hub. Làm thế nào tôi có thể thấy các lệnh của tôi trên hình ảnh docker?
BarzanHayati

@BarzanHayati Bạn có thể hỏi nó như một câu hỏi mới và liên kết nó ở đây không? Hãy thật cụ thể khi hỏi. Hiển thị lệnh để bắt đầu hình ảnh, sau đó đưa ra một số lệnh bạn muốn xem sau đó, ví dụ, sau đó dừng container (nếu đó là những gì bạn thực sự làm trong thực tế), sau đó hỏi cách lấy lại các lệnh đã ban hành. Cảm ơn.
user7610

1
@ user7610 Tôi có thể hỏi nó, nhưng ngay khi tôi hỏi nó, tôi phải xóa nó vì những người dùng khác cho tôi điểm trừ cho câu hỏi lặp đi lặp lại.
BarzanHayati

34

Một giải pháp 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

Từng bước giải thích:

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)

Thí dụ:

 ~  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
Giải pháp đơn giản nhất. Cảm ơn bạn!
dùng3576508

Điều này không thêm dấu gạch chéo ngược khi nó phá vỡ các câu lệnh RUN đa dòng. Tôi đã thêm câu trả lời của riêng tôi lấy cảm hứng từ điều này.
Scott Centoni

tac không có sẵn trên mac, vì vậy bạn có thể dùng awk như dưới đây: | awk '{in NR, $ 0}' | sắp xếp -nr | sed 's / ^ [0-9] * //' |
phulei

11

Tại thời điểm này không thể thực hiện được (trừ khi tác giả của hình ảnh bao gồm rõ ràng Dockerfile).

Tuy nhiên, nó chắc chắn là một cái gì đó hữu ích! Có hai điều sẽ giúp có được tính năng này.

  1. Bản dựng đáng tin cậy (chi tiết trong cuộc thảo luận về docker-dev này
  2. Siêu dữ liệu chi tiết hơn trong các hình ảnh liên tiếp được tạo ra bởi quá trình xây dựng. Về lâu dài, siêu dữ liệu sẽ chỉ ra lệnh xây dựng nào tạo ra hình ảnh, điều đó có nghĩa là có thể tái cấu trúc Dockerfile từ một chuỗi các hình ảnh.

8

Cập nhật tháng 12 năm 2018 cho câu trả lời của 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

Điều này được bắt nguồn từ câu trả lời của @ fallino, với một số điều chỉnh và đơn giản hóa bằng cách sử dụng tùy chọn định dạng đầu ra cho lịch sử docker . Vì macOS và Gnu / Linux có các tiện ích dòng lệnh khác nhau, nên một phiên bản khác là cần thiết cho Mac. Nếu bạn chỉ cần cái này hoặc cái kia, bạn chỉ có thể sử dụng những dòng đó.

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

bên dưới là thông số của lệnh dfimage: -

$ dfimage 0f1947a021ce

TỪ nút: 8 WORKDIR / usr / src / app

Tệp COPY: e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c trong ./

Cài đặt RUN / bin / sh -c npm

COPY dir: a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a6974a274b2184a in.

HẾT 8080

CMD ["npm" "bắt đầu"]

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.