[카테고리:] IT

  • [Synology NAS] Docker Compose로 가볍고 빠른 WordPress 구축하기 (feat. MariaDB + Redis)

    시놀로지 NAS(DSM)의 패키지 센터에서 제공하는 공식 WordPress 패키지는 간편하지만, 버전 업데이트가 느리고 데이터 격리나 성능 튜닝(Redis 캐싱 등)에 제약이 많습니다.

    이번 포스팅에서는 Docker Compose를 이용해 가볍고 빠른 WordPress 구동 환경을 구축하는 전체 과정을 단계별로 정리합니다. 특히 컨테이너 환경에서 빈번하게 발생하는 디렉터리 권한(Permission Denied) 이슈와 DB 연결 실패 트러블슈팅 경험까지 함께 다룹니다.


    구성 환경 요약

    • Host: Synology NAS (DSM 7.x)
    • Storage: NVMe SSD 볼륨 (/volume2/Docker2_Nvme/wordpress)
    • Services:
      • WordPress: 최신 공식 Apache/PHP 이미지
      • MariaDB: 11.x
      • Redis: 7.x (Object Cache 가속용)

    1단계: 프로젝트 디렉터리 생성 및 권한 설정

    도커 컨테이너가 호스트 볼륨의 데이터를 정상적으로 읽고 쓸 수 있도록 디렉터리를 생성하고 소유권을 미리 지정해야 합니다.

    1. 작업 디렉터리 생성

    SSH 터미널에서 아래 명령어로 프로젝트 및 영구 데이터(Data Persistence) 저장 폴더를 만듭니다.

    mkdir -p /volume2/Docker2_Nvme/wordpress/wp-data
    mkdir -p /volume2/Docker2_Nvme/wordpress/db-data
    cd /volume2/Docker2_Nvme/wordpress

    2. 권한(UID/GID) 사전 지정

    도커 컨테이너 내부의 프로세스는 호스트와 서로 다른 UID로 실행됩니다. 사전 권한 작업 없이 컨테이너를 올리면 Permission Denied로 MariaDB가 부팅되지 않거나 워드프레스가 설정 파일을 쓰지 못합니다.

    실제로 권한 사전 지정 없이 Docker Compose로 컨테이너 실행 시 DB권한 부족 문제로 무한 재시작 루프에 빠졌습니다.

    • MariaDB 컨테이너: 내부 mysql 사용자의 기본 UID는 999
    • WordPress 컨테이너: 내부 웹서버 www-data의 기본 UID는 33
    # MariaDB 데이터 폴더 소유권 (UID 999)
    sudo chown -R 999:999 db-data
    sudo chmod -R 775 db-data
    
    # WordPress 데이터 폴더 소유권 (UID 33)
    sudo chown -R 33:33 wp-data
    sudo chmod -R 775 wp-data

    2단계: docker-compose.yml 작성

    프로젝트 디렉터리 내에 Compose 정의 파일을 작성합니다.

    sudo vi docker-compose.yml

    아래 설정을 복사하여 Docker-compos.yml로 생성합니다. (※ YOUR_SECURE_PASSWORD 부분은 본인만의 안전한 비밀번호로 변경하세요.)

    version: '3.8'
    
    services:
      mariadb:
        image: mariadb:11.4
        container_name: wp-mariadb
        restart: unless-stopped
        environment:
          MYSQL_ROOT_PASSWORD: "YOUR_SECURE_ROOT_PASSWORD"
          MYSQL_DATABASE: "wordpress"
          MYSQL_USER: "wpuser"
          MYSQL_PASSWORD: "YOUR_SECURE_PASSWORD"
        volumes:
          - ./db-data:/var/lib/mysql
        networks:
          - wp-net
    
      redis:
        image: redis:7-alpine
        container_name: wp-redis
        restart: unless-stopped
        command: redis-server --appendonly yes
        networks:
          - wp-net
    
      wordpress:
        image: wordpress:latest
        container_name: wp-app
        restart: unless-stopped
        depends_on:
          - mariadb
          - redis
        ports:
          - "8080:80"  # 외부 노출 포트 (리버스 프록시 또는 터널 연결용)
        environment:
          WORDPRESS_DB_HOST: "mariadb:3306"
          WORDPRESS_DB_USER: "wpuser"
          WORDPRESS_DB_PASSWORD: "YOUR_SECURE_PASSWORD"
          WORDPRESS_DB_NAME: "wordpress"
          WORDPRESS_CONFIG_EXTRA: |
            define('WP_REDIS_HOST', 'redis');
            define('WP_REDIS_PORT', 6379);
        volumes:
          - ./wp-data:/var/www/html
        networks:
          - wp-net
    
    networks:
      wp-net:
        driver: bridge

    3단계: 컨테이너 실행 및 초기화 검증

    작성이 끝났으면 백그라운드로 스택을 올립니다.

    sudo docker compose up -d

    컨테이너 상태 점검

    컨테이너 3개가 정상 가동 중인지 확인합니다.

    sudo docker compose ps
    • 만약 wp-mariadb가 계속 재시작(Restarting)된다면 1단계의 db-data 폴더 소유권(999:999)을 다시 점검해야 합니다.

    4단계: 역프록시/Cloudflare 환경 대비 wp-config.php 보완

    Cloudflare Tunnel이나 Synology Reverse Proxy를 거쳐 SSL(HTTPS)을 종단할 경우, 워드프레스가 HTTPS 접속임을 감지하지 못해 **무한 리다이렉트(Too many redirects)**가 발생할 수 있습니다.

    워드프레스 컨테이너가 구동된 후, 생성된 wp-config.php 파일을 열어 헤더 인식 코드를 확인/추가합니다.

    sudo vi /volume2/Docker2_Nvme/wordpress/wp-data/wp-config.php

    파일 상단의 <?php 바로 아랫줄에 다음 코드를 명시합니다:

    /* Cloudflare / Reverse Proxy HTTPS 감지 */
    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
    }

    저장 후 소유권을 다시 확인합니다:

    sudo chown 33:33 /volume2/Docker2_Nvme/wordpress/wp-data/wp-config.php

    5단계: 워드프레스 초기 설정 마법사 진행

    브라우저에서 http://[NAS_IP]:8080 (또는 연결해 둔 도메인 주소)로 접속합니다.

    1. 언어 선택: 한국어 (또는 원하는 언어) 선택 후 계속
    2. 사이트 정보 입력:
      • 사이트 제목: 블로그 이름
      • 사용자명(ID): 관리자 로그인 ID (admin과 같은 흔한 ID 지양)
      • 비밀번호: 안전한 비밀번호 입력
      • 이메일 주소: 비밀번호 분실 시 안내받을 메일
      • 검색엔진 가시성: 세팅 기간 동안 구글 노출을 미루고 싶다면 “차단” 체크 (오픈 시 설정에서 해제 가능)
    3. [워드프레스 설치] 클릭 $\rightarrow$ 관리자 로그인

    6단계: 성능 최적화 – Redis Object Cache 활성화

    컨테이너로 함께 띄운 Redis를 워드프레스와 연동하여 DB 쿼리 부하를 줄여줍니다.

    1. 워드프레스 관리자 화면 $\rightarrow$ 플러그인 $\rightarrow$ 새로 추가
    2. 검색창에 Redis Object Cache 검색 후 지금 설치 $\rightarrow$ 활성화
    3. 좌측 메뉴 설정 $\rightarrow$ Redis 이동
    4. 이미 wp-config.php에 호스트 정보가 전달되어 있으므로, [Enable Object Cache] 버튼을 클릭합니다.
    5. 상태 표시창에 Status: Connected가 뜨면 모든 DB 쿼리 캐싱이 메모리에서 초고속으로 작동합니다.

    마치며

    이로써 시놀로지 NAS 위에 격리되고 성능 최적화까지 마친 워드프레스 인프라가 완성되었습니다.

    지금 이 블로그의 첫 글이죠.

    여하튼 현재 상태로 인터넷에 그대로 노출하면 /wp-admin이나 /wp-login.php로 전 세계 봇들의 무차별 대입 공격(Brute Force)이 쏟아지게 됩니다.

    다음 글에서는 포트포워딩 없이 Cloudflare Tunnel을 연결하고, Cloudflare Zero Trust Access를 통해 관리자 페이지만 본인 인증으로 완벽하게 격리하는 방법을 다루겠습니다.