Подтвердить что ты не робот

Как я могу проверить файловую систему неудачной "сборки докеров"?

Я пытаюсь создать новый образ Docker для нашего процесса разработки, используя cpanm, чтобы установить кучу модулей Perl в качестве базового образа для различных проектов.

При разработке файла Docker cpanm возвращает код сбоя, потому что некоторые из модулей не устанавливаются чистым образом.

Я уверен, мне нужно, чтобы apt установил еще несколько вещей.

Мой вопрос в том, где я могу найти каталог /.cpanm/work, указанный в выводе, чтобы проверить журналы? В общем случае, как я могу проверить файловую систему сбойной команды docker build?

Morning edit После того, как я купил пулю и запустил find, я обнаружил

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

Является ли это надежным, или мне лучше построить "голый" контейнер и запустить материал вручную, пока у меня не будет все, что мне нужно?

4b9b3361

Ответ 1

Каждый раз, когда докер успешно выполняет команду RUN из файла Docker, новый слой в файловой системе изображения фиксируется. Удобно использовать эти слои в качестве изображений для запуска нового контейнера.

Возьмите следующий файл Docker:

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:

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

Однажды в контейнере:

  • попробуйте выполнить команду, которая не удалась, и воспроизведите проблему.
  • затем исправить команду и протестировать ее
  • наконец обновите файл Docker с помощью фиксированной команды

Если вам действительно нужно поэкспериментировать в фактическом слое, который вышел из строя, а не работать с последнего рабочего слоя, см. ответ Drew ниже.

Ответ 2

Верхний ответ работает в том случае, если вы хотите проверить состояние непосредственно перед неудачной командой.

Однако, вопрос задает вопрос о том, как проверить состояние несостоявшегося контейнера. В моей ситуации неудавшаяся команда представляет собой сборку, которая занимает несколько часов, поэтому перематывание перед неудачной командой и ее повторное выполнение занимает много времени и не очень полезно.

Решение здесь заключается в том, чтобы найти контейнер, который не удалось:

$ 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]

Теперь вы на самом деле смотрите состояние сборки в то время, когда оно потерпело неудачу, а не в то время перед запуском команды, вызвавшей сбой.

Ответ 3

Docker кэширует состояние всей файловой системы после каждой успешной строки RUN.

Зная, что:

  • чтобы проверить последнее состояние перед вашей неудачной командой RUN, прокомментировать это в файле Docker (а также любые и все последующие команды RUN), а затем снова запустить docker build и docker run.
  • чтобы проверить состояние после команды RUN, просто добавьте || true к ней, чтобы заставить ее преуспеть; затем выполните, как указано выше (сохраните все и все последующие команды RUN, запустите docker build и docker run)

Tada, не нужно возиться с внутренними компонентами Docker или идентификаторами слоев, а в качестве бонуса Docker автоматически минимизирует объем работы, который необходимо переделать.

Ответ 4

Что бы я сделал, так это прокомментировать Dockerfile ниже и включить строку нарушения. Затем вы можете запустить контейнер и запустить команды докера вручную, и посмотрите на журналы обычным способом. Например. если файл 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...

Ответ 5

Отладка отказов шага сборки действительно очень раздражает.

Лучшее решение, которое я нашел, - убедиться, что каждый шаг, выполняющий реальную работу, преуспевает, и добавление проверки после неудачных попыток. Таким образом вы получаете фиксированный уровень, который содержит выходы неудавшегося шага, которые вы можете проверить.

A Dockerfile с примером после строки # Run DB2 silent installer:

#
# 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 <[email protected]>

# 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