Docker Compose 정리 (9/9)

이전 편: 8. 04 PostgreSQL 볼륨과 초기화 다루기

이 문서가 시리즈의 마지막 편입니다.

# [Docker Compose 실습] 실행 검증과 문제 해결 루틴

Compose 환경에서 문제가 생기면 감으로 파일을 만지기 쉽다. 하지만 대부분의 문제는 정해진 순서로 좁힐 수 있다. 이번 실습의 목표는 실행, 상태 확인, 로그 확인, 설정 확인을 반복 가능한 루틴으로 만드는 것이다.

실행 전 설정 확인

파일을 고친 뒤에는 바로 up하지 말고 먼저 해석 결과를 본다.

docker compose config

확인할 것은 다음이다.

  • version obsolete 경고가 사라졌는가.
  • app.environment에 필요한 값이 들어갔는가.
  • db.environmentPOSTGRES_* 중심으로 좁혀졌는가.
  • SPRING_DATASOURCE_URLjdbc:postgresql://db:5432/... 형태인가.
  • ports가 원하는 값으로 풀렸는가.
  • volumes 이름이 예상한 프로젝트 이름을 기준으로 만들어지는가.
이 명령은 검증용이지 공유용이 아니다

docker compose config에는 실제 secret 값이 나올 수 있다. 확인 후 터미널 안에서만 다룬다.

전체 실행

이미지 빌드까지 포함해서 실행한다.

docker compose up -d --build

--build를 붙이면 앱 코드나 Dockerfile 변경이 이미지에 반영된다. Compose 파일만 바꾼 경우에는 빌드가 필요 없을 수 있지만, 학습 단계에서는 변경 반영 누락을 줄이기 위해 붙이는 편이 안전하다.

실행 상태를 확인한다.

docker compose ps

정상이라면 dbhealthy, appUp 상태가 되어야 한다. 앱에 별도 healthcheck를 넣지 않았다면 앱은 healthy가 아니라 단순 Up으로 보일 수 있다.

로그 확인 순서

문제가 생기면 전체 로그보다 서비스별 로그를 먼저 본다.

docker compose logs -f db

DB가 healthy가 되지 않으면 앱은 시작되지 않거나 대기한다. DB 로그에서 초기화, 비밀번호, 데이터 디렉터리, 포트 충돌 관련 메시지를 확인한다.

DB가 정상이라면 앱 로그를 본다.

docker compose logs -f app

앱 로그에서는 다음 유형을 구분한다.

로그 유형의심 지점
Unable to access jarfileDockerfile의 JAR 파일명 또는 COPY 경로
Connection refusedDB가 아직 준비되지 않았거나 URL이 잘못됨
UnknownHostException: dbCompose 네트워크나 서비스 이름 문제
password authentication failedDB 사용자명 또는 비밀번호 불일치
S3 인증 오류AWS S3 환경 변수 값 또는 권한 문제
JWT secret 관련 오류JWT_SECRET 누락 또는 설정 바인딩 문제

DB 연결 확인

DB 컨테이너 내부에서 PostgreSQL 준비 상태를 확인한다.

docker compose exec db sh -c 'pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"'

테이블 목록도 확인한다.

docker compose exec db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt"'

DB가 정상인데 앱만 실패한다면 앱의 JDBC URL, 사용자명, 비밀번호를 다시 본다. 컨테이너 앱의 DB URL은 localhost가 아니라 db여야 한다.

앱 접근 확인

Compose에서 앱 포트를 ${APP_PORT:-8081}:80로 두었다면 호스트에서는 다음 주소로 접근한다.

http://localhost:8081

PowerShell에서는 상태 코드만 간단히 확인할 수 있다.

Invoke-WebRequest http://localhost:8081 -UseBasicParsing

Actuator health가 열려 있다면 다음 주소도 확인할 수 있다.

http://localhost:8081/actuator/health

보안 설정 때문에 health 엔드포인트가 막혀 있으면 401 또는 403이 나올 수 있다. 이 경우에는 컨테이너가 죽었다는 뜻이 아니라 접근 권한 정책 문제일 수 있다. 앱 로그와 docker compose ps를 함께 본다.

자주 나는 문제와 처리

증상원인 후보확인 명령
version 경고Compose 파일에 version이 남아 있음docker compose config
DB 포트 충돌호스트 5432를 이미 사용 중docker compose ps, Docker Desktop
앱이 DB 연결 실패JDBC URL이 localhost이거나 DB가 unhealthydocker compose logs app, docker compose logs db
수정한 schema.sql이 반영되지 않음기존 postgres_data 볼륨이 이미 초기화됨docker volume ls
컨테이너가 JAR을 못 찾음Dockerfile의 JAR 파일명 고정값 불일치docker compose logs app
.env 값을 바꿨는데 그대로임컨테이너 재생성 또는 config 확인 누락docker compose config, docker compose up -d

정리 명령

컨테이너와 네트워크만 내린다.

docker compose down

DB 데이터까지 지우고 완전히 새로 시작한다.

docker compose down -v

이미지까지 다시 빌드한다.

docker compose up -d --build

캐시 없이 앱 이미지를 다시 빌드한다.

docker compose build --no-cache app
docker compose up -d

down -v--no-cache는 강한 명령이다. 전자는 데이터를 지우고, 후자는 빌드 캐시를 버린다. 문제를 좁힌 뒤 필요한 경우에만 쓴다.

최종 검증 체크리스트

  • docker compose config에서 구조와 변수 보간을 확인했다.
  • docker compose up -d --build로 전체 환경을 실행했다.
  • docker compose ps에서 DB 상태를 확인했다.
  • docker compose logs -f dbdocker compose logs -f app로 실패 지점을 분리할 수 있다.
  • 앱이 DB에 db:5432로 접속한다는 점을 확인했다.
  • downdown -v를 구분해서 사용할 수 있다.

이 루틴이 손에 익으면 Compose 파일은 더 이상 무서운 설정 파일이 아니다. 문제가 생겼을 때 어디서부터 볼지 정해진 실행 환경이 된다.