จะสร้าง Dockerfile จากภาพได้อย่างไร?


241

เป็นไปได้หรือไม่ที่จะสร้าง Dockerfile จากภาพ? ฉันต้องการทราบด้วยสองเหตุผล:

  1. ฉันสามารถดาวน์โหลดภาพจากพื้นที่เก็บข้อมูล แต่ต้องการดูสูตรที่สร้าง

  2. ฉันชอบความคิดในการบันทึกสแนปชอต แต่เมื่อฉันทำมันจะเป็นการดีที่มีรูปแบบที่มีโครงสร้างเพื่อตรวจสอบสิ่งที่ทำ


คุณสามารถใช้ Portainer.io portainer.ioเป็นแอปพลิเคชันเว็บที่ทำงานภายในคอนเทนเนอร์นักเทียบท่าที่ใช้ในการจัดการทุกอย่างเกี่ยวกับคอนเทนเนอร์ของคุณ แม้แต่ภาพที่รับ
Vincent

คำตอบ:


98

จะสร้างหรือย้อนกลับ Dockerfile จากภาพได้อย่างไร?

คุณสามารถ.

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

มันจะดึง automaticlaly Dockerfileภาพนักเทียบท่าเป้าหมายและการส่งออก -sV=1.36ไม่จำเป็นต้องใช้พารามิเตอร์ทุกครั้ง

การอ้างอิง: https://hub.docker.com/repository/docker/alpine/dfimage

ด้านล่างเป็นคำตอบเก่า ๆ มันไม่ทำงานอีกต่อไป

$ 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
นี่คือวิธีนักเทียบท่าและควรทำเครื่องหมายเป็นคำตอบที่เลือก
kytwb

2
@ jenson ไม่แน่นอนเหมือนกันสามารถครอบคลุม 95% แต่ใช้ไม่ได้กับภาพที่แบน
BMW

5
@BMW คุณช่วยแก้ไขปัญหานี้ด้วยการเรียกใช้รูปภาพจากตัวอย่างของคุณได้ไหม? /usr/lib/ruby/gems/2.2.0/gems/excon-0.45.4/lib/excon/unix_socket.rb:14:in `connect_nonblock ': การเชื่อมต่อถูกปฏิเสธ - เชื่อมต่อ (2) สำหรับ / var / run / docker .sock (Errno :: ECONNREFUSED) (Excon :: ข้อผิดพลาด :: SocketError)
ยาว

8
Centurylink / dockerfile-from-image ไม่ทำงานกับ docker รุ่นใหม่ อันนี้ใช้ได้สำหรับฉัน: hub.docker.com/r/chenzj/dfimage
aleung

6
imagelayers.io ดูเหมือนว่าจะถูกทำลาย ไม่พบรูปภาพใด ๆ รวมถึงภาพตัวอย่าง
Robert Lugg

165

เพื่อให้เข้าใจถึงการสร้างอิมเมจของนักเทียบท่าใช้ docker history --no-truncคำสั่ง

คุณสามารถสร้างไฟล์นักเทียบท่าจากภาพ แต่มันจะไม่มีทุกสิ่งที่คุณต้องการที่จะเข้าใจอย่างสมบูรณ์ว่าภาพนั้นถูกสร้างขึ้นอย่างไร สิ่งที่คุณสามารถแยกได้คือ MAINTAINER, ENV, EXPOSE, VOLUME, WORKDIR, ENTRYPOINT, CMD และ ONBUILD บางส่วนของ dockerfile

สคริปต์ต่อไปนี้ควรใช้กับคุณ:

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

ฉันใช้สิ่งนี้เป็นส่วนหนึ่งของสคริปต์เพื่อสร้างคอนเทนเนอร์ที่ทำงานใหม่เป็นภาพ: https://github.com/docbill/docker-scripts/blob/master/docker-rebase

Dockerfile มีประโยชน์ส่วนใหญ่หากคุณต้องการที่จะสามารถบรรจุภาพ

สิ่งที่ควรคำนึงถึงคืออิมเมจนักเทียบท่านั้นสามารถสำรองทาร์ของเครื่องจริงหรือเสมือนได้ ฉันทำภาพนักเทียบท่าหลายรูปด้วยวิธีนี้ แม้แต่ประวัติการสร้างแสดงให้ฉันเห็นการนำเข้าไฟล์ tar ขนาดใหญ่เป็นขั้นตอนแรกในการสร้างภาพ ...


1
มันทำให้ฉัน: json: ไม่สามารถ unmarshal array เป็นค่า Go type typeContainerJSON
Mohsen

คุณสามารถอธิบายความคิดเห็นล่าสุดโดยละเอียดยิ่งขึ้นได้ไหม? ทุกอย่างใน / เพิ่ง tar'ed เป็นปกติหรือไม่ หรือมีกรณีพิเศษหรือไม่?
Robert Lugg

ฉันคิดว่านี่เป็นคำตอบ 6yo แต่ฉันเข้าใจแล้วError response from daemon: page not found
João Ciocca

53

ฉันพลาดคำสั่งจริงในคำตอบที่ยอมรับดังนั้นฉันก็เลยเห็นอีกครั้งในย่อหน้าของมันเองเพื่อดูว่ามีคนมากมายแค่ไหนในตัวฉัน

$ docker history --no-trunc <IMAGE_ID>

1
ดังนั้นทำไมเราต้องub.docker.com/r/chenzj/dfimage? มันเป็นคำตอบที่ใหม่กว่า
lucid_dreamer

3
ฉันเดาเพราะdocker historyพิมพ์บรรทัด Dockerfile ในลำดับย้อนกลับและมันลดRUNคำแนะนำ (คุณได้รับเพียงคำสั่งเองไม่ใช่RUNkeyworkd อยู่ข้างหน้า) และสิ่งอื่น ๆ ดังนั้นคุณต้องแก้ไขด้วยตนเองเพื่อไปที่ Dockerfile ที่ buildable ได้ เครื่องมืออื่นอาจทำการแก้ไขนี้โดยอัตโนมัติสำหรับคุณ (ฉันไม่ได้ลองดังนั้นฉันไม่รู้)
user7610

@ user7610 คำสั่งของคุณเพียงแสดงประวัติของภาพที่ดึงออกมาจากฮับ ฉันจะดูคำสั่งของฉันในภาพนักเทียบท่าได้อย่างไร?
BarzanHayati

@BarzanHayati คุณช่วยถามเป็นคำถามใหม่และเชื่อมโยงได้ที่นี่? จงถามเฉพาะเจาะจงมาก ๆ แสดงคำสั่งเพื่อเริ่มอิมเมจจากนั้นออกคำสั่งบางอย่างที่คุณต้องการดูในภายหลังเป็นตัวอย่างจากนั้นหยุดคอนเทนเนอร์ (ถ้านั่นคือสิ่งที่คุณทำในความเป็นจริง) แล้วถามวิธีการดึงคำสั่งที่ออก ขอบคุณ
user7610

1
@ user7610 ฉันสามารถถามได้ แต่ทันทีที่ฉันถามฉันจะต้องลบเพราะผู้ใช้รายอื่นให้คะแนนลบสำหรับคำถามซ้ำ ๆ
BarzanHayati

35

วิธีทุบตี:

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

คำอธิบายทีละขั้นตอน:

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)

ตัวอย่าง:

 ~  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
ทางออกที่ตรงไปตรงมาที่สุด ขอบคุณ!
user3576508

สิ่งนี้จะไม่เพิ่มเครื่องหมายแบ็กสแลชต่อท้ายเมื่อเลิกงบ RUN หลายชุด ฉันได้เพิ่มคำตอบของตัวเองแรงบันดาลใจจากสิ่งนี้
Scott Centoni

tac ไม่พร้อมใช้งานบน mac ดังนั้นคุณสามารถไปที่ awk เช่นด้านล่าง: | awk '{พิมพ์ NR, $ 0}' | เรียงลำดับ -nr | sed 's / ^ [0-9] * //' |
phulei

11

ไม่สามารถทำได้ในตอนนี้ (เว้นแต่ว่าผู้แต่งรูปภาพจะรวม Dockerfile ไว้อย่างชัดเจน)

อย่างไรก็ตามมันมีประโยชน์อย่างแน่นอน! มีสองสิ่งที่จะช่วยให้ได้รับคุณลักษณะนี้

  1. การสร้างที่เชื่อถือได้ (รายละเอียดในการสนทนานักเทียบท่า -ev
  2. ข้อมูลเมตาที่มีรายละเอียดเพิ่มเติมในภาพต่อเนื่องที่สร้างขึ้นโดยกระบวนการสร้าง ในระยะยาวเมตาดาต้าควรระบุว่าคำสั่ง build ใดที่สร้างอิมเมจซึ่งหมายความว่ามันจะเป็นไปได้ที่จะสร้าง Dockerfile ขึ้นใหม่จากลำดับของอิมเมจ

8

อัปเดตธันวาคม 2561 เป็นคำตอบของ 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

นี้ได้มาจากคำตอบของ @ fallino มีการปรับและ simplifications โดยใช้ตัวเลือกรูปแบบการออกสำหรับประวัตินักเทียบท่า เนื่องจาก macOS และ Gnu / Linux มียูทิลิตีบรรทัดคำสั่งต่างกันจึงจำเป็นต้องใช้เวอร์ชันอื่น หากคุณต้องการเพียงอย่างเดียวคุณสามารถใช้บรรทัดเหล่านั้นได้

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

ด้านล่างคือ ouput ของคำสั่ง dfimage: -

$ dfimage 0f1947a021ce

จากโหนด: 8 WORKDIR / usr / src / app

ไฟล์สำเนา: e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c ใน. /

ติดตั้ง RUN / bin / sh -c npm

สำเนา COPY: a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a69a6974a6974a6974a274b2184a ใน

เปิดเผย 8080

CMD ["npm" "start"]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.