본문 바로가기

시스템/Devops

Docker Compose .env 설정 반영 확인, 파일을 열지 않고 저장부터 점검하기

환경값을 수정했다는 안내 뒤에도 디스크의 수정 시각이 그대로여서, 저장 후 시각 변화를 확인하고 컨테이너를 재생성한 다음 상태 응답과 실제 인식 결과로 반영을 검증했다. 사용자는 값을 넣었으니 Docker를 올려 달라고 했고, .env는 절대 읽지 말라고 했다. 내용을 열지 않고 메타데이터를 확인했는데, 수정 시각은 여전히 전날 그대로였다.

전제 환경 — macOS / Docker Compose / IDE / curl / python3 / 로컬 상태 API

한 줄 답 — 환경값 수정 후에도 .env의 디스크 저장 반영이 확인되지 않아, 내용을 읽지 않고 수정 시각 변화를 기다린 뒤 컨테이너를 재생성하고 상태 응답과 실제 인식 시험으로 적용을 검증했다.

핵심만 먼저

  • .env 내용 대신 파일 크기와 수정 시각 확인.
  • IDE에서 저장한 뒤 수정 시각 변화 확인.
  • 컨테이너 재생성 후 필요한 상태 필드만 조회.
  • 실제 화면 입력으로 연결 상태와 인식 품질을 따로 검증.

왜 이런 일이 생기나

IDE에서 값을 편집한 사실과 디스크에 저장된 사실은 다르다. 사용자가 수정했다고 다시 말한 뒤에도 .env 메타데이터는 그대로였다. 저장을 요청한 뒤에야 수정 시각이 바뀌는 것을 확인했다. IDE의 미저장 상태가 원인이었을 가능성은 당시 추정이며, IDE 내부 상태를 직접 확인한 결과는 없다.

파일 크기와 수정 시각은 저장 여부를 좁히는 단서이지 설정값의 정확성을 증명하지 않는다. 파일 내용을 읽어 빈 양식이라고 확인한 것도 아니다.

상태 응답의 configured는 현재 리더에 문제가 없는지를 반영한다. 설정값 자체를 비교한 결과가 아니며, 문제 상태는 problem으로 반환된다. 기록상 이 상태 응답에는 키나 엔드포인트가 노출되지 않았다.

이번 프로젝트에서는 컨테이너 재생성으로 설정 반영을 진행했다. 다른 프로젝트에도 반드시 같은 재생성 방식이 필요하다는 근거는 없다.

먼저 의심한 곳

답부터 보면 당연해 보이지만, 처음 몇 시간은 여기에 썼습니다.

처음 의심한 것 그렇게 본 이유 아니라고 판단한 근거
처음 놓치기 쉬웠던 건 사용자가 IDE에서 값을 수정했다는 말과 디스크의 .env가 저장됐다는 사실을 같은 것으로 취급하는 일이었다. 사용자가 값을 넣었다며 Docker를 올려 달라고 요청했고, 이후에도 수정했다고 재차 말했다. .env는 919바이트, 수정 시각 전날 22:19로 빈 양식을 만들었을 때의 메타데이터와 같았고 10:28 확인에서도 그대로였다. 당일 변경된 pricing.env는 553바이트, 10:27:03이었다. 저장 요청 후에야 .env 수정 시각 변화가 감지됐다. 내용이나 IDE 내부 상태를 직접 확인한 것은 아니다.

전체 그림

저장·실행 상태·기능을 분리해 확인

[IDE 환경값 편집]
        |
        v
[디스크 .env 메타데이터]
        |-- 수정 시각 그대로 --> [저장 요청] --> [시각 변화 대기]
        |                                      |
        +-------------- 변화 확인 <-------------+
                            |
                            v
                 [컨테이너 재생성]
                            |
                            v
                 [상태 API 일부 필드]
                            |
                            v
                 [실제 보드 입력 시험]
                            |
                            v
              [정상 연결 뒤에도 대소문자 오인]

절차

1. 메타데이터를 확인하고 IDE의 변경을 저장한다

이걸 먼저 보는 이유는 수정한 파일과 실행에 쓰는 파일을 혼동하지 않기 위해서다. 당시 pricing.env는 바뀌었지만 .env의 크기와 수정 시각은 그대로였다.

점검 — ~/handwriting-latex-poc 프로젝트 디렉터리에서 .env 메타데이터 확인

stat -f "%N %z bytes, modified %Sm" .env

이렇게 나오면 정상

# .env의 파일 크기와 modified 뒤의 수정 시각을 확인.
# 내용은 출력하지 않음.

확인 — 별도 터미널에서 저장 전에 실행해 수정 시각 변화 대기

f=~/handwriting-latex-poc/.env; t0=$(stat -f %m "$f"); until [ "$(stat -f %m "$f")" != "$t0" ]; do sleep 2; done; sleep 1; stat -f "%N %z bytes, modified %Sm" "$f"

이렇게 나오면 정상

# 대기 중에는 출력이 없음.
# 수정 시각이 바뀌면 파일 이름·크기·수정 시각을 출력.
# 출력된 수정 시각이 diagnose에서 확인한 시각과 달라졌는지 확인.

실패하면 — 수정 시각이 그대로면 IDE의 수정 표시를 확인하고 ⌘S 또는 File → Save All로 저장해 달라고 요청한다. 저장하기 전에 아래 verify의 대기 명령부터 실행한다. 명령이 종료돼 변경된 수정 시각이 출력되면 2단계로 넘어간다.

2. 컨테이너를 재생성하고 리더 상태를 확인한다

수정 시각이 바뀐 것으로 확인한 건 디스크 저장까지다. 실행 중인 리더에도 반영됐는지는 재생성 뒤 상태 응답으로 따로 확인한다.

실행 — 수정 시각 변화 확인 후 ~/handwriting-latex-poc 프로젝트 디렉터리에서 실행

docker compose up -d --force-recreate 2>&1 | tail -3

이렇게 나오면 정상

# 컨테이너 재생성 로그의 마지막 3줄을 확인.

확인 — 로컬 상태 API에서 필요한 필드만 출력

sleep 2 && curl -s localhost:8765/api/health | python3 -c "import json,sys; h=json.load(sys.stdin); print({k: h[k] for k in ('engine','label','configured','problem','itex')})"

이렇게 나오면 정상

# engine, label, configured, problem, itex만 출력되는지 확인.
# configured가 참이고 problem이 문제 없는 상태를 나타내면 3단계로 진행.
# configured는 설정값 자체를 비교한 결과가 아님.

실패하면 — 재생성이 완료됐는지 확인할 수 없거나 상태 응답을 읽을 수 없으면 3단계로 넘어가지 않는다. 상태 응답이 나오면 configured만 보지 말고 problem도 확인한다. 재생성 실패나 상태 문제별 해결 절차는 이 기록에 없다.

3. 실제 보드에 분수를 입력해 인식 결과를 확인한다

상태 응답만 보고 끝내지 않은 이유는 실제 인식이 맞는지도 봐야 했기 때문이다. 정상 연결 뒤에도 x =를 X =로 읽는 오인은 남았다.

실패하면 — x =가 X =로 인식되면 연결 실패와 구분해 기록한다. 이번 시험에도 대소문자 오인이 남았으며, 이를 고친 절차는 없다.

끝났는지 확인하기

  • 저장 대기 명령이 종료되고 .env의 변경된 수정 시각이 출력됐다.
  • 상태 조회 출력에는 지정한 다섯 필드만 있다.
  • configured가 참이고 problem이 문제 없는 상태를 나타낸다.
  • 분자를 쓰기 전에 분모 3이 먼저 활자로 바뀐다.
  • 완료 시 줄 전체가 x=\frac{1}{3}으로 인식된다.

파라미터

키 값 설명
-d 사용 Docker Compose 컨테이너를 백그라운드로 실행.
--force-recreate 사용 이번 설정 반영 절차에서 컨테이너를 다시 생성.

증상별 조치

증상 원인 해결
사용자가 수정했다고 재차 말한 뒤에도 10:28에 확인한 `.env` 메타데이터는 그대로였다. 디스크 저장이 반영되지 않았을 가능성. IDE 미저장은 당시 추정. IDE의 수정 표시를 확인하고 저장을 요청한 뒤 수정 시각 변화를 기다린다.
줄 `x =`가 `X =`로 인식돼 1.8초 정상 연결 뒤에도 남은 대소문자 인식 오인. 내부 원인은 미확인. 설정 반영 여부와 별도로 인식 결과를 기록한다. 이 사례에는 오인 수정 절차가 없다.

롤백

이전 설정으로 되돌린 기록과 복원 명령은 없으므로 롤백 절차를 제시하지 않는다.

마치며

  • 저장 여부, 실행 중인 리더의 상태, 실제 기능 품질은 서로 다른 증거로 판정한다.

숫자로 보면

  • 919바이트 / 전날 22:19 / 10:28 — 저장 요청 전 .env는 919바이트였고 수정 시각은 전날 22:19였으며, 10:28 재확인에서도 메타데이터가 그대로였다.
  • 553바이트 / 10:27:03 — 당일 변경된 pricing.env는 553바이트, 수정 시각 10:27:03으로 관측됐지만 이것은 .env 저장 완료의 증거가 아니었다.
  • 1.8초 — 설정 반영 후 화면 시험에서 x =는 X =로 인식됐고 1.8초가 걸렸다.
  • 1.6초 / 2.0초 — 분수 입력 시험에서 분모 3의 인식은 1.6초, 분자 1의 인식은 2.0초가 걸렸다.
  • 2.8초 — 완료 시 줄 전체가 x=\frac{1}{3}으로 인식됐고 2.8초가 걸렸다.

같은 증상에서 궁금한 것

.env를 읽지 않고 저장됐는지 확인할 수 있나요?

파일 메타데이터로 저장 여부를 좁혀 확인할 수 있다. 이번에는 크기와 수정 시각을 조회하고, 저장 후 수정 시각 변화가 감지되는지 기다렸다. 이것만으로 설정값의 정확성을 증명하지는 않는다.

IDE에서 .env를 수정했는데 Docker에 반영되지 않으면 무엇부터 보나요?

먼저 디스크의 .env 수정 시각을 확인한다. 이번 기록에서는 사용자의 수정 안내 뒤에도 시각이 그대로였고, 저장 후 변화가 감지된 다음 컨테이너를 재생성했다.

상태 API의 configured가 설정값이 맞다는 뜻인가요?

이 서버에서는 아니다. configured는 현재 리더에 문제가 없는지를 반영하는 값이므로 problem과 함께 확인해야 하며, 설정값 자체를 비교한 결과는 아니다.

설정 반영을 확인했는데 손글씨 인식이 틀릴 수도 있나요?

그렇다. 이번 시험에서도 정상 연결 뒤 x =가 X =로 인식되는 오인이 남았다. 완료 시 분수 전체는 x=\frac{1}{3}으로 인식됐으므로 연결 상태와 개별 인식 품질을 구분했다.