HomeLAB/Linux

[Linux]Nginx Proxy Manager(NPM)에서 DB 오류 날때 해결 방법

expbox77 2025. 1. 24. 16:24

오라클 클라우드를 사용하면서 Nginx Proxy Manager(NPM)를 잘 사용하고 있습니다. 홈랩 쪽은 OPNsense에서 HAProxy를 리버스 프록시로 사용하지만, 오라클 클라우드는 ARM에 CLI로 conf 파일을 설정해야 하는 게 좀 귀찮아서 NPM을 Docker로 설치해서 사용하고 있습니다. 올리고 싶은 서비스의 docker-compose.yaml 파일에 대충 네트워크만 맞춰주고 컨테이너 올려주고 웹에서 "딸깍" 몇 번만 하면 그리 어렵지 않게 설정할 수 있어 많은 사람들이 사용하는 리버스 프록시 프로그램입니다.

 

Let's Encrypt 인증서가 6일 이내에 만료된다는 이메일 - 현재는 해결했다.

 

NPM에서는 자동으로 인증서를 갱신하기에 딱히 신경 쓸 필요는 없습니다. 그런데 얼마 전에 Let's Encrypt 측에서 인증서가 곧 만료된다는 메일이 왔는데, 왜 이런 메일이 왔는가 싶어서 확인해 봤습니다. 확인해 보니 오랜 기간 도커 이미지의 업데이트를 못해서 컨테이너 내부에 Certbot 패키지 버전을 사용할 수 없게 되면서 인증서를 재발급받을 수 없게 되는 것이 원인인 것으로 결론을 내렸습니다. 그런데 작년에 최신 버전으로 업데이트를 시도했다가 DB 오류로 실패하고 원복 했는데, 이제 인증서를 갱신하지 못하면 잘 돌아가던 서비스를 전부 사용할 수 없게 되니 어쩔 수 없이 업데이트를 미룰 수 없게 되었습니다.

 

그 시도 중에 하나를 해결하면 문제가 하나 생겨서 2가지 문제를 해결했다. 검색해 보니까 선발대가 Github에 잘 정리해 놔서 생각보다 빠르게 해결할 수 있었습니다.


0. 시스템 사양

오라클 클라우드 Ampere A1

CPU: ARM 4 Core vCPU

RAM: 24GB

OS: Ubuntu 22.04 LTS

 

1. 기존의 NPM의 docker-compose.yaml 구성

NPM은 역사와 전통의 X86 시스템뿐만이 아니라 ARM 시스템도 지원합니다. yaml 파일이 좀 길어서 접어놨는데 잘못된 파일이라서 볼 필요는 없습니다. 나중에 수정된 yaml 파일이 나오니 이 부분은 구경만 하시면 되겠습니다.

 

NPM 서비스는 메인 NPM과 MariaDB로 구동됩니다.

더보기
version: "3.1"
services:
  npm:
    image: 'jc21/nginx-proxy-manager:${NPM_VERSION}'
    container_name: NPM_main
    restart: unless-stopped
    ports:
      - '80:80'            # http
      - '443:443'          # https
      - '81:81'            # management page
    environment:
      DB_MYSQL_HOST: "npm_db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: ${NPM_USER}
      DB_MYSQL_PASSWORD: ${NPM_PASSWD}
      DB_MYSQL_NAME: ${NPM_DBNAME}
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    networks:
      - artemis_net
      - npm_net
    depends_on:
      - npm_db

  npm_db:
    image: 'jc21/mariadb-aria:${DB_VERSION}'
    container_name: NPM_DB
    tty: true
    expose:
      - 3306
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${NPM_ROOT_PASSWD}
      MYSQL_DATABASE: ${NPM_DBNAME}
      MYSQL_USER: ${NPM_USER}
      MYSQL_PASSWORD: ${NPM_PASSWD}
      MARIADB_AUTO_UPGRADE: 1
    volumes:
      - ./data/mysql:/var/lib/mysql
    networks:
      - npm_net

networks:
  artemis_net:
    external: true
  npm_net:
    external: true

 

.env 파일에 나머지 구성을 저장했습니다.

 

2. 문제 상황 해결 방법

1) npm 'Can\'t create table `NPM_DB`.`migrations`

기존의 yaml 파일에서 NPM과 MariaDB의 버전을 최신 버전으로 업데이트하기 위해 버전 부분만 "latest"로 지정하고 docker copmose pull && docker compose up으로 도커 컨테이너를 실행했을 때 만난 문제입니다. 상세 내역은 아래의 이미지를 참고해 주세요.

 

 

이런 로그가 NPM에서 나타나게 되는데, 이 오류는 NPM 웹은 열리나 제대로 된 인증 정보를 넣더라도 로그인이 불가능한 문제가 생깁니다. DB를 마이그레이션 할 수 없는 문제인 것으로 파악했습니다. 해결 방법을 찾아보니 이 부분은 DB가 버전 마이그레이션을 못하는 게 아니라 DB 파일에 대한 권한 문제인 것이라며 권한을 컨테이너 내부에서 수정하는 방법을 사용했습니다.

 

하지만 그 방법을 사용한 결과 해결은 했으나 컨테이너를 새로 시작하는 순간 문제가 다시 발생했습니다. 그래서 해결 방법에 관해서 좀 더 살펴본 결과 아예 DB 디렉터리를 NPM 디렉터리에서 분리해야 한다고 했습니다. 즉, 제 docker-compose.yaml 파일에는 NPM 컨테이너에 할당되어 있는 디렉터리 경로 내부에 DB 컨테이너의 디렉터리가 포함되어 있었고 DB 컨테이너가 실행되면서 DB 파일의 권한을 수정한다고 해도 depends_on으로 NPM이 다시 그 DB 파일의 권한을 수정해 버렸던 것으로 보입니다.

 

제가 예전에 어떤 글을 참고해서 docker-compose.yaml 파일을 작성했는지는 잘 모르겠지만, 혹시나 싶어 확인해 본 공식 문서에서는 확실히 분리가 되어있었습니다. 아마 그때 당시에는 잘 되었으니 그냥 사용한 것으로 보입니다.

 

해결 방법은 그리 어렵지 않습니다. 

https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1499#issuecomment-1494593464

NPM 컨테이너에 할당되어 있던 디렉터리 내부에 DB 컨테이너에 할당된 디렉터리가 있는데 그 디렉터리를 외부로 이동시키고 docker-compose.yaml에서도 그 부분을 수정해 줬습니다.

 

디렉터리 이동

# 도커 컨테이너에서 생성된 디렉터리라서 root 권한으로 실행해야함.
sudo mv data/mysql ./

 

NPM 컨테이너 볼륨 할당

   volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

 

MariaDB 컨테이너 볼륨

    volumes:
      - ./mysql:/var/lib/mysql

 

2) npm Incorrect definition of table mysql.column_stats: expected column 'hist_type' at position 9 to have type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB'), found type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB').

DB 파일의 권한 문제를 해결했지만 아직 문제는 남아있었습니다. 로그인은 잘 되나 로그인할 때 DB에 로그가 쌓이기 시작했습니다. 상세 내역은 아래 이미지를 참고해 주세요.

 

 

이런 로그가 DB에서 나타나게 되는데, 이 오류는 작동 자체는 제대로 되는데 로그인할 때마다 로그가 계속 쌓이게 되는 부분도 있고 억지로 돌아가는 느낌이라 더 큰 문제가 생기기 전에 잡으면 좋을 것 같았습니다. 해결 방법을 찾아보니 DB 버전이 꽤나 구버전이라 그런지 DB를 수동으로 업그레이드시켜줘야 하는 것으로 보입니다.

 

해결 방법은 어렵지 않습니다.

https://github.com/NginxProxyManager/nginx-proxy-manager/issues/3428#issuecomment-1885421270

실행되어 있는 DB 컨테이너에 명령어를 날려서 DB를 수동으로 업그레이드시키면 됩니다.

 

DB는 중요하니까 꼭 백업을 해놔야 합니다.

# DB는 중요하니까 꼭 백업을 해놓고 시도하세요.
# 명령어
docker exec -it [DB 컨테이너의 이름] mysql_upgrade -u root -p [DB 이름]

# 제 시스템의 경우
docker exec -it NPM_DB mysql_upgrade -u root -p npm_db

 

3. 결론

제가 겪었던 문제의 경우에는 대부분 DB에 관련된 문제였습니다. 이 부분을 좀 더 잘 살피고 제대로 했다면 좋았을 텐데 해결 방법을 찾기가 그리 어렵지 않았고 해결이 100% 안 되는 경우도 가끔 있는데 이 문제는 완전하게 해결할 수 있어서 다행이었습니다.

 

최종 수정된 docker-compose.yaml 파일

더보기
version: "3.1"
services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: NPM_main
    restart: unless-stopped
    ports:
      - '80:80'            # http
      - '443:443'          # https
      - '81:81'            # management page
    environment:
      DB_MYSQL_HOST: "npm_db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: ${NPM_USER}
      DB_MYSQL_PASSWORD: ${NPM_PASSWD}
      DB_MYSQL_NAME: ${NPM_DBNAME}
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - artemis_net
      - npm_net
    depends_on:
      - npm_db

  npm_db:
    image: 'jc21/mariadb-aria:latest'
    container_name: NPM_DB
    tty: true
    expose:
      - 3306
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${NPM_ROOT_PASSWD}
      MYSQL_DATABASE: ${NPM_DBNAME}
      MYSQL_USER: ${NPM_USER}
      MYSQL_PASSWORD: ${NPM_PASSWD}
      MARIADB_AUTO_UPGRADE: 1
    volumes:
      - ./mysql:/var/lib/mysql
    networks:
      - npm_net

networks:
  artemis_net:
    external: true
  npm_net:
    external: true

 

.env 파일은 별도 작성되었습니다.

 


레퍼런스

https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1499

https://github.com/NginxProxyManager/nginx-proxy-manager/issues/3428