이미지에서 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

대상 도커 이미지를 자동으로 가져 와서 내 보냅니다 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:`connect_nonblock '에서 : 연결 거부-/ var / run / docker의 경우 connect (2) .sock (errno를 :: ECONNREFUSED) (Excon :: 오류 :: 소켓 오류)

8
Centurylink / dockerfile-from-image는 새 버전 도커에서 작동하지 않습니다. 이것은 나를 위해 작동합니다 : hub.docker.com/r/chenzj/dfimage
aleung

6
imagelayers.io가 손상된 것 같습니다. 그것은 그것의 데모 포함한 모든 이미지를 찾을 수 없습니다
로버트 Lugg에게

165

도커 이미지가 작성된 방법을 이해하려면 docker history --no-trunc명령을 사용하십시오 .

이미지에서 도커 파일을 만들 수는 있지만 이미지 생성 방법을 완전히 이해하려는 모든 것은 포함하지 않습니다. 추출 할 수있는 것은 도커 파일의 MAINTAINER, ENV, EXPOSE, VOLUME, WORKDIR, ENTRYPOINT, CMD 및 ONBUILD 부분입니다.

다음 스크립트가 적합합니다.

#!/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 백업 일 수 있다는 것입니다. 이 방법으로 여러 도커 이미지를 만들었습니다. 빌드 기록조차도 이미지를 만드는 첫 번째 단계로 거대한 tar 파일을 가져 오는 것을 보여줍니다 ...


1
json : 배열 유형을 Go 유형의 Go 값으로 정렬 해제 할 수 없습니다. ContainerJSON
Mohsen

마지막 코멘트를 더 자세히 설명 할 수 있습니까? 모든 것이 정상적으로 작동합니까? 아니면 특별한 경우가 있습니까?
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지침 (당신은 단지 명령 자체가 아닌 얻을 RUN및 기타 물건 그것의 앞에 keyworkd)을 편집해야합니다 있도록 수동으로 빌드 할 Dockerfile에 도착. 다른 도구는이 편집을 자동으로 수행 할 수 있습니다 (사용하지 않았으므로 모르겠습니다)
user7610

@ user7610 명령은 허브에서 가져온 이미지의 기록을 보여줍니다. 도커 이미지에서 내 명령을 어떻게 볼 수 있습니까?
BarzanHayati

@BarzanHayati 새로운 질문으로 여기에 링크 해 주시겠습니까? 요청할 때 매우 구체적으로 설명하십시오. 명령을 표시하여 이미지를 시작한 다음, 나중에 보려고하는 일부 명령을 실행 한 다음 컨테이너를 중지 (실제로 실제로 수행하는 경우) 한 다음 발행 된 명령을 검색하는 방법을 요청하십시오. 감사.
user7610

1
@ user7610 요청할 수는 있지만 다른 사용자가 반복되는 질문에 대해 마이너스 포인트를 주므로 요청하면 바로 삭제해야합니다.
BarzanHayati

35

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

단계별 설명 :

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 2018

mac에서는 tac을 사용할 수 없으므로 다음과 같이 awk로 이동할 수 있습니다. | awk '{print NR, $ 0}'| 정렬 -nr | sed 's / ^ [0-9] * //'|
phulei

11

이 시점에서는 불가능합니다 (이미지 작성자가 Dockerfile을 명시 적으로 포함하지 않은 경우).

그러나 그것은 확실히 유용한 것입니다! 이 기능을 얻는 데 도움이되는 두 가지가 있습니다.

  1. 신뢰할 수있는 빌드 ( 이 docker-dev 토론 에서 자세히 설명 됨)
  2. 빌드 프로세스에서 생성 된 연속 이미지의보다 자세한 메타 데이터. 장기적으로 메타 데이터는 이미지를 생성 한 빌드 명령을 나타내야합니다. 즉, 일련의 이미지에서 Dockerfile을 재구성 할 수 있습니다.

8

BMW의 답변으로 2018 년 12 월 업데이트

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의 답변에서 파생되었으며 docker history에 출력 형식 옵션을 사용하여 약간의 조정과 단순화를했습니다 . macOS와 Gnu / Linux에는 다른 명령 줄 유틸리티가 있으므로 Mac에는 다른 버전이 필요합니다. 둘 중 하나만 필요한 경우 해당 줄만 사용할 수 있습니다.

#!/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 명령의 출력입니다.

dfimage 0f1947a021ce

FROM 노드 : 8 WORKDIR / usr / src / app

복사 파일 : ./의 e76d2e84545dedbe901b7b7b0c8d2c9733baa07cc821054efec48f623e29218c

RUN / bin / sh -c npm 설치

복사 디렉터리 : a89a4894689a38cbf3895fdc0870878272bb9e09268149a87a6974a274b2184a in.

박람회 8080

CMD [ "npm" "시작"]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.