홈 서버 구축 시리즈를 진행하면서 만난 문제를 따로 정리했다.
시리즈가 궁금하다면 → 홈 서버 구축 일지
Error: reading config from file: open /etc/caddy/Caddyfile: no such file or directory
증상이 일관성이 없어서 처음엔 원인을 찾기 어려웠다.
GitHub Actions의 Sync server 단계에서 시작된다.
git reset --hard origin/main
git reset --hard는 파일을 새로 작성하면서 Caddyfile의 inode(파일 고유번호)를 교체한다.
# static/docker-compose.yml
volumes:
- ./caddy/:/etc/caddy/:ro
Caddy 컨테이너
→ 호스트의 ./caddy/ 디렉토리를 /etc/caddy/에 bind mount
→ Docker bind mount는 inode를 기준으로 파일 추적
git reset --hard 실행 전
→ Caddyfile inode #12345
git reset --hard 실행 후
→ Caddyfile inode #99999 (새 파일 생성)
컨테이너 내부
→ inode #12345를 참조하고 있었는데 사라짐
→ /etc/caddy/Caddyfile: no such file or directory
VirtioFS(OrbStack의 파일시스템 공유 방식)에서 새 inode가 컨테이너에 propagation되는 데 수초의 지연이 발생한다.
| 백엔드 | 프론트엔드 | |
|---|---|---|
| 빌드 방식 | Gradle (느림) | Vite (빠름, 캐시됨) |
| git reset → caddy reload 사이 시간 | 길다 → propagation 완료 | 짧다 → propagation 미완료 |
| 결과 | 우연히 성공 | 실패 |
롤백에서 성공한 이유도 같은 맥락이다.
롤백 실행 시점에는 이미 propagation이 완료돼 있었기 때문이다.
컨테이너 내부 파일 경로에 의존하지 않고, 호스트 파일을 stdin으로 직접 주입하는 방식으로 바꿨다.
# 변경 전 - 컨테이너 내부 파일 경로 참조 (inode 문제 영향 받음)
docker exec virgin-road-caddy caddy reload --config /etc/caddy/Caddyfile
# 변경 후 - 호스트 파일을 stdin으로 직접 전달 (inode 무관)
docker exec -i virgin-road-caddy caddy reload --config - --adapter caddyfile < "$CADDY_FILE"
--config - 옵션은 Caddy가 파일 경로 대신 stdin에서 설정을 읽도록 하는 옵션이다.
호스트에서 직접 읽어서 주입하기 때문에 Docker bind mount 상태와 완전히 무관하다.
Linux 환경에서는 bind mount 기반 --config /etc/caddy/Caddyfile이 표준이지만, Mac(OrbStack) 환경에서는 VirtioFS 특성상 이 방식이 잘 안 되는 경우가 있다.
참고로 stdin으로 Caddy 리로드하는 건 공식 지원이다.
Caddy 공식 문서에 --config - (stdin으로 읽기)가 명시되어 있으니 이상한 방법을 쓴 게 아니다 !
Docker bind mount는 inode 기준으로 파일 추적
→ git reset --hard, sed -i '' 등 inode를 교체하는 명령어 주의
해결 원칙
→ 컨테이너 내부 파일 경로에 의존하지 말 것
→ 호스트에서 직접 stdin으로 주입하는 방식 사용
증상이 비일관적으로 나타나면 타이밍 이슈를 의심해보자.
이번처럼 빌드 속도 차이 때문에 어떤 배포는 되고 어떤 배포는 안 되는 경우가 생긴다.