2014-10-06 13 views
129

Tôi đang cố gắng xây dựng một hình ảnh Docker mới cho quá trình phát triển của chúng tôi, sử dụng cpanm để cài đặt một loạt mô-đun Perl làm hình ảnh cơ sở cho các dự án khác nhau.Làm cách nào tôi có thể kiểm tra hệ thống tệp của một `trình tạo docker không thành công`?

Trong khi phát triển Dockerfile, cpanm trả về mã lỗi vì một số mô-đun không cài đặt sạch.

Tôi khá chắc chắn mình cần phải nhận apt để cài đặt thêm một số thứ.

Câu hỏi của tôi là, tôi có thể tìm thấy thư mục /.cpanm/work được trích dẫn ở đầu ra để kiểm tra nhật ký? Trong trường hợp chung, làm cách nào tôi có thể kiểm tra hệ thống tệp của lệnh docker build không thành công?

Morning chỉnh sửa Sau khi cắn đạn và chạy một find tôi phát hiện ra

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

là đáng tin cậy này, hay tôi khấm khá hơn việc xây dựng một "trần" container và chạy thứ bằng tay cho đến khi tôi có tất cả những điều Tôi cần?

+0

về '/ var/lib/Docker/aufs/diff/3afa404e [...]/cpanm' những là bên trong của Docker và Tôi sẽ không gây rối với họ – Thomasleveil

Trả lời

173

Mỗi lần Docker thực hiện thành công một lệnh RUN từ một Dockerfile, một lớp mới trong hệ thống tập tin hình ảnh được cam kết. Thuận tiện bạn có thể sử dụng các lớp id như hình ảnh để bắt đầu một container mới.

Lấy Dockerfile sau:

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

và xây dựng nó:

$ 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 

Bạn bây giờ có thể bắt đầu một container mới từ 00f017a8c2a6, 044e1532c6905bd8172529c1:

$ 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 

tất nhiên bạn có thể muốn bắt đầu trình bao để kết thúc Lore hệ thống tập tin và cố gắng ra lệnh:

$ 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 

Khi một trong những lệnh Dockerfile thất bại, những gì bạn cần làm là để tìm kiếm các id của lớp trước và chạy một vỏ trong một container tạo ra từ id rằng:

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

Khi ở trong container:

  • thử lệnh rằng thất bại, và mô phỏng vấn đề
  • sau đó sửa chữa các lệnh và kiểm tra nó
  • cuối cùng cập nhật Dockerfile của bạn với lệnh cố định

Nếu bạn thực sự cần phải thử nghiệm trong lớp thực tế mà thất bại thay vì làm việc từ lớp làm việc cuối cùng, xem Drew's answer.

+0

Rất nhiều - trong này - sẽ không loại bỏ các thùng chứa sau khi tôi làm những việc này? – Altreus

+0

có. Không có các thùng chứa lưu giữ điểm chỉ nhằm gỡ lỗi Dockerfile của bạn khi bạn có thể tạo lại chúng theo ý muốn. – Thomasleveil

+0

OK điều này thực sự là siêu hữu ích, nhưng tôi có vấn đề nếu xây dựng vùng chứa không thành công, tôi không thể sử dụng thủ thuật này với mã băm của vùng chứa mà nó cho biết đang hoạt động. Không có hình ảnh nào được tạo nếu RUN không thành công . Tôi có thể đính kèm vào thùng chứa trung gian chưa bao giờ được làm sạch không? – Altreus

2

Điều tôi sẽ làm là nhận xét Dockerfile bên dưới và bao gồm dòng vi phạm. Sau đó, bạn có thể chạy các container và chạy các lệnh docker bằng tay, và nhìn vào các bản ghi theo cách thông thường. Ví dụ. nếu Dockerfile là

RUN foo 
RUN bar 
RUN baz 

và nó chết tại quầy bar tôi sẽ làm

RUN foo 
# RUN bar 
# RUN baz 

Sau đó

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

Đó là những gì tôi đã làm quá trước khi tìm chủ đề này. Có những cách tốt hơn mặc dù không yêu cầu chạy lại bản dựng. –

+0

@Aaron. Cảm ơn vì đã nhắc tôi về câu trả lời này. Tôi đã không xem nó trong một thời gian dài. Bạn có thể giải thích tại sao câu trả lời được chấp nhận tốt hơn câu trả lời này từ quan điểm thực tế hay không. Tôi chắc chắn có được lý do tại sao câu trả lời của Drew là tốt hơn. Có vẻ như câu trả lời được chấp nhận vẫn yêu cầu chạy lại. – seanmcl

+0

Tôi thực sự đã bỏ phiếu cho câu trả lời của Drew và không được chấp nhận. Cả hai đều hoạt động mà không cần chạy lại bản dựng. Trong câu trả lời được chấp nhận, bạn có thể nhảy vào một trình bao ngay trước lệnh không thành công (Bạn có thể chạy lại nó để xem lỗi nếu nó nhanh). Hoặc với câu trả lời của Drew, bạn có thể nhận được một trình bao sau khi lệnh không thành công đã chạy (Trong trường hợp của anh ta lệnh thất bại đã chạy dài và trạng thái bên trái có thể được kiểm tra). –

3

Docker caches the entire filesystem state sau mỗi dòng thành công RUN.

Biết rằng:

  • để kiểm tra trạng thái mới nhất trước khi bạn thất bại RUN lệnh, nhận xét nó ra trong Dockerfile (cũng như bất kỳ và tất cả các tiếp theo RUN lệnh), sau đó chạy docker builddocker run một lần nữa.
  • để kiểm tra trạng thái sau lệnh không thành công RUN, chỉ cần thêm || true vào nó để buộc nó thành công; sau đó tiến hành như trên (giữ bất kỳ và tất cả các tiếp theo RUN lệnh nhận xét ra, chạy docker builddocker run)

Tada, không cần phải gây rối với internals Docker hoặc ID lớp, và như là một tiền thưởng Docker tự động giảm thiểu khối lượng công việc mà cần phải được thực hiện lại.

+0

Đó là một ý tưởng hay. – anonymous

83

Câu trả lời hàng đầu hoạt động trong trường hợp bạn muốn kiểm tra trạng thái ngay trước lệnh không thành công.

Tuy nhiên, câu hỏi sẽ hỏi cách kiểm tra trạng thái của vùng chứa không thành công. Trong tình huống của tôi, lệnh không thành công là một bản dựng mất vài giờ, do đó, tua lại trước khi lệnh thất bại và chạy nó lại mất một thời gian dài và không hữu ích lắm.

Giải pháp ở đây là để tìm container mà thất bại:

$ 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 

Commit nó đến một hình ảnh:

$ docker commit 6934ada98de6 
sha256:7015687976a478e0e94b60fa496d319cdf4ec847bcd612aecf869a72336e6b83 

Và sau đó chạy các hình ảnh [nếu cần thiết, chạy bash]:

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

Bây giờ bạn đang thực sự xem xét trạng thái của bản dựng tại thời điểm nó không thành công, thay vì ở phần ti tôi trước khi chạy lệnh gây ra lỗi.

+6

Đây phải là câu trả lời được chấp nhận! Cảm ơn bạn! – qbolec

0

Gỡ lỗi các bước xây dựng lỗi thực sự rất khó chịu.

Giải pháp tốt nhất mà tôi đã tìm thấy là đảm bảo rằng mỗi bước thực hiện công việc thực sự thành công và thêm kiểm tra sau những bước không thành công. Bằng cách đó bạn nhận được một lớp cam kết có chứa các kết quả đầu ra của bước không thành công mà bạn có thể kiểm tra.

Một Dockerfile, với một ví dụ sau # Run DB2 silent installer dòng:.

# 
# 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 
Các vấn đề liên quan