종이 설정 조각이 압착 장치를 통과하며 잘못된 Docker config.json을 검증하고 복구하는 과정을 상징한 대표 이미지

Docker Desktop invalid ~/.docker/config.json high CPU: 설정 파일 검증으로 실행 중단 막기

Docker Desktop invalid ~/.docker/config.json high CPU 증상은 설정 파일 하나가 잘못됐는데도 애플리케이션이 멈춘 채 CPU와 메모리를 많이 쓰는 형태로 나타날 수 있다. Docker는 2026년 7월 27일 공개한 4.84.0 릴리스 노트에서 이 문제를 모든 플랫폼의 수정 항목으로 명시했다. 수정 전에는 오류 대화상자도 나타나지 않을 수 있었다.

이 글은 2026년 8월 13일 공식 문서와 Ubuntu 기반 환경의 격리 JSON 비교를 기준으로 한다. jq 1.7과 Python 3 파서로 구문 판정은 직접 비교했지만, 이 환경에는 Docker CLI와 Docker Desktop이 없어 실제 멈춤, 자원 사용량, 4.84.0의 대화상자는 재현하지 않았다. 목표는 실제 설정 내용을 노출하거나 지우지 않고 원인을 좁혀 정상 시작 여부를 확인하는 것이다.

20초 핵심 요약

  • 무엇: ~/.docker/config.json을 백업한 뒤 내용을 출력하지 않는 파서로 JSON 구문을 검사한다.
  • 왜: 유효하지 않은 파일은 4.84.0 이전 Docker Desktop을 멈추게 하고 CPU·메모리 사용을 높이면서 오류 안내까지 막을 수 있었다.
  • 어떻게: jq empty의 종료 코드를 확인하고 최소 구문만 수정한 다음, Desktop 버전과 재시작 결과를 별도로 판정한다.

리소스를 늘리기 전에 config.json부터 의심할 조건

Docker Desktop 4.84.0 릴리스 노트가 확정하는 범위는 좁고 구체적이다. 유효하지 않은 ~/.docker/config.json 때문에 Desktop이 멈추고 CPU·메모리를 많이 사용하면서 오류 대화상자를 표시하지 않던 문제를 수정했다. 4.84.0부터는 같은 상황에서 파일을 고치라는 대화상자를 표시한다.

이는 4.84.0이 손상된 파일을 자동 복구한다는 뜻이 아니다. 모든 고CPU 현상이 이 파일 때문이라는 뜻도 아니다. 설정 파일이 문법상 유효하다면 파일 공유 범위, 실행 중인 컨테이너 workload, 확장, VM 자원처럼 다른 경로로 진단을 옮겨야 한다. Docker도 공유 폴더의 파일 변경 알림 오버헤드를 별도의 CPU 부하 원인으로 설명한다.

진단 전에 실제 설정 경로도 확인해야 한다. 기본값은 ~/.docker/config.json이지만 DOCKER_CONFIG 환경 변수나 --config 옵션으로 다른 디렉터리를 쓸 수 있으며, --config가 더 높은 우선순위를 가진다. 기본 경로에 파일이 없다고 새 파일부터 만들지 말고 현재 실행 방식이 가리키는 경로를 먼저 확인한다.

원본을 보존한 뒤 내용 없이 구문만 검사한다

Docker Desktop을 완전히 종료하고 파일을 복사한다. 다음 명령은 가능한 범위에서 파일의 mode, ownership, timestamp를 보존한다.

cp -p ~/.docker/config.json ~/.docker/config.json.backup-$(date +%Y%m%d-%H%M%S)

명령이 실패하면 그대로 진행하지 않는다. 실제 파일 경로와 권한, 같은 이름의 백업 존재 여부부터 확인한다. 백업에도 레지스트리 인증과 프록시 관련 정보가 남을 수 있으므로 Git에 추가하거나 오류 보고서에 첨부해서는 안 된다. 재설치나 factory reset을 고려한다면 이미지·컨테이너·VM disk 백업은 이 파일 복사와 별개다.

백업 뒤에는 파일 내용을 출력하지 않는 검사를 실행한다.

jq empty ~/.docker/config.json
echo $?

오류 출력이 없고 종료 코드가 0이면 JSON 문법 검사를 통과한 것이다. 실패하면 jq가 표시한 line과 column을 기록한다. jq . ~/.docker/config.json은 전체 내용을 터미널에 출력하므로 화면 공유나 로그 수집이 있는 환경에서는 피하는 편이 안전하다.

jq가 없다면 Python 3 표준 도구로 같은 파일을 읽기 전용 검사할 수 있다.

python3 -m json.tool ~/.docker/config.json >/dev/null
echo $?

여기서도 종료 코드 0만 구문 성공으로 판정한다. 두 명령은 파일을 수정하지 않는다.

후행 쉼표와 잘린 파일은 종료 코드로 구분된다

격리 비교에는 실제 사용자 설정 대신 Docker 형태를 최소화한 합성 파일 세 개를 사용했다. 정상 입력은 credsStore와 빈 auths 객체만 포함했고, 실패 입력에는 각각 마지막 속성 뒤의 쉼표와 닫는 중괄호 누락을 넣었다.

비교에 사용한 입력 원문은 다음과 같다. 실제 ~/.docker/config.json이나 인증정보는 포함하지 않았다.

valid.json

{
  "credsStore": "desktop",
  "auths": {}
}

trailing-comma.json

{
  "credsStore": "desktop",
  "auths": {},
}

truncated.json

{
  "credsStore": "desktop",
  "auths": {}

세 입력에 같은 두 파서를 실행한 실제 출력과 종료 상태는 아래와 같다.

$ jq --version
jq-1.7
$ jq empty valid.json; echo "jq_exit=$?"
jq_exit=0
$ python3 -m json.tool valid.json >/dev/null; echo "python_exit=$?"
python_exit=0

$ jq empty trailing-comma.json; echo "jq_exit=$?"
jq: parse error: Expected another key-value pair at line 4, column 1
jq_exit=5
$ python3 -m json.tool trailing-comma.json >/dev/null; echo "python_exit=$?"
Expecting property name enclosed in double quotes: line 4 column 1 (char 44)
python_exit=1

$ jq empty truncated.json; echo "jq_exit=$?"
jq: parse error: Unfinished JSON term at EOF at line 4, column 0
jq_exit=5
$ python3 -m json.tool truncated.json >/dev/null; echo "python_exit=$?"
Expecting property name enclosed in double quotes: line 4 column 1 (char 42)
python_exit=1

같은 명령에서 정상 파일만 0을 반환했고, 후행 쉼표와 잘린 파일은 모두 비정상 종료했다. 오류 문구는 서로 달랐으므로 단순히 “invalid”라고만 기록하기보다 위치와 EOF 여부를 보고 수정 범위를 정할 수 있다. 이 비교는 JSON 문법 판정만 검증하며 Docker Desktop의 고CPU 동작을 재현한 결과는 아니다.

유효 JSON과 두 가지 구문 오류의 파서 종료 코드 비교

전체 초기화 대신 오류가 난 구문만 고친다

후행 쉼표라면 마지막 구성원 뒤의 쉼표만 제거한다. 파일이 잘렸다면 백업과 파일을 만든 도구의 기록을 대조해 닫는 구조를 복원한다. 원인을 모르는 상태에서 전체 파일을 {}로 덮어쓰면 로그인, credential helper, 프록시, 플러그인, 출력 형식 설정을 함께 잃을 수 있다.

수정이 불안하면 원본이 아니라 백업의 복사본에서 먼저 파서 검사를 반복한다. 실제 경로를 수정한 뒤에는 jq empty와 보조 파서가 모두 0인지 다시 확인한다. 오류 메시지만 사라지고 종료 코드를 보지 않으면 자동화 환경에서 실패를 놓칠 수 있다.

Docker가 제공하는 것은 config.json 속성 설명과 예제이며, 허용 필드를 완전히 판정하는 별도의 기계 판독용 JSON Schema는 아니다. 따라서 파서를 통과한 다음에는 공식 config.json 속성 문서를 기준으로 auths, credsStore, 레지스트리별 credHelpers, proxies 같은 값을 따로 살핀다.

credHelpers에 접미사가 지정돼 있다면 해당 docker-credential-<suffix> 프로그램이 PATH에 있는지 확인할 수 있다.

command -v docker-credential-<suffix>

이 명령은 helper의 존재만 확인한다. 인증 성공이나 설정값의 의미까지 보장하지 않는다. 조직이 SSO나 credential policy로 이 파일을 관리한다면 helper 항목을 임의로 제거하지 말고 관리 정책과 생성 주체를 먼저 확인한다.

4.84.0 여부와 재시작 결과를 따로 판정한다

Docker Desktop CLI를 사용할 수 있는 환경에서는 버전을 먼저 확인한다.

docker desktop version

설치 변경 없이 업데이트 존재 여부만 확인하려면 문서화된 --check-only 옵션을 쓴다.

docker desktop update --check-only

4.84.0 미만은 이 invalid 파일 무응답 버그의 수정 전 범위다. 파일 수정과 별개로 업데이트를 검토하되, 실제 업데이트는 조직 정책과 설치 권한, 백업을 확인한 뒤 수행한다. 4.84.0 이상에서 invalid 파일을 만났다면 공식 기대 동작은 자동 복구가 아니라 수정 안내 대화상자 표시다.

구문을 고친 뒤에는 다음 결과를 함께 본다.

  • Docker Desktop Dashboard가 열린다.
  • Docker 명령을 다시 실행할 수 있다.
  • 시작 중 나타났던 비정상 CPU·메모리 사용이 가라앉는다.
  • 수정한 로그인, helper, 프록시 관련 동작이 유지된다.

첫 세 항목을 이 조사 환경에서 직접 검증한 것은 아니다. 실제 환경에서 구문 검사만 성공하고 증상이 그대로라면 config.json 원인으로 확정하지 않는다. 특히 리소스 제한을 무작정 높이는 대신 파일 공유 범위와 실행 workload 등 다른 원인을 분리해 확인한다.

복원은 백업 보존과 같은 말이 아니다

수정 후 인증이나 프록시, 플러그인 동작이 나빠졌다면 Docker Desktop을 종료한다. 현재 수정본을 별도 이름으로 보존한 뒤 백업 파일을 원래 위치로 복사하고 다시 구문을 검사한다.

cp -p ~/.docker/config.json.backup-YYYYMMDD-HHMMSS ~/.docker/config.json
jq empty ~/.docker/config.json

백업 자체가 invalid라면 그대로 복원할 때 멈춤 증상도 돌아올 수 있다. 백업은 원본 상태를 보존하는 수단이지 정상 설정임을 보장하는 사본이 아니다. 이 경우 백업을 버리지 않은 채 Docker 공식 속성 문서와 조직의 설정 생성 경로를 대조해 최소 수정해야 한다.

삭제, 재설치, factory reset은 이 단계의 첫 선택이 아니다. Docker Desktop 제거는 로컬 Docker 데이터를 없앨 수 있으므로 설정 파일 하나의 구문 오류와 전체 데이터 복구 문제를 섞지 않는다.

이 진단을 끝낼 기준

jq empty0을 반환하고 Docker 전용 속성과 helper도 의도대로인데 Desktop이 계속 높은 CPU를 쓴다면, 이 버그에 대한 진단은 끝난 것이다. 그때는 config.json 삭제를 반복하지 말고 파일 공유와 workload 등 별도의 원인으로 넘어가는 편이 맞다.

반대로 invalid 판정과 4.84.0 미만 버전이 함께 확인됐다면 원본 백업, 최소 구문 수정, 재검사, 버전 검토의 순서를 유지한다. 복구 후 이미지 신뢰성까지 이어서 점검하려면 Docker 이미지 attestation API 확인 방법을 참고할 수 있다.

참고 링크

비슷한 글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다