본문 바로가기

기초 튼튼/시행착오노트

[에러해결] ec2에서 docker-compose로 mysql 기동시 기존 유져 기존재 해결

증상

  • 에러 메시지:
    pgsql
    복사
    ERROR 1396 (HY000) at line 1: Operation CREATE USER failed for 'cheston'@'%'
  • 컨테이너 로그:
    MySQL 컨테이너 로그에 사용자 생성 에러가 나타남.
  • 수동으로 MySQL 접속 후:
    수동으로 접속해서 drop user 'cheston'@'%'; 명령어를 실행하면 정상적으로 삭제됨.

원인

  1. Persistent 볼륨에 남은 이전 데이터:
    • MySQL 데이터를 저장하는 Docker 볼륨에 이미 'cheston'@'%' 사용자가 생성되어 있었기 때문에, 컨테이너가 재시작될 때 초기화 스크립트에서 다시 사용자를 생성하려고 하면 충돌이 발생함.
  2. MySQL 기동 타이밍 문제:
    • 스크립트가 MySQL 데몬을 시작한 직후에 바로 사용자 관련 명령어를 실행하는 경우, MySQL이 완전히 기동되기 전에 명령이 실행되어 내부 상태가 불안정할 수 있음.
    • 이로 인해 DROP USER IF EXISTS 명령이 정상 동작하지 않거나, 이미 존재하는 사용자에 대해 오류가 발생할 가능성이 있음.
  3. 스크립트 중복 실행 문제:
    • 컨테이너가 재시작되거나 초기화 스크립트가 여러 번 실행되면서 이미 존재하는 사용자에 대해 다시 생성 명령이 실행될 때 에러가 발생함.

해결 방안

  1. Persistent 볼륨 초기화 (데이터 초기화가 가능할 경우):
    • 기존 데이터(사용자 정보)를 삭제하고 새로 초기화하는 방법입니다.
    bash
    복사
    docker-compose down -v docker-compose up -d
    • 이렇게 하면 새로운 볼륨이 생성되어 MySQL 초기화 스크립트가 깨끗한 상태에서 실행됩니다.
  2. MySQL 기동 완료 후 스크립트 실행:
    • MySQL이 완전히 시작되기 전에 사용자 생성 명령어가 실행되지 않도록, mysqladmin ping 등을 사용하여 MySQL이 준비될 때까지 대기하는 로직을 스크립트에 추가합니다.
    • 예를 들어:
      bash
      복사
      #!/bin/bash service mysql start # 최대 30초간 MySQL 기동 대기 timeout=30 until mysqladmin ping --silent; do sleep 1 timeout=$((timeout - 1)) if [ $timeout -le 0 ]; then echo "MySQL did not start in time." exit 1 fi done if [ -n "${MYSQL_USER}" ]; then mysql -uroot -e "DROP USER IF EXISTS '${MYSQL_USER}'@'%';" mysql -uroot -e "CREATE USER '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';" mysql -uroot -e "GRANT ALL PRIVILEGES ON *.* TO '${MYSQL_USER}'@'%';" mysql -uroot -e "FLUSH PRIVILEGES;" fi sleep infinity
    • 이 방식은 MySQL이 완전히 준비된 후에 사용자 관련 명령어를 실행하여 타이밍 문제를 방지합니다.
  3. 명령어 안전하게 사용하기:
    • MySQL 8.0 이상에서는 CREATE USER IF NOT EXISTS ... 구문을 사용할 수 있으므로, 이를 사용해도 좋습니다.
    • 그러나 이미 존재하는 사용자를 명시적으로 제거하는 방식(DROP 후 CREATE)이 보다 명확한 경우도 있습니다.

결론

  • 문제 요약:
    Persistent 볼륨에 남은 이전 사용자 데이터와 MySQL 기동 타이밍 문제로 인해, 스크립트 내에서 'cheston'@'%' 사용자 삭제 및 재생성이 제대로 처리되지 않아 ERROR 1396 에러가 발생했습니다.
  • 해결 방법:
    1. 필요에 따라 기존 볼륨을 초기화하여 깨끗한 상태에서 시작하거나,
    2. MySQL이 완전히 기동된 후에 사용자 삭제 및 생성 명령어가 실행되도록 스크립트에 대기 로직을 추가하는 방법으로 문제를 해결할 수 있습니다.

수동으로 MySQL 접속 후 사용자를 삭제하면 성공한 것으로 보아, 볼륨의 기존 데이터가 문제였던 것으로 판단됩니다. 이 점과 MySQL 기동 타이밍을 고려하여 스크립트를 개선하면 정상적으로 동작할 것입니다.

반응형