Làm thế nào để bắt đầu một container Docker bị dừng bằng một lệnh khác?


250

Tôi muốn bắt đầu một container Docker bị dừng bằng một lệnh khác, vì lệnh mặc định gặp sự cố - có nghĩa là tôi không thể khởi động container và sau đó sử dụng 'docker exec'.

Về cơ bản tôi muốn bắt đầu một cái vỏ để tôi có thể kiểm tra nội dung của container.

May mắn thay tôi đã tạo ra container với tùy chọn -it!

Câu trả lời:


380

Tìm id container đã dừng của bạn

docker ps -a

Cam kết container đã dừng:

Lệnh này lưu trạng thái vùng chứa đã sửa đổi thành một hình ảnh mới user/test_image

docker commit $CONTAINER_ID user/test_image

Bắt đầu / chạy với một điểm vào khác nhau:

docker run -ti --entrypoint=sh user/test_image

Mô tả đối số mục nhập: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-r nb

Ghi chú:

Các bước trên chỉ cần bắt đầu một container bị dừng với cùng trạng thái hệ thống tập tin. Đó là điều tuyệt vời cho một cuộc điều tra nhanh. Nhưng các biến môi trường, cấu hình mạng, khối lượng đính kèm và các nhân viên khác không được kế thừa, bạn nên chỉ định rõ ràng tất cả các đối số này.

Các bước để bắt đầu một container bị dừng đã được mượn từ đây: (bình luận cuối cùng) https://github.com/docker/docker/issues/18078


1
không, hình ảnh chỉ đọc. Nó lưu trạng thái vùng chứa đã sửa đổi thành hình ảnh mới test_image
Dmitriusan

4
Điều này bỏ lỡ gần như tất cả các cấu hình về env, volume, UID, 'Tất cả những gì nó có chung với container bị dừng là hệ thống tập tin (có thể đủ cho một số người)
Florian Klein

4
Sẽ thật tuyệt nếu tôi bằng cách nào đó có được cùng một môi trường, cấu hình mạng, khối lượng đính kèm. Có thể chuyển đổi inspectđầu ra thành một cấu hình được sử dụng với lần chạy tiếp theo không?
Otheus

2
@Webman, vâng, nhưng điều đó không đúng với khối lượng được gắn trước khi dừng một container. Bạn sẽ phải đính kèm cùng một khối lượng rõ ràng khi bạn khởi động container vào lần tới
Dmitriusan

1
@ EmreTapcı, tôi nghĩ làm điều đó là trái với ý thức hệ Docker. Các container được dự định là một thực thể chạy và sử dụng đơn lẻ, trái ngược với các máy ảo. Bạn có thể cố gắng làm theo câu trả lời aaa90210 , nhưng nó sẽ là một hack.
Dmitriusan

126

Chỉnh sửa tệp này (tương ứng với vùng chứa đã dừng của bạn):

vi /var/lib/docker/containers/923...4f6/config.json

Thay đổi tham số "Đường dẫn" để trỏ đến lệnh mới của bạn, ví dụ / bin / bash. Bạn cũng có thể đặt tham số "Đối số" để truyền đối số cho lệnh.

Khởi động lại dịch vụ docker (lưu ý điều này sẽ dừng tất cả các container đang chạy):

service docker restart

Liệt kê các thùng chứa của bạn và đảm bảo lệnh đã thay đổi:

docker ps -a

Bắt đầu container và gắn vào nó, bây giờ bạn sẽ ở trong vỏ của bạn!

docker start -ai mad_brattain

Đã làm việc trên Fedora 22 bằng Docker 1.7.1.

LƯU Ý: Nếu hệ vỏ của bạn không tương tác (ví dụ: bạn không tạo vùng chứa ban đầu với tùy chọn -it), thay vào đó, bạn có thể thay đổi lệnh thành "/ bin / ngủ 600" hoặc "/ bin / tail -f / dev / null" để cung cấp cho bạn đủ thời gian để thực hiện "docker exec -it CONTID / bin / bash" như một cách khác để lấy shell.

LƯU Ý 2: Các phiên bản mới hơn của docker có config.v2.json, trong đó bạn sẽ cần thay đổi Entrypoint hoặc Cmd (cảm ơn user60561).


44
đôi mắt của tôi. đôi mắt của tôi. Tôi hy vọng đây là một yêu cầu tính năng ở đâu đó để xử lý việc này đúng cách trong Docker.
gertvdijk

2
@AlexeyStrakh bạn có thể thử chạy "/ usr / bin / ngủ 600" và sau đó thực hiện "docker exec -it / bin / bash" để lấy shell. Mặc dù tôi không chắc chắn làm thế nào để đặt tham số vào biến Path đó. Nếu không, hãy thử và tìm một lệnh khác sẽ tồn tại đủ lâu để bạn thực hiện một lệnh thực thi hoặc xem câu trả lời từ Dmitriusan.
aaa90210

3
đó là câu trả lời thực sự chính xác duy nhất cho câu hỏi: tất cả các đề xuất khác đều chạy một container "gần như giống nhau", nhưng họ quên các tập, env, UIDs, Lỗi
Florian Klein

3
Trong trường hợp của tôi / usr / bin / ngủ không có sẵn. Tôi đã thành công với..."Path":"tail","Args":["-f","/dev/null"]...
nevrom

4
Các phiên bản mới hơn của docker có config.v2.json, nơi bạn sẽ cần phải thay đổi Entrypointhoặc Cmd.
dùng60561

20

Thêm một kiểm tra vào đầu tập lệnh Entrypoint của bạn

Docker thực sự cần phải thực hiện điều này như một tính năng mới, nhưng đây là một tùy chọn giải pháp khác cho các tình huống mà bạn có Entrypoint chấm dứt sau thành công hoặc thất bại, điều này có thể gây khó khăn cho việc gỡ lỗi.

Nếu bạn chưa có tập lệnh Entrypoint, hãy tạo tập lệnh chạy bất kỳ lệnh nào bạn cần cho vùng chứa của mình. Sau đó, ở đầu tệp này, thêm các dòng này vào entrypoint.sh:

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

Để đảm bảo catgiữ kết nối, bạn có thể cần cung cấp TTY. Tôi đang chạy container với tập lệnh Entrypoint của mình như vậy:

docker run -t --entrypoint entrypoint.sh image_name

Điều này sẽ khiến tập lệnh chạy một lần, tạo một tệp cho biết nó đã chạy (trong hệ thống tệp ảo của bộ chứa). Sau đó, bạn có thể khởi động lại container để thực hiện gỡ lỗi:

docker start container_name

Khi bạn khởi động lại bộ chứa, already_rantập tin sẽ được tìm thấy, khiến tập lệnh Entrypoint bị đình trệ cat(chỉ chờ mãi cho đầu vào sẽ không bao giờ đến, nhưng giữ cho bộ chứa tồn tại). Sau đó, bạn có thể thực hiện bashphiên gỡ lỗi :

docker exec -i container_name bash

Trong khi container đang chạy, bạn cũng có thể loại bỏ already_ranvà thực hiện thủ công entrypoint.shtập lệnh để chạy lại nó, nếu bạn cần gỡ lỗi theo cách đó.


3
Ngoài ra, bạn có thể làm cho điểm truy cập chạy /bin/shthay vì cat- sau đó bạn luôn có thể nhận được chỉ cần khởi động lại. Giải pháp của bạn đá!
Danny Dulai

4

Vấn đề của tôi:

  • Tôi bắt đầu một container với docker run <IMAGE_NAME>
  • Và sau đó thêm một số tệp vào thùng chứa này
  • Sau đó, tôi đóng container và cố gắng bắt đầu lại với lệnh tương tự như trên.
  • Nhưng khi tôi kiểm tra các tập tin mới, chúng bị thiếu
  • Khi tôi chạy docker ps -atôi có thể thấy hai container.
  • Điều đó có nghĩa là mỗi khi tôi chạy docker run <IMAGE_NAME>lệnh, hình ảnh mới sẽ được tạo

Giải pháp: Để làm việc trên cùng một thùng chứa bạn đã tạo ở nơi đầu tiên, hãy làm theo các bước sau

  • docker ps để lấy container của container của bạn
  • docker container start <CONTAINER_ID> để bắt đầu container hiện có
  • Sau đó, bạn có thể tiếp tục từ nơi bạn rời đi. ví dụdocker exec -it <CONTAINER_ID> /bin/bash
  • Sau đó, bạn có thể quyết định tạo một hình ảnh mới từ nó

Điều này không trả lời câu hỏi. OP muốn biết cách khởi động lại container nhưng với các đối số khác với các đối số được sử dụng trongdocker run <containerID>
CodeBlooding

2

Tôi lấy câu trả lời của @ Dmitriusan và biến nó thành bí danh:

bí danh docker-run-trước-container = 'trước_container_id = "$ (docker ps -aq | head -n1)" && docker cam kết "$ trước / $ trước_container_id "'

Thêm phần này vào ~/.bashrctệp bí danh của bạn và bạn sẽ có một docker-run-prev-containerbí danh mới tiện lợi sẽ thả bạn vào một vỏ trong thùng chứa trước đó.

Hữu ích cho việc gỡ lỗi docker builds.


2

Đây không phải là chính xác những gì bạn yêu cầu, nhưng bạn có thể sử dụng docker exporttrên một container bị dừng nếu tất cả những gì bạn muốn là kiểm tra các tệp.

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR

1

Nó không được chỉ định liệu container có thoát hay không, chỉ là mã của bạn gặp sự cố và bạn cần xem những gì đang diễn ra trong container. Nếu nó không thoát ra, đây là một giải pháp tiềm năng khác.

Nhận id container với docker ps

docker exec -it 665b4a1e17b6 /bin/sh

Nếu điểm vào được đặt thành vấn đề gì đó, nó cũng có thể bị ghi đè như đề xuất trong câu trả lời của Dmitriusan. Cũng cần lưu ý rằng bạn có thể gắn vào bất kỳ container đang chạy nào docker attach. Vì vậy, nhiều giải pháp giải pháp khác nhau. Tôi chỉ không thấy sự cần thiết phải cam kết với hình ảnh. Có vẻ như không cần thiết.

Tài liệu thực thi Docker - https://docs.docker.com/engine/reference/commandline/exec/

Tài liệu cho Docker đính kèm - https://docs.docker.com/engine/reference/commandline/attach/


-12

Tôi thực sự không đồng ý với cả hai câu trả lời này. Nếu bạn chỉ muốn xem những gì trong container, thì bạn có thể chạy lệnh này để lấy shell. Không cần phải thay đổi điểm vào tất cả hoặc bất kỳ cấu hình.

docker run -it <image_name> bash

12
Điều này không hoạt động vì op đang hỏi về một container, không phải hình ảnh.
Peter Vrabel

Tôi cho rằng quyền của bạn nhưng không thấy một lý do để làm điều đó mặc dù. Bạn có thể ghi nhật ký đường ống đến thiết bị xuất chuẩn và docker logs <container_id> --followsẽ cung cấp cho bạn những gì bạn cần. Một cách khác là sử dụng lệnh ở trên, sau đó bắt đầu dịch vụ sự cố trên hình ảnh đó với cùng một lệnh trong dockerfile và gỡ lỗi từ đó.
deadbabykitten

4
Lệnh run tạo một thùng chứa mới từ một hình ảnh. Nó không bắt đầu một container dừng lại.
Wulled Abdulla

2
Ummm, .. không phải vấn đề của docker là mọi hình ảnh đều có thể được quay theo cùng một cách? Điều này phủ nhận lập luận của bạn. Anh ấy không CẦN bắt đầu một container dừng lại. Bất kỳ container nào cũng giống hệt nhau nên việc anh ta bắt đầu hay dừng lại không thực sự quan trọng. Anh ta chỉ cố gắng kiểm tra nội dung. Cách dễ nhất để làm điều đó là bash in và chạy lệnh hoặc đầu ra đường ống của lệnh tới các bản ghi. Các bạn nghĩ ra những giải pháp phức tạp nhất cho những vấn đề đơn giản đôi khi.
deadbabykitten

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.