Docker 컨테이너가 "생성됨" 상태로 중단됩니다.

Docker 컨테이너가 "생성됨" 상태로 중단됩니다.

우분투 터미널에서 다음을 실행합니다.

sudo strace -f -p `pidof containerd` -o strafce_log

다른 터미널에서 나는 실행합니다

docker run ubuntu

결과적으로 두 터미널이 모두 정지됩니다. :( docker 서비스를 중지하면 더 이상 시작할 수 없습니다.

컨테이너는 상태를 유지 created하고 컨테이너에서 실행하는 모든 명령이 중단됩니다( docker logs,, )docker rmsystem prune

다른 컨테이너나 이미지에 대한 Docker 명령은 정상적으로 작동합니다. Docker ps도 작동합니다

나는 또한 내가 확인해야 할 것을 온라인에서 발견했습니다 cat /var/log/syslog | grep docker. 불행히도 거기에도 아무것도 없습니다.

Docker 또는 컨테이너가 수행하는 작업에 대한 추가 로그나 정보를 얻을 수 있는 곳을 알려 주시겠어요?

답변1

생성된 로그를 분석한 결과 이라는 프로세스가 종료되면 중지되는 sudo strace -ff -p $(pidof containerd) -o strace_log것으로 나타났습니다 . 이것이 나를 만든다execve()runc initrunc GH 페이지의 버그 보고서이것은 pthread를 사용하는 모든 프로그램에서 재현될 수 있는 커널 버그임을 설명하고 execve()문제를 재현하는 데 사용할 수 있는 짧은 Go 프로그램을 제공합니다.

package main

import (
    "os"
    "syscall"
)

func main() {
    syscall.Exec("/bin/echo", []string{"/bin/echo", "Hello"}, os.Environ())
}

이것이 커널 버그라는 것을 알고 호스트가 부팅할 수 없거나 가상 머신을 사용할 수 없는 위험 없이 Linux 커널을 신속하게 빌드하고 교체할 수 있도록 테스트에 Raspberry Pi를 사용했으며 Raspbian은 Go가 설치되어 있지 않기 때문에 테스트를 위해 다음 C 프로그램을 사용했습니다.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>

void *foo(void *p)
{
  (void) p;
  while(1)
    {
      puts("in thread");
      sleep(2);
    }
}

int main(void)
{
  printf("pid: %jd\n", (intmax_t) getpid());
  pthread_t tid;
  pthread_create(&tid, NULL, foo, NULL);

  char *envp[] = {"var"};
  char *ls_args[] = { "/bin/ls" , "-l", NULL};
  if (execve(ls_args[0], ls_args, envp) < 0) {    
    perror("execve error");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

빌드 gcc strace-test.c -o strace-test -pthread하고 strace -f ./strace-test막히는지 확인하세요.

strace를 수정하기로 되어 있던 패치가 2016년에 Linux 커널 메일링 리스트로 전송되었습니다. 그러나 아직 승인되지 않았으며 전체 토론을 읽고 이유를 알아낼 수 있습니다. 그럼에도 불구하고 나는 이 패치를 내 로컬 컴퓨터에 적용했습니다. Raspberry Pi Linux 커널 트리rpi-5.6.y 분기의 경우 Raspberry Pi에서 커널을 다시 빌드하고 교체한 후 strace -f ./strace-test더 이상 중단되지 않습니다. 2016년 이후 Linux 소스 코드에 일부 변경이 있었고 패치가 완전히 적용되지 않았습니다. FWIW, 내가 적용한 전체 패치는 다음과 같습니다.

diff --git a/kernel/fork.c b/kernel/fork.c
index 60a1295..c26aaa1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1224,7 +1224,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
        struct mm_struct *mm;
        int err;

-       err =  mutex_lock_killable(&task->signal->cred_guard_mutex);
+       err =  mutex_lock_interruptible(&task->signal->cred_guard_mutex);
        if (err)
                return ERR_PTR(err);

diff --git a/kernel/signal.c b/kernel/signal.c
index 9ad8dea..ea7c7b5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -108,6 +108,10 @@ static bool sig_ignored(struct task_struct *t, int sig, bool force)
        if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
                return false;

+       /* Do not ignore signals sent from child to the parent */
+       if (current->ptrace && current->parent == t)
+               return 0;
+
        /*
         * Tracers may want to know about even ignored signal unless it
         * is SIGKILL which can't be reported anyway but can be ignored

관련 정보