Alpine Linux 서버에 SSH 접속은 잘 되는데, 막상 MySQL 관련 작업(로컬/원격 접속, mysqldump, 앱 연결)이 실패하는 경우가 종종 있습니다. 이런 상황은 “SSH 문제”가 아니라 “MySQL 접근 경로/권한/바인딩/방화벽” 쪽의 설정 실수일 때가 많습니다.
아래는 가장 흔한 실수부터 순서대로 확인해서, 일단 살리고(임시) 원인을 해결한 뒤 재발을 막는 흐름으로 정리했습니다.
1) 빠른 복구(임시): 지금 당장 원인 좁히기와 우회
먼저 “SSH는 되는데 MySQL이 안 된다”를 두 갈래로 나눠보면 빨라집니다. (1) 서버 안에서 MySQL이 안 되나? (2) 서버 밖(원격)에서만 안 되나?
- 서버 내부에서 MySQL 상태 확인: 서비스가 죽어 있거나 소켓/포트가 다르면 내부도 실패합니다.
- 원격에서만 실패: bind-address, 방화벽, MySQL 계정 host/권한, TLS 요구 같은 설정이 흔한 원인입니다.
서버 내부 점검(가장 먼저)
- mysqld가 떠 있는지 확인: rc-service mariadb status (Alpine 기본은 MariaDB 패키지인 경우가 많습니다)
- 포트 리슨 확인: ss -lntp | grep 3306
- 로컬 접속 확인: mysql -uroot -p -h 127.0.0.1 (소켓 문제가 의심되면 TCP로 강제)
원격이 급하면 임시 우회(안전하게)
- SSH 터널링으로 임시 접속: 방화벽/바인딩 이슈를 건드리기 전에 우회로 원인 분리를 합니다. 로컬 PC에서 ssh -L 13306:127.0.0.1:3306 user@server 후, mysql -h 127.0.0.1 -P 13306 -u계정 -p
- 터널링으로는 되는데 원격 직결은 실패한다면, MySQL이 외부에 열려 있지 않거나(바인딩/방화벽), 계정 host 제한이 걸렸을 가능성이 큽니다.
여기까지가 “일단 업무를 진행하기 위한 임시 복구”이고, 다음부터 근본 원인으로 들어가면 됩니다.
2) 근본 해결: MySQL이 실제로 어디에 바인딩되어 있는지 확인
가장 흔한 실수는 MySQL이 127.0.0.1에만 바인딩되어 있는데 원격에서 접속하려고 시도하는 경우입니다. 반대로, 보안상 외부에 열면 안 되는데 0.0.0.0로 열어둔 상태로 방치하는 경우도 있습니다.
리슨 주소 확인: ss -lntp | grep 3306 결과에서 127.0.0.1:3306이면 로컬 전용입니다. 원격이 필요하면 정책부터 정하세요.
- 원격 접속이 필요 없다: 127.0.0.1 유지 + SSH 터널링만 허용(권장)
- 원격 접속이 꼭 필요: 특정 내부망/운영 IP만 허용 + 계정 권한/방화벽/TLS 정책까지 함께 맞춤
Alpine에서 MariaDB/MySQL 설정 파일 위치는 설치 방식에 따라 다르지만 보통 /etc/my.cnf 또는 /etc/my.cnf.d/ 아래에 있습니다. bind-address나 skip-networking 같은 옵션이 있는지 확인하세요.
설정을 바꿨다면 재시작 전후로 rc-service mariadb restart 후 다시 ss -lntp로 리슨 상태가 원하는 대로 바뀌었는지 확인합니다.
3) 근본 해결: MySQL 계정의 host 제한/권한(Grant) 실수 점검
원격 접속 문제의 두 번째로 흔한 원인은 계정이 'user'@'localhost'로만 만들어져 있거나, 접속하는 IP 대역이 Grant에 포함되지 않은 경우입니다. SSH는 되는데 MySQL 로그인만 “Access denied”로 터지는 전형적인 패턴이 여기서 나옵니다.
확인 포인트
- 같은 username이라도 'user'@'localhost'와 'user'@'10.%'는 완전히 다른 계정으로 취급됩니다.
- 앱 서버가 바뀌었는데(새 IP) 기존 Grant가 예전 IP로만 되어 있으면 바로 실패합니다.
- 원격을 열더라도 '%'는 가급적 피하고, 운영 IP/대역만 지정하는 쪽이 안전합니다.
권한을 손댄 뒤에는 FLUSH PRIVILEGES가 필요한 경우가 있지만(구버전/상황에 따라), 요즘은 GRANT/CREATE USER가 즉시 반영되는 구성이 많습니다. 그래도 혼동을 줄이려면 변경 후 재접속 테스트는 꼭 하세요.
4) 근본 해결: 방화벽(iptables/nftables)과 클라우드 보안그룹에서 3306이 막히는 경우
“서버 내부에서는 접속되는데 외부에서만 타임아웃”이면 방화벽이나 클라우드 보안그룹에서 막혔을 가능성이 큽니다. Alpine은 구성에 따라 iptables/nftables, 또는 별도 방화벽 도구를 쓰기도 합니다.
- 서버 로컬에서 포트는 열려 있는데(리슨 중) 외부에서 접속이 안 되면: 서버 방화벽 또는 클라우드 보안그룹을 의심
- 외부 개방이 필요하다면: 3306을 전체 오픈하지 말고, 운영 IP(또는 VPN 대역)만 허용
- 외부 개방이 불필요하다면: 3306은 닫고 SSH 터널/VPN만 허용하는 설계가 보통 더 안전하고 관리가 쉽습니다.
추가로, 같은 “원격”이라도 사내망에서 되는지/인터넷에서 안 되는지에 따라 보안그룹/라우팅/NAT 이슈가 갈립니다. 테스트는 한 번에 한 변수만 바꿔가며 하세요.
5) 근본 해결: SSH로 들어가서 실행하는 mysql 명령이 다른 소켓/다른 설정을 바라보는 실수
의외로 자주 나오는 케이스가 “SSH 접속 후 mysql은 실행되는데, 특정 작업만 실패”입니다. 보통 아래 중 하나입니다.
- 소켓 경로 불일치: mysql 클라이언트는 기본 소켓을 보는데, 서버 mysqld는 다른 소켓을 쓰는 경우. 이때는 -h 127.0.0.1로 TCP 접속을 강제하면 빠르게 분리됩니다.
- 권한/환경 변수 차이: root로 실행할 때와 일반 계정으로 실행할 때 홈 디렉터리의 .my.cnf, PATH가 달라서 다른 계정으로 접속 시도하는 경우
- 컨테이너/Docker 착각: mysqld가 컨테이너 안에서 돌고 있는데 호스트에서 127.0.0.1:3306으로 붙으려다 실패(또는 반대). 이 경우 “어디에서 실행 중인가”를 먼저 확정해야 합니다.
특히 Alpine에서는 패키지 구성이 간결한 대신, 운영자가 소켓/데이터 디렉터리 등을 커스텀한 상태로 남아 있는 경우가 있어 “기본값 가정”이 실패 원인이 되기도 합니다.
6) 재발 방지: 변경 전후 검증 루틴 + 최소 노출 원칙 체크리스트
한 번 복구하고 나면, 다음 장애는 “작은 변경”에서 다시 시작합니다. 아래 체크리스트를 운영 루틴으로 만들어두면 같은 유형의 장애가 크게 줄어듭니다.
- 접속 경로 정책: 원격 직결을 허용할지(최소 IP만), 아니면 SSH 터널/VPN만 허용할지 문서화
- 바인딩 검증: 변경 후 ss -lntp | grep 3306로 리슨 주소 확인(127.0.0.1인지, 특정 IP인지, 0.0.0.0인지)
- 권한 검증: 앱 서버 IP 변경/증설 시 MySQL 계정 host/권한이 함께 변경되는지 점검
- 방화벽 이중 점검: 서버 방화벽 + 클라우드 보안그룹(또는 라우터 ACL) 둘 다 확인
- 로그 위치 습관화: MariaDB/MySQL 에러 로그와 인증 실패 로그를 확인하는 경로를 팀 내에 공유
- 임시 우회 기록: SSH 터널로 우회했다면 “왜 직결이 안 됐는지” 원인 티켓을 남기고 반드시 닫기
원격 DB 접속을 꼭 열어야 한다면, 최소한 “허용 IP 제한 + 강한 인증 + 필요 시 TLS”까지 한 세트로 맞추는 게 안전합니다. 반대로 대부분의 운영에서는 DB는 내부망/로컬에 두고 SSH/VPN으로만 접근하는 구성이 단순하고 안정적입니다.
마무리
Alpine에서 SSH는 되는데 MySQL 작업이 실패하면, 먼저 “내부에서도 실패인가/원격에서만 실패인가”로 갈라서 보시면 대부분 빠르게 좁혀집니다. 그 다음은 바인딩, 권한(Grant), 방화벽 순서로 확인하는 게 가장 효율적입니다.
급할 땐 SSH 터널링으로 임시 복구하고, 이후에는 접근 정책과 체크리스트로 같은 실수를 반복하지 않게 만드는 흐름이 안정적입니다.