AD JB Toolbox 01

MariaDB 강좌 / Docker로 MariaDB 실습 환경 만들기

Docker Compose로 MariaDB 컨테이너, 접속 포트, 데이터 볼륨을 파일 하나에서 관리할 수 있습니다. 서버를 PC에 직접 설치하지 않고 분리된 실습 환경을 만들되, 컨테이너를 삭제하는 것과 데이터 볼륨을 삭제하는 것은 구분해야 합니다.

실습 범위와 준비 사항

Docker는 애플리케이션과 실행 환경을 컨테이너라는 단위로 구동하는 도구이며, Compose는 여러 실행 설정을 YAML 파일로 관리하는 기능입니다. 여기서는 MariaDB 하나만 실행하고 호스트 PC의 127.0.0.1:3307에서 연결합니다. 이미 3306 포트의 MariaDB를 사용하더라도 포트를 분리해 실습할 수 있습니다.

Docker 공식 Compose 설치 안내에 따라 Docker Engine과 Compose 플러그인 또는 Docker Desktop을 준비하세요. Windows의 Docker Desktop에서는 Linux 컨테이너를 사용합니다. 다음 명령이 모두 동작하고 Docker 엔진이 실행 중이어야 합니다.

docker version
docker compose version

이 예제는 mariadb:11.8 이미지 계열을 명시합니다. 이 태그는 같은 계열의 패치 이미지로 바뀔 수 있으므로 엄밀하게 재현하려면 검증한 패치 태그나 이미지 다이제스트를 기록하세요. 로컬 검증에서는 Compose YAML과 아래 SQL을 확인했으며, Docker 이미지 실행과 볼륨 유지 실험은 별도의 Docker 환경에서 확인할 항목입니다.

작업 폴더와 암호 파일 만들기

  1. 새 작업 폴더 mariadb-appops를 만들고 그 안에서 터미널을 엽니다. 다른 Compose 프로젝트의 폴더에서 실행하지 마세요.
  2. 하위 폴더 secrets에 root-password.txt와 app-password.txt를 만듭니다. 각각 서로 다른 실습용 암호 한 줄을 UTF-8 형식으로 저장하고 빈 파일이나 설명 문구를 넣지 않습니다.
  3. 같은 작업 폴더에 아래 compose.yaml과 .gitignore를 저장합니다. 암호 파일은 저장소에 올리지 않고 파일 접근 권한으로 보호합니다.
secrets/
.env

위 두 줄은 .gitignore 내용입니다. Compose secrets는 파일을 서비스에 전달하는 방식이며, 로컬 암호 파일을 자동으로 암호화하는 금고가 아닙니다. 파일과 Docker 접근 권한 자체도 관리해야 합니다. Compose secrets의 동작과 지원 범위에서 Linux 컨테이너 조건과 파일 마운트 방식을 확인할 수 있습니다.

Compose 파일의 연결 관계 이해하기

name: mariadb-appops
services:
  db:
    image: mariadb:11.8
    ports:
      - "127.0.0.1:3307:3306"
    environment:
      MARIADB_ROOT_PASSWORD_FILE: /run/secrets/root_password
      MARIADB_DATABASE: appops_lab
      MARIADB_USER: app_user
      MARIADB_PASSWORD_FILE: /run/secrets/app_password
    secrets:
      - root_password
      - app_password
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
secrets:
  root_password:
    file: ./secrets/root-password.txt
  app_password:
    file: ./secrets/app-password.txt
volumes:
  db_data:

호스트 포트는 3307, 컨테이너 내부 포트는 3306입니다. PC에서 연결할 때는 127.0.0.1:3307을 쓰지만 같은 Compose 네트워크의 다른 서비스에서는 db:3306으로 연결합니다. 127.0.0.1 바인딩은 이 실습 포트를 외부 네트워크에 직접 공개하지 않도록 범위를 제한합니다.

db_data는 데이터 디렉터리를 보관하는 이름 있는 볼륨입니다. 암호는 _FILE 환경 변수가 가리키는 파일에서 읽습니다. 공식 이미지 환경 변수 설명에 따르면 초기 데이터베이스·사용자·암호 설정은 빈 데이터 디렉터리를 초기화할 때 적용됩니다. 이미 데이터가 있는 볼륨에서 암호 파일만 고쳐도 기존 계정의 암호가 변경되지는 않습니다.

헬스체크는 공식 healthcheck.sh로 연결 가능 여부와 InnoDB 초기화 상태를 확인합니다. 컨테이너가 단순히 실행 중인 상태와 데이터베이스가 요청을 받을 준비가 된 상태를 구분하기 위한 설정입니다.

시작하고 실제 데이터가 저장되는지 확인하기

docker compose config --quiet
docker compose up -d
docker compose ps
docker compose logs --tail=80 db

config --quiet는 설정을 검사하며, ps에서 서비스가 실행되고 healthy가 되는지 확인합니다. 초기화가 끝나지 않았다면 로그를 먼저 읽고 기다립니다. 암호 파일이 없거나 포트가 이미 사용 중이면 해당 경로·포트를 수정한 뒤 다시 실행하세요.

docker compose exec db mariadb --default-character-set=utf8mb4 -u app_user -p appops_lab

암호 입력창에서 app-password.txt의 값을 입력합니다. 다음 SQL을 클라이언트에서 실행하면 한 행이 조회됩니다. CREATE TABLE은 첫 실행용이므로 같은 테이블이 이미 있으면 먼저 기존 실습 결과를 조회하고 중복 실행 여부를 판단하세요.

USE appops_lab;
CREATE TABLE docker_notes (
  note_id INT NOT NULL PRIMARY KEY,
  note_text VARCHAR(80) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO docker_notes VALUES (1, 'volume survives container replacement');
SELECT note_id, note_text FROM docker_notes;

PC에 별도의 MariaDB 클라이언트가 있다면 아래 명령으로 같은 데이터를 조회할 수도 있습니다. 컨테이너 안에서 쓴 포트 3306을 호스트 연결에 그대로 쓰면 다른 서버로 연결할 수 있습니다.

mariadb --protocol=tcp --host=127.0.0.1 --port=3307 --default-character-set=utf8mb4 -u app_user -p appops_lab

컨테이너 교체와 데이터 초기화를 구분하기

docker compose down
docker compose up -d

기본 down은 컨테이너와 프로젝트 네트워크를 정리하지만 이 예제의 이름 있는 볼륨은 남깁니다. 다시 healthy가 된 뒤 같은 계정으로 접속해 SELECT * FROM docker_notes;를 실행하고 앞의 행이 남아 있는지 확인하세요. 이 확인이 컨테이너 교체 후 데이터 유지 여부를 보여 줍니다.

docker compose down --volumes는 이름 있는 볼륨도 제거하여 데이터가 사라질 수 있습니다. 재시작 명령으로 사용하지 말고, 해당 실습 프로젝트의 데이터를 모두 버리기로 확인한 경우에만 실행합니다. 볼륨은 백업을 대신하지 않으므로 필요한 데이터는 데이터베이스 백업 절차에 따라 별도로 보관하세요. Compose down의 삭제 범위도 함께 확인할 수 있습니다.

접속 실패를 원인별로 좁히기

증상 확인할 항목
Docker 엔진에 연결하지 못함 Docker Desktop 또는 Docker Engine 실행 상태와 현재 Docker context
포트 충돌 호스트 3307 사용 여부. 변경하면 PC 클라이언트의 포트도 함께 변경
Access denied 실제 초기화에 사용된 계정·암호와 기존 볼륨 여부. 암호 파일 수정만으로 초기화되지 않음
컨테이너는 실행되지만 연결 실패 health 상태, 초기화 로그, 서비스 이름 db와 호스트 127.0.0.1의 구분
재생성 후 다른 데이터가 보임 프로젝트 이름 mariadb-appops, 작업 폴더, 연결 포트와 마운트한 볼륨

문제를 해결하려고 볼륨을 먼저 삭제하지 마세요. 어느 서버와 어느 데이터 디렉터리에 연결했는지 확인한 뒤, 설정 수정으로 해결할 문제인지 데이터를 새로 초기화할 상황인지 구분하면 실습 결과를 보존할 수 있습니다.

같은 카테고리의 다른 글
MariaDB 강좌 / 데이터베이스 만들기: CREATE DATABASE·USE·문자 집합

MariaDB 강좌 / 데이터베이스 만들기: CREATE DATABASE·USE·문자 집합

shopcourse 데이터베이스를 만들고 현재 연결의 작업 대상으로 선택합니다. utf8mb4와 collation, 기존 DB에서 IF NOT EXISTS의 한계, 권한·문자 설정 확인을 예제로 설명합니다.

MariaDB / VIEW

MariaDB / VIEW

VIEW는 가상의 테이블입니다. 실제로 데이터를 저장하지 않고, 기존의 하나 이상의 테이블을 기반으로 한 쿼리 결과를 테이블처럼 사용할 수 있게 해줍니다. 뷰는 복잡한 쿼리를 단순화하고, 보안 및 데이터 관리에 유용하게 사용됩니다.

MariaDB 강좌 / 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품

MariaDB 강좌 / 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품

월별 paid 매출, 미구매 포함 고객별 구매 금액, 미판매 상품 조회를 종합 실습합니다. 주문·상세 단위와 취소 정책을 정하고 세 결과의 전체 금액을 교차 검증합니다.

MariaDB 강좌 / 이벤트 스케줄러로 정기 작업 실행하고 결과 확인하기

MariaDB 강좌 / 이벤트 스케줄러로 정기 작업 실행하고 결과 확인하기

비활성 일회성 이벤트를 생성한 뒤 미래 시각으로 활성화하고 결과 행과 예약 메타정보를 대조합니다. 반복 작업의 중복·겹침 위험, 권한·시간대 점검과 안전한 중지·정리 방법도 설명합니다.

MariaDB 강좌 / 테이블 관계 설계하기: 일대다·다대다·외래키

MariaDB 강좌 / 테이블 관계 설계하기: 일대다·다대다·외래키

고객·상품·주문·상세 네 테이블로 일대다와 다대다 관계를 설계합니다. 복합키·주문 당시 단가·외래키 실패 입력과 삭제 제한을 실행하고 업무상 삭제 정책을 구분합니다.

MariaDB 강좌 / 중복 데이터를 줄이는 정규화와 주문 데이터베이스 설계

MariaDB 강좌 / 중복 데이터를 줄이는 정규화와 주문 데이터베이스 설계

주문 상세에 반복한 고객 정보의 변경 오류를 관찰하고 키별 사실을 네 테이블로 나눕니다. 부분·이행 종속, 거래 당시 단가와 스냅샷 보존, 무결성 제약과 성능의 별도 검토를 설명합니다.

MariaDB 강좌 / 사용자 계정 만들고 필요한 권한만 부여하기

MariaDB 강좌 / 사용자 계정 만들고 필요한 권한만 부여하기

사용자·호스트 조합을 확인하고 상품 한 테이블의 SELECT만 허용하는 계정을 만듭니다. 새 연결의 허용·거절 시험, 권한 회수와 기존 계정을 덮어쓰지 않는 정리 절차를 설명합니다.

MariaDB 강좌 / 두 연결로 격리 수준·잠금·교착 상태 확인하기

MariaDB 강좌 / 두 연결로 격리 수준·잠금·교착 상태 확인하기

별도 연결 두 개로 REPEATABLE READ·READ COMMITTED, 행 잠금 대기와 교착 상태를 비교합니다. 실행 순서, 예상 읽기 값, 실패 후 전체 트랜잭션 정리와 연결별 설정 복원을 안내합니다.

MariaDB 강좌 / WITH로 공통 테이블 식 만들고 쿼리 나누기

MariaDB 강좌 / WITH로 공통 테이블 식 만들고 쿼리 나누기

WITH의 공통 테이블 식으로 결제 주문·주문별 합계·고객 연결을 단계별로 나눕니다. 중간 결과 검증, 한 문장 안의 유효 범위와 성능을 자동 보장하지 않는 이유를 설명합니다.

MariaDB 강좌 / INNER JOIN으로 서로 연결된 데이터 조회하기

MariaDB 강좌 / INNER JOIN으로 서로 연결된 데이터 조회하기

고객과 주문을 INNER JOIN으로 연결하고 결과 한 행의 의미를 확인합니다. ON과 WHERE, 테이블 별칭, 일대다로 늘어나는 행과 조건 없는 곱집합을 비교합니다.