이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- Compose service, network, volume은 로컬 Spring 운영 환경에서 각각 어떤 책임을 가지는가?
- service name, host port, container port, volume 이름을 어떻게 읽어야 하는가?
- Compose 파일이 운영 장애 학습에 도움이 되려면 어떤 계약을 명확히 해야 하는가?
개요
Docker Compose는 여러 container를 하나의 로컬 환경으로 묶는 도구다.
Spring API, MySQL, Redis를 같은 명령으로 띄우고, 같은 network에서 서로 찾게 하고, 필요한 데이터는 volume으로 보존할 수 있다.
Compose를 잘 쓰면 “내 컴퓨터에서는 됐는데 다른 사람은 안 된다”를 줄이고, 운영 의존성의 기본 계약을 로컬에서 연습할 수 있다.
Service
Compose의 service는 실행 단위다.
services:
api:
build: .
ports:
- "8080:8080"
mysql:
image: mysql:8.4
redis:
image: redis:7.2api, mysql, redis는 container 이름처럼 보이지만 더 중요한 것은 network alias다.
같은 Compose project 안에서 api는 mysql:3306, redis:6379로 접근할 수 있다.
Spring 설정도 이 이름을 기준으로 작성해야 한다.
Network
Compose는 기본 network를 만든다.
별도 설정이 없어도 service들은 같은 project network에 붙는다.
중요한 것은 localhost의 기준이다.
Spring container 내부에서 localhost는 Spring container 자신이다.
따라서 MySQL 주소는 다음처럼 써야 한다.
spring.datasource.url=jdbc:mysql://mysql:3306/app
spring.data.redis.host=redishost machine에서 MySQL에 붙을 때는 publish된 host port를 쓴다.
mysql:
ports:
- "3306:3306"왼쪽은 host port이고 오른쪽은 container port다.
Volume
Volume은 container 교체와 데이터 보존을 분리한다.
services:
mysql:
image: mysql:8.4
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:mysql-data를 쓰면 MySQL container를 지워도 데이터가 남을 수 있다.
하지만 테스트를 매번 깨끗하게 시작하려면 reset 절차가 필요하다.
docker compose down -v
docker compose up -ddown -v는 volume을 지우므로 로컬 개발 데이터도 함께 사라진다.
운영 데이터가 있는 환경에서는 같은 감각으로 실행하면 안 된다.
Compose Config 확인
Compose 파일은 변수 치환과 override가 적용된 최종 결과를 확인해야 한다.
docker compose config
docker compose ps
docker compose logs --tail 100 apidocker compose config는 .env, env_file, 여러 compose 파일의 병합 결과를 보여준다.
이 명령 없이 파일만 보면 실제 실행 값과 다를 수 있다.
운영 체크리스트
- service 이름이 Spring 설정의 host 이름과 일치하는가?
- host port와 container port를 구분해 문서화했는가?
- DB와 Redis 데이터가 volume에 남아야 하는지, 매번 초기화해야 하는지 정했는가?
docker compose config출력이 기대한 env와 port를 보여주는가?- Compose project name이 팀원마다 달라도 충돌하지 않는가?
- local 전용 값과 운영 Secret이 섞이지 않는가?
- reset 명령이 위험 명령으로 표시되어 있는가?
장애 신호
- Spring이
localhost:3306으로 붙으려다 connection refused가 난다. - host에서는 MySQL에 붙지만
apicontainer에서는 실패한다. docker compose ps에서 DB는 Up이지만 Spring startup은 DB 연결 실패로 종료된다.docker compose down -v후 로컬 테스트 데이터가 사라졌다.- 팀원마다
.env.local값이 달라 재현 결과가 다르다. - host port 충돌로 Compose가 시작되지 않는다.
안전한 완화 조치
접속 문제는 service name과 network부터 확인한다.
데이터 유실이 의심되면 volume 삭제 명령을 멈추고 mount 정보를 본다.
docker compose ps
docker compose exec api printenv | grep -E 'SPRING|DB|REDIS'
docker volume lsport 충돌이면 host port를 바꾸거나 해당 host process를 확인한다.
무작정 down -v로 초기화하면 원인과 데이터를 같이 잃을 수 있다.
인프라 담당자와 공유할 자료
로컬 재현 환경: docker compose
문제: api container에서 mysql 접속 실패
Spring DB URL: jdbc:mysql://localhost:3306/app
Compose service: mysql
확인 결과: host mysql 접속은 성공, api container 내부 접속 실패
수정 방향: DB URL을 jdbc:mysql://mysql:3306/app으로 변경Compose 문제도 service, network, volume, env를 분리해 전달하면 운영 환경의 유사 문제를 설명하기 쉬워진다.
실전 팁
- service name은 운영 의존성 이름과 비슷하게 짓는다.
- local port publish는 필요한 것만 연다.
- volume 이름에는 서비스와 용도를 드러낸다.
docker compose config출력을 리뷰 자료로 쓴다.- reset 명령은 README에서 별도 경고와 함께 둔다.
위험 신호!
- Spring container에서 DB host를
localhost로 둔다. - 익명 volume에 DB 데이터를 두고 reset 방법을 모른다.
- host port 충돌을 해결하려고 임의 프로세스를 바로 죽인다.
.env.local을 팀원이 각자 다르게 관리한다.- 운영 환경에서도 Compose local reset 명령을 같은 감각으로 실행한다.
확인 질문
확인 질문
- Compose service name이 중요한 이유는 무엇인가?
- 같은 Compose network 안에서 service name이 DNS 이름처럼 동작해 container 간 접근 주소가 되기 때문이다.
docker compose down -v를 조심해야 하는 이유는 무엇인가?
- container뿐 아니라 named volume까지 삭제해 로컬 DB 데이터나 재현 증거를 잃을 수 있기 때문이다.
docker compose config를 확인해야 하는 이유는 무엇인가?
- 변수 치환과 override가 반영된 실제 실행 설정을 확인해야 파일만 볼 때 놓치는 drift를 줄일 수 있기 때문이다.