다른 명령으로 중지 된 Docker 컨테이너를 시작하는 방법은 무엇입니까?


251

기본 명령이 충돌하여 중지 된 Docker 컨테이너를 다른 명령으로 시작하고 싶습니다. 컨테이너를 시작할 수 없으며 'docker exec'를 사용할 수 있습니다.

기본적으로 컨테이너의 내용을 검사 할 수 있도록 쉘을 시작하고 싶습니다.

다행히도 -it 옵션으로 컨테이너를 만들었습니다!

답변:


380

중지 된 컨테이너 ID 찾기

docker ps -a

중지 된 컨테이너를 커미트하십시오.

이 명령은 수정 된 컨테이너 상태를 새 이미지로 저장합니다 user/test_image

docker commit $CONTAINER_ID user/test_image

다른 진입 점으로 시작 / 실행 :

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

진입 점 인수 설명 : https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

노트 :

위의 단계는 동일한 파일 시스템 상태로 중지 된 컨테이너를 시작합니다. 빠른 조사에 좋습니다. 그러나 환경 변수, 네트워크 구성, 연결된 볼륨 및 기타 직원은 상속되지 않으므로 이러한 모든 인수를 명시 적으로 지정해야합니다.

중지 된 컨테이너를 시작하는 단계는 여기에서 차용되었습니다 : (마지막 코멘트) https://github.com/docker/docker/issues/18078


1
아니요, 이미지는 읽기 전용입니다. 수정 된 컨테이너 상태를 새로운 이미지 test_image에 저장합니다.
Dmitriusan

4
ENV, 볼륨, UID, ...이 정지 된 컨테이너와 공통되는 모든 약이 미스 거의 모든 설정 (일부 어쩌면 충분하다) 파일 시스템입니다
플로리안 클라인

4
어떻게 든 동일한 환경, 네트워크 구성, 연결된 볼륨을 얻을 수 있다면 좋을 것입니다. inspect출력을 후속 실행에 사용되는 구성으로 변환 할 수 있습니까?
Otheus

2
@Webman, 예. 그러나 컨테이너를 중지하기 전에 마운트 된 볼륨의 경우에는 해당되지 않습니다. 다음에 컨테이너를 시작할 때 동일한 볼륨을 명시 적으로 첨부해야합니다.
Dmitriusan

1
@ EmreTapcı, 나는 Docker 이데올로기에 반대한다고 생각합니다. 컨테이너는 가상 머신과 달리, 일회용 런 앤드 로우 어웨이 엔티티입니다. aaa90210 답변 을 따르려고 시도 할 수도 있지만 해킹 일 것입니다.
Dmitriusan

126

중지 된 컨테이너에 해당하는이 파일을 편집하십시오.

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

"Path"매개 변수를 변경하여 새 명령을 지정하십시오 (예 : / bin / bash). "Args"매개 변수를 설정하여 명령에 인수를 전달할 수도 있습니다.

docker 서비스를 다시 시작하십시오 (이것은 모든 실행중인 컨테이너를 중지시킵니다).

service docker restart

컨테이너를 나열하고 명령이 변경되었는지 확인하십시오.

docker ps -a

컨테이너를 시작하고 연결하면 이제 껍질 안에 있어야합니다!

docker start -ai mad_brattain

Docker 1.7.1을 사용하여 Fedora 22에서 작업했습니다.

참고 : 쉘이 대화식이 아닌 경우 (예 : -it 옵션으로 원래 컨테이너를 작성하지 않은 경우) 대신 명령을 "/ bin / sleep 600"또는 "/ bin / tail -f / dev / null"로 변경할 수 있습니다. 쉘을 얻는 또 다른 방법으로 "docker exec -it CONTID / bin / bash"를 수행 할 충분한 시간을 제공합니다.

참고 2 : 최신 버전의 도커에는 config.v2.json이 있으며, 여기서 엔트리 포인트 또는 Cmd를 변경해야합니다 (user60561 덕분에).


44
내 눈. 내 눈. Docker에서이를 올바르게 처리 할 수있는 기능 요청이기를 바랍니다.
gertvdijk

2
@AlexeyStrakh "/ usr / bin / sleep 600"을 실행 한 다음 "docker exec -it / bin / bash"를 실행하여 쉘을 얻을 수 있습니다. 해당 Path 변수에 매개 변수를 넣는 방법을 모르겠습니다. 그렇지 않으면 exec를 수행하기에 충분히 오래 살아남거나 Dmitriusan의 답변을 볼 수있는 다른 명령을 찾아보십시오.
aaa90210

3
그 질문에 대한 유일한 정확한 답변입니다. 다른 모든 제안은 "거의 같은"컨테이너를 실행하지만, 그 양, 환경, UID 등을 잊어 버립니다.
Florian Klein

3
제 경우에는 / usr / bin / sleep을 사용할 수 없었습니다. 나는 성공했습니다..."Path":"tail","Args":["-f","/dev/null"]...
nevrome

4
최신 버전의 도커에는 또는 config.v2.json중 하나를 변경해야하는 곳이 있습니다 . EntrypointCmd
user60561

20

진입 점 스크립트 상단에 수표 추가

Docker는 실제로이 기능을 새로운 기능으로 구현해야하지만 성공 또는 실패 후 종료되는 진입 점이있어 상황을 디버그하기가 어려운 상황에 대한 또 다른 해결 방법이 있습니다.

진입 점 스크립트가없는 경우 컨테이너에 필요한 명령을 실행하는 스크립트를 작성하십시오. 그런 다음이 파일의 맨 위에 다음 행을 추가하십시오 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

cat연결 을 유지 하려면 TTY를 제공해야합니다. Entrypoint 스크립트를 사용하여 컨테이너를 다음과 같이 실행합니다.

docker run -t --entrypoint entrypoint.sh image_name

그러면 스크립트가 한 번 실행되어 이미 컨테이너의 가상 파일 시스템에서 실행되었음을 나타내는 파일이 생성됩니다. 그런 다음 컨테이너를 다시 시작하여 디버깅을 수행 할 수 있습니다.

docker start container_name

컨테이너를 다시 시작하면 already_ran파일이 발견되어 시작점 스크립트가 중단됩니다 cat(입력되지 않는 입력을 영원히 기다리지 만 컨테이너를 활성 상태로 유지함 ). 그런 다음 디버깅 bash세션 을 실행할 수 있습니다 .

docker exec -i container_name bash

컨테이너가 실행되는 동안 디버깅해야하는 경우 스크립트를 제거 already_ran하고 수동으로 실행하여 entrypoint.sh다시 실행할 수도 있습니다.


3
또한 시작점 /bin/sh대신 실행 점 cat을 만들 수 있습니다. 그러면 항상 다시 시작하면됩니다. 당신의 솔루션은 바위!
Danny Dulai

4

내 문제:

  • 나는 컨테이너를 시작했다. docker run <IMAGE_NAME>
  • 그런 다음이 컨테이너에 파일을 추가했습니다.
  • 그런 다음 컨테이너를 닫고 위와 동일한 명령으로 다시 시작하려고했습니다.
  • 그러나 새 파일을 확인했을 때 누락되었습니다
  • 내가 실행할 때 docker ps -a두 개의 컨테이너를 볼 수있었습니다.
  • docker run <IMAGE_NAME>, 명령 을 실행할 때마다 새로운 이미지가 생성됩니다.

솔루션 : 첫 번째 실행에서 작성한 동일한 컨테이너에서 작업하려면 다음 단계를 수행하십시오.

  • docker ps 컨테이너의 컨테이너를 얻기 위해
  • docker container start <CONTAINER_ID> 기존 컨테이너를 시작하려면
  • 그럼 당신은 당신이 떠난 곳에서 계속할 수 있습니다. 예 :docker exec -it <CONTAINER_ID> /bin/bash
  • 그런 다음 새 이미지를 만들어 결정할 수 있습니다

이것은 질문에 대답하지 않습니다. OP는 컨테이너를 다시 시작하는 방법을 알고 싶지만 다음에 사용 된 것과 다른 인수로docker run <containerID>
CodeBlooded

2

@Dmitriusan의 답변을 가져 와서 별칭으로 만들었습니다.

별칭 docker-run-prev-container = 'prev_container_id = "$ (docker ps -aq | head -n1)"&& docker commit "$ prev_container_id" "prev_container / $ prev_container / $ prev_container_id"&& docker run -it --entrypoint = bash "prev_container / $ prev_container_id " '

~/.bashrc파일을 aliases 파일에 추가하면 멋진 새 docker-run-prev-container별칭이 생성되어 이전 컨테이너의 셸로 이동합니다.

디버깅 실패에 도움이됩니다 docker build.


2

이것은 정확히 원하는 것이 아니지만 docker export파일을 검사하는 것만 으로 중지 된 컨테이너에서 사용할 수 있습니다 .

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

1

컨테이너가 종료되는지 여부는 지정되지 않았으며 코드가 충돌하고 컨테이너에서 무슨 일이 일어나고 있는지 볼 필요가 있습니다. 종료되지 않으면 또 다른 잠재적 솔루션이 있습니다.

컨테이너 ID를 docker ps

docker exec -it 665b4a1e17b6 /bin/sh

진입 점이 문제가있는 것으로 설정되면 Dmitriusan의 답변에서 제안한대로 무시할 수도 있습니다. 로 실행중인 컨테이너에 연결할 수 있습니다 docker attach. 많은 솔루션이 다른 솔루션입니다. 이미지에 커밋 할 필요가 없습니다. 불필요한 것 같습니다.

부두 노동자 간부에 대한 문서 - https://docs.docker.com/engine/reference/commandline/exec/

부두 노동자에 대한 문서는 첨부 - https://docs.docker.com/engine/reference/commandline/attach/


-12

나는 실제로이 두 대답에 동의하지 않습니다. 컨테이너에 무엇이 있는지 보려면이 명령을 실행하여 쉘을 얻을 수 있습니다. 구성을 전혀 또는 전혀 변경하지 않아도됩니다.

docker run -it <image_name> bash

12
op가 이미지가 아닌 컨테이너에 대해 묻는 것처럼 작동하지 않습니다.
Peter Vrabel

나는 당신의 권리를 생각하지만 그렇게 할 이유를 보지 못합니다. stdout에 로그를 파이프하고 docker logs <container_id> --follow필요한 것을 제공합니다. 다른 대안은 위의 명령을 사용한 다음 dockerfile에서 동일한 명령으로 해당 이미지에서 충돌 서비스를 시작하고 거기서부터 디버그하는 것입니다.
deadbabykitten

4
run 명령은 이미지에서 새 컨테이너를 만듭니다. 중지 된 컨테이너를 시작하지 않습니다.
Waleed Abdulla

2
음, 도커의 요점은 모든 이미지가 정확히 같은 방식으로 회전 할 수 있다는 것입니까? 이것은 당신의 주장을 부정합니다. 그는 중지 된 컨테이너를 시작할 필요가 없습니다. 모든 컨테이너는 정확히 동일하므로 어떤 컨테이너가 시작 또는 중지되는지는 중요하지 않습니다. 그는 단지 내용물을 조사하려고합니다. 가장 쉬운 방법은 명령을 bash에 넣고 실행하여 명령의 파이프 출력을 로그에 실행하는 것입니다. 때로는 간단한 문제에 대한 가장 복잡한 솔루션을 제시합니다.
deadbabykitten

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