BlueByte
network not foundFixed

Docker Compose: network not found

작성 Haneul Seo2026년 9월 8일 업데이트8 min

안녕하세요, BlueByte입니다. 어제까지 되던 프로젝트에서 docker compose up을 실행했는데 network-not-found 오류로 멈춥니다 — network <name> declared as external, but could not be found이거나, 컨테이너를 시작하려다 뜨는 Error response from daemon: network <hash> not found입니다. compose 파일은 바뀌지 않았는데, 컨테이너가 기대하는 네트워크가 더 이상 없는 것입니다. 오늘은 두 메시지 형태, Compose가 네트워크를 어떻게 이름 짓고 만드는지, 왜 하나가 사라지는지, 실제로 무엇이 있는지 보는 법, 그리고 경우별 해결까지 하나씩 짚어보겠습니다.

Compose가 출력하는 두 가지 "network not found" 메시지

이 오류를 만드는 상황은 둘로 나뉩니다. 첫째는 없어진 external 네트워크입니다:

network shared_net declared as external, but could not be found

compose 파일이 어떤 네트워크를 external: true로 표시하면, Compose에게 자신이 관리하지 않는 네트워크에 붙으라고 지시하는 것인데 — 그 네트워크가 아직 없는 것입니다. 둘째는 dangling 네트워크 참조입니다:

Error response from daemon: network 7b2a...f31 not found

여기서는 Compose 또는 앞서 만든 컨테이너가 이미 삭제된 네트워크를 ID로 여전히 참조합니다. docker compose up, down, start, restart에서 마주치며 — 저장된 참조가 데몬에 더 이상 없는 네트워크를 가리키는 것입니다.

Compose가 기본 네트워크를 이름 짓고 만드는 방식

docker compose up을 실행하면 Compose는 <project>_default라는 네트워크를 만들어 모든 서비스를 붙입니다. 프로젝트 이름은 compose 파일이 있는 디렉터리에서 오며, 재정의하지 않는 한 그렇습니다:

docker compose -p myproj up -d       # 또는 COMPOSE_PROJECT_NAME=myproj 설정
[+] Running 2/2
 ✔ Network myproj_default   Created
 ✔ Container myproj-web-1   Started

그래서 myapp_default는 myapp 프로젝트의 것입니다. 디렉터리 이름을 바꾸거나 프로젝트 이름을 바꾸면 Compose는 다르게 이름 붙은 네트워크를 찾기 시작하는데 — 실제로는 아무것도 지우지 않았는데 네트워크가 "사라진" 것처럼 보이는 흔한 이유입니다.

네트워크가 사라진 이유

참조가 깨지는 구체적인 원인은 몇 가지입니다:

  • 누군가 docker network prune 또는 docker network rm을 실행해, 멈춘 컨테이너가 여전히 가리키는 네트워크를 제거함.
  • Docker 데몬이나 호스트가 재시작됐고, 옛 컨테이너 메타데이터가 기대하는 방식으로 네트워크가 다시 만들어지지 않음.
  • compose 파일이 생성된 적 없는 external: true 네트워크를 선언했거나, 다른 이름으로 만들어짐.
  • 프로젝트 이름이 바뀜 — 디렉터리를 바꿨거나 -p를 추가해 — 이제 Compose는 newname_default를 찾는데 컨테이너는 oldname_default에 붙어 있음.

어떤 네트워크가 있고 프로젝트가 무엇을 기대하는지 확인하기

데몬이 실제로 가진 것을 나열한 뒤, compose 파일이 요구하는 것을 확인하세요:

docker network ls
docker compose config --networks

docker network ls는 모든 네트워크를 이름과 ID로 보여주고, docker compose config --networks는 병합된 compose 파일이 기대하는 네트워크를 출력합니다. 둘째 목록의 이름이 첫째에 없다면 그것이 빈틈입니다. 멈춘 컨테이너가 어떤 네트워크에 묶여 있는지 보려면:

docker inspect -f '{{json .NetworkSettings.Networks}}' myproj-web-1

dangling 네트워크 고치기: 내렸다가 다시 만들기

dangling 참조 경우라면, 프로젝트를 내려 Compose가 네트워크를 다시 세우게 하세요. --remove-orphans는 이전 프로젝트 이름에서 남은 컨테이너도 정리합니다:

docker compose down --remove-orphans
docker compose up -d

down 자체가 같은 네트워크 오류로 실패하면, 컨테이너를 강제로 다시 만들어 새 네트워크에 붙게 하세요:

docker compose up -d --force-recreate
 ✔ Network myproj_default   Created
 ✔ Container myproj-web-1   Recreated

없어진 external 네트워크 고치기: 먼저 만들기

external: true 네트워크는 docker compose up 전에 존재해야 합니다. 한 번 만든 뒤 프로젝트를 올리세요:

docker network create shared_net
docker compose up -d

이름은 정확히 일치해야 합니다. compose 파일이 네트워크에 커스텀 name:을 부여했다면, 키가 아니라 그 이름을 만드세요:

networks:
  shared_net:
    external: true
    name: company_shared

여기서는 docker network create company_shared를 실행해야 합니다 — Compose는 company_shared를 조회하고, shared_net은 로컬 별칭일 뿐입니다.

실제 사례: 호스트 재부팅 뒤 prune된 네트워크

작은 스택이 몇 주째 떠 있었습니다. 호스트를 재부팅한 뒤 공간을 확보하려고 docker system prune을 실행했는데, 멈춰 있던 프로젝트의 네트워크가 제거됐습니다. 그 뒤 docker compose up -d가 network 7b2a...f31 not found로 실패했습니다. docker network ls로 myproj_default가 사라졌음을 확인했습니다. docker compose down --remove-orphans가 낡은 참조를 정리했고, docker compose up -d가 myproj_default를 다시 만들어 두 컨테이너를 재연결했으며, 스택이 되살아났습니다 — compose 파일 수정 없이, 프로젝트 네트워킹을 깨끗한 상태로 되돌린 것뿐입니다.

"network already exists"·"port is already allocated"와 어떻게 다른가

network not found는 부재의 경우입니다 — Compose가 기대하는 네트워크가 없습니다. network <name> ... already exists는 반대로, 같은 이름의 남은 네트워크가 생성을 막는 것이라 docker network rm으로 제거합니다. Bind for 0.0.0.0:8080 failed: port is already allocated는 네트워크와 무관하며 — 다른 프로세스가 발행된 호스트 포트를 점유한 것입니다. 셋 중 무엇을 받았는지 읽으면 네트워크를 만들지, 제거할지, 포트를 비울지가 갈립니다.

관련 질문

external 오류와 daemon 오류의 차이가 뭔가요?

external 오류는 compose 파일이 여러분이 직접 만들어야 할 네트워크를 기대한다는 뜻입니다. daemon의 'network <id> not found'는 컨테이너가 삭제된 네트워크를 가리키는 dangling 참조를 들고 있다는 뜻으로, 프로젝트를 내렸다 다시 만들면 해결됩니다.

docker compose down --remove-orphans가 데이터를 지우나요?

아니요. 컨테이너와 프로젝트의 기본 네트워크를 제거하지, named 볼륨은 아닙니다. 볼륨과 이미지는 남습니다. named 볼륨까지 지우려면 -v를 명시적으로 붙여야 합니다.

docker network prune이 계속 제 스택을 깹니다.

prune은 실행 중인 컨테이너가 붙어 있지 않은 네트워크를 제거하므로, 멈춘 스택의 네트워크는 대상이 됩니다. 스택을 올린 채로 실행하거나, Compose 프로젝트가 도는 호스트에서는 피하고, 이후 docker compose up으로 되살리세요.

네트워크가 external이고 존재하는데도 Compose가 못 찾습니다.

실제 이름을 확인하세요. external 네트워크에 name:을 설정하면 Compose는 키가 아니라 그 값을 조회합니다. docker network ls에 바로 그 이름이 보여야 합니다.

매번 컨테이너를 다시 만들어야 하나요?

아니요 — 참조가 dangling일 때만입니다. 평범한 docker compose restart는 아무것도 다시 만들지 않고 기존 <project>_default 네트워크를 재사용합니다.

참고 자료

Haneul Seo

Infrastructure engineer · 10+ years running Linux fleets

같은 카테고리 다른 글

detected dubious ownershipFixed

Git: fatal: detected dubious ownership in repository

Git 2.35.2의 CVE-2022-24765 수정 이후, Git은 작업 트리나 .git 디렉터리의 소유자가 명령을 실행한 사용자와 다르면 저장소를 읽지 않습니다. 컨테이너, CI 작업, sudo 세션, 공유 드라이브에서 주로 나타납니다. 저장소가 내 것이어야 한다면 소유권을 바로잡고, 아니라면 global 설정의 safe.directory에 정확한 경로를 추가하세요 — Git은 이 설정을 저장소 자신의 설정에서는 무시합니다.

Git
failed calling webhookFixed

Kubernetes: Internal error occurred: failed calling webhook

admission webhook이 쓰기 요청 앞에 서 있는데 API server가 응답을 받지 못했고, 기본값인 failurePolicy: Fail이 그 침묵을 거부로 바꾼 것입니다. 메시지 끝부분이 곧 진단입니다 — context deadline exceeded는 호출이 도달하지 못한 것, no endpoints available은 떠 있는 게 없는 것, x509 줄은 API server가 webhook 인증서를 신뢰하지 않는 것입니다. 원인마다 해결이 다르고, 어느 것도 매니페스트 문제가 아닙니다.

Kubernetes
1205Fixed

MySQL: ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

다른 트랜잭션이 쥐고 있는 행 잠금을 innodb_lock_wait_timeout 만큼 기다리다 포기한 것입니다. sys.innodb_lock_waits 가 막고 있는 세션을 지목하고 KILL 문까지 만들어 주며, blocking_query 가 NULL 이면 블로커가 열린 트랜잭션 위에서 놀고 있다는 뜻입니다. 재시도 로직이 가장 자주 틀리는 지점은 따로 있습니다. 기본값에서는 타임아웃된 문장 하나만 롤백되므로, 트랜잭션은 그대로 열린 채 앞서 잡은 잠금을 전부 쥐고 있습니다.

MySQL
MISCONFFixed

Redis: MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk

읽기는 되는데 모든 쓰기가 거부됩니다. 마지막 백그라운드 저장이 실패했고 stop-writes-on-bgsave-error 기본값이 yes 이기 때문입니다. 진짜 원인은 로그에 적혀 있습니다 — 디스크 공간 부족, redis 사용자가 쓸 수 없는 dir, rename 시점의 read-only 마운트, 또는 fork 가 Cannot allocate memory 로 실패하는 경우입니다. 원인을 고치고 BGSAVE 한 번만 돌리면 재시작 없이 쓰기가 돌아옵니다. rdb_last_bgsave_status 가 err 에서 ok 로 바뀝니다. stop-writes-on-bgsave-error no 는 쓰기를 즉시 되살리지만 스냅샷은 여전히 실패한 상태로 두므로, 해결이 아니라 의도한 맞교환으로 다뤄야 합니다.

Redis
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryFixed

Node.js: FATAL ERROR: Reached heap limit — JavaScript heap out of memory (종료 코드 134)

V8 힙에는 시스템 메모리와 Node 릴리스에서 유도되는 자기만의 천장이 있고, 가진 RAM 보다 훨씬 낮은 경우가 흔합니다. 빌드나 서버가 거기 닿으면 V8 은 FATAL ERROR: Reached heap limit 과 종료 코드 134 로 스스로 중단합니다. v8.getHeapStatistics().heap_size_limit 으로 실제 한도를 읽은 뒤, 큰 작업은 --max-old-space-size(MiB)나 NODE_OPTIONS 로 올리고, 컨테이너 안에서는 cgroup 한도보다 낮게 잡고, 오래 도는 프로세스의 누수는 --heapsnapshot-near-heap-limit 으로 잡으세요. FATAL ERROR 줄 없이 137 로 끝나면 컨테이너 kill 이지 이 오류가 아닙니다.

Node.js
exec /docker-entrypoint.sh: exec format errorFixed

Docker: 컨테이너 시작 직후 "exec format error" — 플랫폼이 다른 이미지, 에뮬레이터 없음, 셔뱅 없는 스크립트

컨테이너가 첫 명령에서 exec format error 로 끝납니다. 커널의 ENOEXEC, 즉 파일은 있지만 여기서는 실행할 수 없다는 뜻입니다. 실제로는 한 CPU 아키텍처에서 빌드한 이미지(Apple 실리콘 Mac은 linux/arm64 를 만듭니다)를 binfmt_misc 에 QEMU 핸들러가 없는 다른 아키텍처(x86_64 서버)에서 돌리거나, 엔트리포인트 스크립트의 첫 줄이 셔뱅이 아닌 경우입니다. uname -m, docker image inspect, ls /proc/sys/fs/binfmt_misc 로 원인을 가르고, docker buildx build --platform 을 명시(또는 두 플랫폼 매니페스트 목록 발행)하거나, 에뮬레이션이 목적이면 QEMU 등록과 --platform, 스크립트라면 #!/bin/sh 한 줄로 해결합니다.

Docker