Docker Compose PHP·Nginx·MariaDB 시작 경합 — healthcheck 전후 로그로 확인하기
Docker Compose로 PHP와 MariaDB를 함께 시작하면 DB 컨테이너가 실행 중이어도 PHP의 첫 연결은 실패할 수 있다. 컨테이너 시작과 DB가 인증·쿼리를 처리할 준비가 되는 시점은 다르기 때문이다.
아래 실습 이미지에는 수정 전 Connection refused와 수정 후 DB connection OK가 기록돼 있다. 이 글은 두 실행의 로그를 비교하고, healthcheck와 service_healthy가 해결하는 범위를 설명한다. 반복 실행 횟수와 실패율은 이미지에서 확인되지 않으므로 결과를 일반화하지 않는다.
1. 이미지에서 확인되는 실행 환경
- 구성: Docker Compose의 db·php·nginx 서비스.
- DB 서버: 성공 로그에
10.11.18-MariaDB-ubu2204가 표시된다. - 실습 DB와 접속 계정:
testdb,app. - 검증 자료: 2026-08-13의 시작 로그와 재시작 전후 데이터 조회 화면.
Docker Engine·Compose의 정확한 버전과 이미지 digest는 첨부 화면에 없다. 같은 실습을 다시 실행할 때는 다음 명령으로 환경을 별도 기록한다. 아래 YAML의 이미지 태그는 기존 구성 예시이며, 같은 태그라도 내려받는 시점에 따라 실제 이미지가 달라질 수 있다.
docker version
docker compose version
docker compose config --services
2. DB 컨테이너 시작만 기다렸을 때의 실패
기존 구성의 PHP 서비스는 짧은 형식의 depends_on: [db]를 사용했다. 이 설정은 DB의 쿼리 처리 준비까지 기다리는 조건이 아니다.
services:
db:
image: mariadb:10.11
environment:
MARIADB_DATABASE: testdb
MARIADB_USER: app
MARIADB_PASSWORD: ${DB_PASSWORD}
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
- "./testdb.sql:/docker-entrypoint-initdb.d/01-testdb.sql:ro"
php:
build: ./php
depends_on: [db]
environment:
DB_HOST: db
DB_NAME: testdb
DB_USER: app
DB_PASSWORD: ${DB_PASSWORD}
nginx:
image: nginx:1.27-alpine
depends_on: [php]
ports: ["8080:80"]
volumes:
db_data:
이 구성은 시작 순서를 설명하기 위한 예시이며, 이것만으로 실행할 수 있는 전체 배포 구성은 아니다. PHP의 Dockerfile과 접속 확인 처리, Nginx 설정, 초기화용 testdb.sql, 환경 변수가 별도로 필요하다. PHP는 시작 직후 DB 접속을 시도하고 그 결과를 로그에 기록하도록 구성했다고 가정한다.
이 화면은 PHP가 DB에 접속하지 못했다는 사실을 보여준다. 다만 Connection refused만으로 원인을 확정할 수는 없다. 시작 시점의 준비 대기 문제와 함께 접속 대상 호스트·포트 및 DB 시작 오류도 확인해야 한다. 이번 비교에서는 DB 준비 완료를 기다리는 조건을 추가한 뒤 접속 결과를 다시 확인했다.
3. 애플리케이션 계정의 쿼리 성공을 기다린다
DB에 healthcheck를 추가하고 PHP의 의존 조건을 service_healthy로 변경한다. 아래 내용은 앞의 구성에 반영할 변경 부분이며, PHP 환경 변수와 DB volume 설정 등은 그대로 유지한다.
services:
db:
healthcheck:
test:
- CMD-SHELL
- >
mariadb -h 127.0.0.1
-u"$${MARIADB_USER}"
-p"$${MARIADB_PASSWORD}"
"$${MARIADB_DATABASE}"
-e "SELECT 1" >/dev/null
interval: 5s
timeout: 3s
retries: 10
start_period: 20s
php:
depends_on:
db:
condition: service_healthy
$${...}는 Compose가 호스트에서 변수를 확장하지 않고 컨테이너 안에서 환경 변수를 확장하도록 하는 표기다. 여기서는 root 계정 대신 애플리케이션용 계정으로 DB를 선택한 뒤 SELECT 1이 성공하는지 확인한다.
이 검사는 DB 컨테이너 내부에서 인증과 간단한 쿼리가 성공하는지만 확인한다. PHP 컨테이너에서 DB로 연결되는지, 필요한 테이블과 마이그레이션이 준비됐는지까지 증명하지는 않는다. 따라서 PHP의 실제 접속 결과도 함께 확인해야 한다.
4. 첨부 로그에서 확인한 변경 후 결과
| 항목 | 이미지에 기록된 내용 |
|---|---|
| 수정 전 PHP 시작 | 2026-08-13 09:12:04, 접속 결과는 Connection refused |
| 수정 후 DB 준비 완료 로그 | 2026-08-13 09:14:51, ready for connections |
| healthcheck 상태 | PHP 시작 로그보다 먼저 Healthy가 표시되었다. 상태가 바뀐 정확한 시각은 이미지에 없다. |
| 수정 후 PHP 시작·접속 | 2026-08-13 09:14:53, DB connection OK |
| 반복 검증 | 전체 실행 횟수와 실패율은 기록되지 않았다. 여기서는 첨부된 수정 전후 실행 결과만 판단한다. |
PHP 로그의 시각에는 +00:00이 표시되지만 DB 로그의 시각에는 시간대가 표시되지 않는다. 따라서 표시된 시각의 차이만으로 정확한 대기 시간을 계산하지 않는다. 첨부 자료에서 확인할 수 있는 사실은 변경 후 실행에서 Healthy 표시 다음에 PHP가 DB 접속에 성공했다는 점이다.
다시 검증할 때는 수정 전과 수정 후의 초기 데이터 상태를 동일하게 맞춰 비교해야 한다. 최초 DB 초기화와 기존 데이터를 사용하는 시작은 준비 시간이 다를 수 있으므로, 조건이 다른 실행 결과를 그대로 성공률 비교에 사용하지 않는다.
docker compose config --quiet
docker compose up --build -d
docker compose ps -a
docker compose logs --timestamps db php nginx
다른 이름의 Compose 파일을 사용한다면 모든 명령에 같은 -f 옵션을 지정한다. 이번 재시작 이미지에서는 docker-compose-healthcheck.yml을 사용했다. 전체 설정이나 검사 로그를 공개하기 전에는 확장된 접속 정보가 포함되지 않았는지 확인한다.
5. 재시작 전후 데이터 확인은 시작 순서와 구분한다
다음 이미지에서 실행한 명령은 docker compose restart다. 컨테이너를 삭제하고 다시 만드는 down → up 검증은 아니다. 재시작 전후에 audit_logs의 같은 마커 행이 조회되었다.
docker compose -f docker-compose-healthcheck.yml exec db mariadb -uapp -p testdb
비밀번호를 대화식으로 입력해 접속한 뒤 다음 SQL로 기존 마커를 확인한다. 이 쿼리는 실습용 audit_logs 테이블이 있는 환경을 대상으로 하며, 모든 DB에서 그대로 사용할 수 있는 스키마는 아니다.
SELECT audit_log_id, action, detail, created_at
FROM audit_logs
WHERE action = 'VOLUME_MARKER';
클라이언트를 종료하고 다음 명령을 실행한 뒤, DB 준비가 끝나면 다시 접속해 같은 SQL을 실행한다.
docker compose -f docker-compose-healthcheck.yml restart
이 결과는 재시작 전후에 마커 행이 유지됐다는 사실을 보여준다. 컨테이너를 다시 만든 뒤 volume이 연결되는지 또는 백업 복원이 가능한지 검증한 결과는 아니다. 구성 예시에는 named volume을 지정했지만, 영속성을 별도로 확인하려면 컨테이너 재생성을 포함한 검증이 필요하다. 일반적인 docker compose down은 named volume을 삭제하지 않지만 down -v는 삭제 대상에 포함하므로, 필요한 데이터가 있는 환경에서는 실행하지 않는다.
6. 시작 후 발생하는 DB 장애에는 별도 대응이 필요하다
이번 조건 변경은 Compose가 서비스를 시작할 때 DB의 healthcheck 성공을 기다리도록 하는 설정이다. 시작 후 발생하는 DB 중단, 네트워크 단절, 기존 접속의 만료를 계속 해결하는 기능은 아니다. 실행 중인 애플리케이션에는 접속 재설정, 횟수와 시간을 제한한 재시도, 적절한 실패 응답 처리가 필요하다. 쓰기 작업을 재시도한다면 중복 실행에 대한 처리 방법도 정해야 한다.
첨부 로그에서는 변경 전 접속 실패와 변경 후 Healthy 표시에 이어진 PHP 접속 성공을 확인할 수 있다. 이를 시작 시점의 확인 결과로 해석하고, 지속적인 장애 대응 능력과 HTTP 응답의 정상 여부는 별도 검증으로 확인한다.
참고 자료
공식 문서 확인일: 2026-09-08. 기존 이미지에 기록된 내용을 바탕으로 작성했으며, 이번 편집 과정에서 실습을 다시 실행하지는 않았다.
댓글 0