[debugging] 실패한`docker build`의 파일 시스템을 어떻게 검사 할 수 있습니까?

cpanm다양한 프로젝트의 기본 이미지로 Perl 모듈을 설치하는 데 사용하여 개발 프로세스를 위해 새로운 Docker 이미지를 작성하려고합니다 .

Dockerfile을 개발하는 동안 cpanm일부 모듈이 제대로 설치되지 않았기 때문에 실패 코드를 리턴합니다.

apt좀 더 설치 해야한다고 확신합니다 .

내 질문은 /.cpanm/work로그를 검사하기 위해 출력에서 ​​인용 된 디렉토리를 어디에서 찾을 수 있습니까? 일반적인 경우 실패한 docker build명령 의 파일 시스템을 어떻게 검사 할 수 있습니까?

아침 편집 글 머리 기호를 물고 실행 한 후 find발견

/var/lib/docker/aufs/diff/3afa404e[...]/.cpanm

이것이 신뢰할 수 있습니까, 아니면 “베어”컨테이너를 빌드하고 필요한 것을 모두 얻을 때까지 수동으로 실행하는 것이 더 낫습니까?



답변

docker RUN가 Dockerfile에서 명령을 성공적으로 실행할 때마다 이미지 파일 시스템의 새 레이어 가 커밋됩니다. 편리하게 해당 레이어 ID를 이미지로 사용하여 새 컨테이너를 시작할 수 있습니다.

다음 Dockerfile을 가져옵니다.

FROM busybox
RUN echo 'foo' > /tmp/foo.txt
RUN echo 'bar' >> /tmp/foo.txt

그리고 그것을 빌드하십시오 :

$ docker build -t so-2622957 .
Sending build context to Docker daemon 47.62 kB
Step 1/3 : FROM busybox
 ---> 00f017a8c2a6
Step 2/3 : RUN echo 'foo' > /tmp/foo.txt
 ---> Running in 4dbd01ebf27f
 ---> 044e1532c690
Removing intermediate container 4dbd01ebf27f
Step 3/3 : RUN echo 'bar' >> /tmp/foo.txt
 ---> Running in 74d81cb9d2b1
 ---> 5bd8172529c1
Removing intermediate container 74d81cb9d2b1
Successfully built 5bd8172529c1

당신은 지금부터 새 컨테이너를 시작할 수 있습니다 00f017a8c2a6, 044e1532c690그리고 5bd8172529c1:

$ docker run --rm 00f017a8c2a6 cat /tmp/foo.txt
cat: /tmp/foo.txt: No such file or directory

$ docker run --rm 044e1532c690 cat /tmp/foo.txt
foo

$ docker run --rm 5bd8172529c1 cat /tmp/foo.txt
foo
bar

물론 파일 시스템을 탐색하고 명령을 시도하기 위해 쉘을 시작하려고 할 수 있습니다.

$ docker run --rm -it 044e1532c690 sh
/ # ls -l /tmp
total 4
-rw-r--r--    1 root     root             4 Mar  9 19:09 foo.txt
/ # cat /tmp/foo.txt
foo

Dockerfile 명령 중 하나가 실패하면 이전 계층ID 를 찾아 해당 ID에서 작성된 컨테이너에서 쉘을 실행해야합니다.

docker run --rm -it <id_last_working_layer> bash -il

컨테이너에 들어가면 :

  • 실패한 명령을 시도하고 문제를 재현하십시오.
  • 그런 다음 명령을 수정하고 테스트하십시오.
  • 마지막으로 고정 명령으로 Dockerfile을 업데이트하십시오.

마지막 작업 계층에서 작업하는 대신 실패한 실제 계층에서 실제로 실험해야하는 경우 Drew의 답변을 참조하십시오 .


답변

최상위 답변은 실패한 명령 직전에 상태를 검사하려는 경우에 작동합니다.

그러나 질문은 실패한 컨테이너 자체의 상태를 검사하는 방법을 묻습니다. 내 상황에서 실패한 명령은 몇 시간이 걸리는 빌드이므로 실패한 명령 전에 되감기하고 다시 실행하는 데 시간이 오래 걸리고별로 도움이되지 않습니다.

여기서 해결책은 실패한 컨테이너를 찾는 것입니다.

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS               NAMES
6934ada98de6        42e0228751b3        "/bin/sh -c './utils/"   24 minutes ago      Exited (1) About a minute ago                       sleepy_bell

이미지로 커밋 :

$ docker commit 6934ada98de6
sha256:7015687976a478e0e94b60fa496d319cdf4ec847bcd612aecf869a72336e6b83

그런 다음 이미지를 실행하십시오 (필요한 경우 bash 실행).

$ docker run -it 7015687976a4 [bash -il]

이제 실제로는 실패를 일으킨 명령을 실행하기 전이 아닌 실패한 시점의 빌드 상태를 실제로보고 있습니다.


답변

Docker 각 성공적인 RUN라인 후에 전체 파일 시스템 상태를 캐시합니다 .

그것을 아는 것은:

  • 당신의 실패하기 전에 최신 상태 검사 RUN명령을의 Dockerfile (뿐만 아니라 이후의 모든 그것을 주석 RUN, 다음 실행 명령) docker builddocker run다시.
  • 실패한 명령 상태를 검사하려면 RUN단순히 추가 || true하여 성공하도록하십시오. 그런 다음 위와 같이 진행하십시오 (모든 후속 RUN명령은 주석 처리하고 실행 docker build하고 docker run)

Tada는 Docker 내부 또는 레이어 ID를 망칠 필요가 없으며 보너스로 Docker는 다시 수행 해야하는 작업량을 자동으로 최소화합니다.


답변

빌드 단계 실패 디버깅은 실제로 매우 성가신 일입니다.

내가 찾은 최선의 해결책은 실제 작업을 수행하는 각 단계가 성공했는지 확인하고 실패한 단계 후에 검사를 추가하는 것입니다. 이렇게하면 검사 할 수없는 실패한 단계의 출력이 포함 된 커밋 된 레이어를 얻을 수 있습니다.

# Run DB2 silent installer행 뒤에 예제가있는 Dockerfile :

#
# DB2 10.5 Client Dockerfile (Part 1)
#
# Requires
#   - DB2 10.5 Client for 64bit Linux ibm_data_server_runtime_client_linuxx64_v10.5.tar.gz
#   - Response file for DB2 10.5 Client for 64bit Linux db2rtcl_nr.rsp
#
#
# Using Ubuntu 14.04 base image as the starting point.
FROM ubuntu:14.04

MAINTAINER David Carew <carew@us.ibm.com>

# DB2 prereqs (also installing sharutils package as we use the utility uuencode to generate password - all others are required for the DB2 Client)
RUN dpkg --add-architecture i386 && apt-get update && apt-get install -y sharutils binutils libstdc++6:i386 libpam0g:i386 && ln -s /lib/i386-linux-gnu/libpam.so.0 /lib/libpam.so.0
RUN apt-get install -y libxml2


# Create user db2clnt
# Generate strong random password and allow sudo to root w/o password
#
RUN  \
   adduser --quiet --disabled-password -shell /bin/bash -home /home/db2clnt --gecos "DB2 Client" db2clnt && \
   echo db2clnt:`dd if=/dev/urandom bs=16 count=1 2>/dev/null | uuencode -| head -n 2 | grep -v begin | cut -b 2-10` | chgpasswd && \
   adduser db2clnt sudo && \
   echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

# Install DB2
RUN mkdir /install
# Copy DB2 tarball - ADD command will expand it automatically
ADD v10.5fp9_linuxx64_rtcl.tar.gz /install/
# Copy response file
COPY  db2rtcl_nr.rsp /install/
# Run  DB2 silent installer
RUN mkdir /logs
RUN (/install/rtcl/db2setup -t /logs/trace -l /logs/log -u /install/db2rtcl_nr.rsp && touch /install/done) || /bin/true
RUN test -f /install/done || (echo ERROR-------; echo install failed, see files in container /logs directory of the last container layer; echo run docker run '<last image id>' /bin/cat /logs/trace; echo ----------)
RUN test -f /install/done

# Clean up unwanted files
RUN rm -fr /install/rtcl

# Login as db2clnt user
CMD su - db2clnt


답변

내가 할 일은 아래 Dockerfile을 주석 처리하고 문제를 일으키는 행을 포함시키는 것입니다. 그런 다음 컨테이너를 실행하고 수동으로 docker 명령을 실행하고 일반적인 방식으로 로그를 볼 수 있습니다. 예를 들어 Dockerfile이

RUN foo
RUN bar
RUN baz

그리고 내가 할 바에서 죽어 가고있다.

RUN foo
# RUN bar
# RUN baz

그때

$ docker build -t foo .
$ docker run -it foo bash
container# bar
...grep logs...


답변