>  Q&A  >  본문

문제 2003(HY000) 해결 방법: MySQL 서버 'db_mysql:3306'에 연결할 수 없습니다(111).

<p>저는 최근 FastAPI Python 서버 컨테이너화를 시도했습니다(복제/두배 목적으로도). 이전에는 Docker 컨테이너에 MySQL 서버만 있으면 모든 것이 괜찮았지만 웹 서버도 서비스로 만들었을 때 MySQL 서버에 연결할 수 없어 이제는 애플리케이션이 작동하지 않습니다.</p> <p>다음은 애플리케이션의 서버 데이터베이스 초기화 커넥터에 대한 코드 조각입니다</p> <pre class="lang-py Prettyprint-override"><code>from fastapi import FastAPI mysql.connector 가져오기 앱 = FastAPI() DB구성 = { "호스트": "로컬호스트", "데이터베이스": "server_db", "사용자": "db_user", "password": "사용자-비밀번호" } # 데이터베이스 연결 확인 노력하다: init_cnx = mysql.connector.connect( 호스트='로컬호스트', 사용자='db_user', 비밀번호='사용자-비밀번호' ) 커서 = init_cnx.cursor() cursor.execute("'server_db'와 같은 데이터베이스 표시") 커서.fetchone() == 없음인 경우: # 데이터베이스가 존재하지 않으면 데이터베이스를 생성합니다. 커서.execute("CREATE DATABASE server_db") 커서.execute("서버_db 사용") cursor.execute("CREATE TABLE 메시지(" "message_id INT NOT NULL AUTO_INCREMENT," "발신자_이름 VARCHAR(32)," "message_text VARCHAR(64)," "created_at DATE," "user_messages_count INT," "기본 키(message_id));") print('데이터베이스가 생성되었습니다!') 커서.닫기() init_cnx.close() mysql.connector.Error를 err로 제외: print("init_cnx에서 오류가 발생했습니다:", err) # 데이터베이스 I/O 기능 비동기 defexecute_db_query(query,cursor_buffered=False): cnx = mysql.connector.connect(**dbconfig) 노력하다: 커서 = cnx.cursor(buffered=cursor_buffered) 커서.execute("서버_db 사용") 커서.실행(쿼리) 결과 = 커서.fetchall() cnx.커밋() print("쿼리가 성공적으로 실행되었습니다!") 결과 반환 e와 같은 예외를 제외하고: print("쿼리 실행 중 오류 발생:", e) 마지막으로: 만약 cnx라면: cnx.닫기() # 애플리케이션이 데이터베이스에 연결되어 있는지 확인하는 데 사용되는 루트 디렉터리 기능을 가져옵니다. @app.get("/") 비동기 def get_root(): 노력하다: 항목_카운트 = 실행 실행을 기다립니다_db_query("SELECT COUNT(*) FROM 메시지",cursor_buffered=True) {"메시지 항목"을 반환합니다: 항목_수[0][0]} e와 같은 예외를 제외하고: {"오류": e}를 반환합니다. <p>서버의 Dockerfile</p> <pre class="brush:php;toolbar:false;">FROM python:3.11.4-slim-bookworm WORKDIR/앱 요구사항.txt를 복사하세요. 실행 pip install --no-cache-dir -r 요구사항.txt 복사 server.py . 노출 8000 CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]</pre> <p>init.sql 스크립트</p> <pre class="lang-sql Prettyprint-override"><code>CREATE USER 'db_user'@'%' IDENTIFIED BY 'user-password'; GRANT OPTION을 사용하여 *.*에 대한 모든 권한을 'db_user'@'%'에 부여합니다. 플러시 권한; <p>및 docker-compose.yml</p> <pre class="lang-yaml Prettyprint-override"><code>버전: "3.8" 서비스: db_mysql: 이미지: mysql:8 다시 시작: 항상 환경: MYSQL_ROOT_PASSWORD: "루트" 볼륨: - "./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql" - "./mysql/db_mysql_data:/var/lib/mysql" - "./mysql/mysql_logs:/var/log/mysql" 네트워크: -dummy_network 서버_1: 이미지: dummy_msg_server 포트: - "8081:8000" 네트워크: -dummy_network #명령: sh -c "sleep 60s" 의존: -db_mysql 서버_2: 이미지: dummy_msg_server 포트: - "8082:8000" 네트워크: -dummy_network #명령: sh -c "sleep 60s" 의존: -db_mysql 볼륨: db_mysql_data: #외부: 참 네트워크: dummy_network: 드라이버: 브릿지 <p>MySQL 컨테이너가 완전히 초기화되기 전에 API를 사용하려고 하면 오류가 발생할 수 있지만 MySQL 서버가 요청을 처리할 준비가 되었음을 나타낼 때까지 기다리기 때문에 이는 문제가 되지 않습니다. 그 외에는 MySQL 서버에 연결을 시도하지 않습니다. </p> <p>호스트 이름/IP 주소를 사용하여 연결을 시도했습니다. 슬림 이미지를 사용하지 않고 dockerfile의 python:3.11.4 이미지를 이전 Debian 버전으로 변경해 보세요.컨테이너에 대해 공용 네트워크를 명시적으로 사용해 보십시오. Docker는 컨테이너가 네트워크에 있음을 계속 표시하고 서버 컨테이너의 컬 요청이 무언가를 반환합니다. 또한 docker-compose.yml은 이전에 db_mysql 서비스에 포트 3306:3306을 제공했습니다. 그것도 문제가 아닌 것 같아요. </p> <p><strong>업데이트 1. </strong>조사 중에 데이터베이스가 이미 생성된 경우 애플리케이션이 해당 데이터베이스에 요청을 보내고 올바른 응답을 받는 데 아무런 문제가 없다는 사실이 발견되었습니다. 유일한 문제는 코드의 생성 스크립트를 사용하여 데이터베이스를 생성할 수 없다는 것입니다. </p><p> (이제 프로젝트가 다른 단계에 있으므로 코드 블록을 업데이트해야 할 것 같습니다.)</p>
P粉178132828P粉178132828431일 전715

모든 응답(1)나는 대답할 것이다

  • P粉141455512

    P粉1414555122023-09-06 09:54:17

    서버와 데이터베이스 컨테이너가 동시에 시작되어 문제가 발생하는 문제가 발생했습니다. 데이터베이스 서버에 대한 첫 번째(및 마지막) 연결 시도는 데이터베이스 서버가 연결을 수락할 준비가 되기 전에 발생합니다.

    이 문제를 해결하기 위해 docker-compose.yml 파일에 상태 확인을 추가하기로 결정했습니다.

    으아악

    이 구성을 사용하면 상태 확인을 통해 데이터베이스 서버가 준비되었음을 확인할 때까지 서버의 컨테이너가 시작되지 않습니다.

    그러나 wait-for-it.sh스크립트를 사용하여 이 상황을 처리하는 더 나은 방법이 있습니다. 저는 개인적으로 Docker 컨테이너를 사용하여 애플리케이션을 마이크로서비스로 분할하는 숙련된 백엔드 개발자를 알고 있습니다. 그들은 이 스크립트 사용에 대해 긍정적인 의견을 표명했습니다. 개인적으로 시도하지는 않았지만 대체 솔루션으로 고려해 보는 것이 좋습니다.

    회신하다
    0
  • 취소회신하다