Docker Compose를 사용하면 여러 개의 컨테이너를 동시에 띄워 다양한 환경을 쉽게 구축할 수 있습니다. 예를 들어, Python(Flask) 백엔드와 MySQL 데이터베이스를 각각 컨테이너로 구성해 한 번에 실행할 수 있죠.
하지만 종종 아래와 같은 MySQL 연결 오류를 마주하게 됩니다.
Can't connect to MySQL server on 'my-db' ([Errno 111] Connection refused)
이번 글에서는 왜 이런 에러가 발생하는지, 그리고 어떻게 해결해야 하는지를 설명하도록 하겠습니다.
에러 원인: 컨테이너는 서로 다른 'localhost'를 가진다
보통 우리는 MySQL 주소를 이렇게 작성합니다.
conn = pymysql.connect(
host="localhost",
user="root",
password="pwd1234",
database="test_db"
)
하지만 이 방식은 컨테이너 환경에서는 잘못된 접근입니다. 이유는 다음과 같습니다:
- 각 컨테이너는 독립된 네트워크 공간을 갖습니다.
- Flask 컨테이너에서 localhost는 자기 자신을 가리킵니다.
- 즉, 위 코드는 Flask 컨테이너 내부에 존재하지 않는 MySQL을 찾고 있는 셈입니다.
해결 방법: host에 서비스 이름을 써야 한다
conn = pymysql.connect(
host="my-db", # Compose의 MySQL 서비스 이름
user="root",
password="pwd1234",
database="test_db"
)
이전 글에서 my-db는 docker-compose.yml에서 MySQL 서비스를 다음과 같이 정의했기 때문입니다.
services:
my-db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: pwd1234
MYSQL_DATABASE: test_db
※ 이때 my-db는 네트워크 상에서 해당 MySQL 컨테이너의 호스트 이름처럼 작동합니다.
추가 참고사항: depends_on으로 실행 순서 보장하기
MySQL이 완전히 실행되기 전에 Python 앱이 연결을 시도하면 여전히 실패할 수 있습니다.
이럴 땐 depends_on 설정을 활용해 Flask 컨테이너가 MySQL 컨테이너를 기다린 후 실행되도록 할 수 있습니다.
services:
my-db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: pwd1234
MYSQL_DATABASE: test_db
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 5s
retries: 10
my-app:
build: ./app
depends_on:
my-db:
condition: service_healthy
위 수정사항을 반영해서 다시 실행하면 아래와 같이 정상 페이지가 보이는 것을 알 수 있습니다.
'MLOps > Docker' 카테고리의 다른 글
[Kubernetes#1] 쿠버네티스(Kubernetes)란? (0) | 2025.05.13 |
---|---|
[Docker#15] Docker Compose 여러 개의 컨테이너 동시에 띄우기(1) (0) | 2025.05.13 |
[Docker#14] Docker Compose란? (0) | 2025.05.12 |
[Docker#13] Dockerfile WORKDIR (3) | 2025.05.12 |
[Docker#12] Dockerfile RUN (0) | 2025.05.12 |