[Docker] Docker로 CRUD 게시판 만들어보기 1편 - Flask 게시판을 컨테이너로 실행하기
앞에서는 Docker의 이미지, 컨테이너, Dockerfile 같은 기본 개념을 살펴봤다.이번에는 지금까지 공부한 내용을 실제로 써보기 위해 간단한 CRUD 게시판을 Docker로 실행해보자.이번 실습에서는 다음 기
daniellee09.tistory.com
이전 글에서는 Flask와 SQLite로 간단한 CRUD 게시판을 만들고 Docker 컨테이너에서 실행해봤다.
전체 구조는 다음과 같았다.
app.py
│
↓
Dockerfile
│
↓
Docker Image
│
↓
Container
게시판은 정상적으로 실행됐지만 문제가 하나 있었다.
SQLite 데이터베이스 파일이 컨테이너 내부에 저장되고 있었다.
Container
│
└─ /data
└─ board.db
따라서 컨테이너를 삭제하면 게시글 데이터도 함께 사라졌다.
이번에는 Docker의 Volume과 Bind Mount를 이용해서 이 문제를 해결해보자.

1. 왜 Volume이 필요할까?
컨테이너는 영구적으로 사용하는 공간이라기보다 언제든 새로 만들고 삭제할 수 있는 실행 환경에 가깝다.
예를 들어 컨테이너를 삭제하면
docker rm -f board-container
컨테이너 내부의 데이터도 함께 사라진다.
Container
│
└─ board.db
↓ 삭제
Container 없음
board.db 없음
하지만 게시판의 게시글이나 데이터베이스 같은 데이터는 컨테이너가 사라져도 유지되어야 한다.
그래서 데이터를 컨테이너 외부에 따로 저장해야 한다.
이때 사용할 수 있는 것이 Docker Volume이다.
2. Docker Volume 만들기
먼저 Volume을 하나 만든다.
docker volume create board-data
만들어진 Volume은 다음 명령어로 확인한다.
docker volume ls
대략 다음과 같이 나타난다.
DRIVER VOLUME NAME
local board-data
board-data라는 Docker 전용 저장 공간이 만들어진 것이다.
3. Volume을 컨테이너에 연결하기
이제 컨테이너를 실행하면서 Volume을 연결한다.
docker run -d \
--name board-container \
-p 5000:5000 \
-v board-data:/data \
docker-board
핵심은 다음 부분이다.
-v board-data:/data
형식은 다음과 같다.
-v Volume이름:컨테이너경로
따라서
board-data
│
│ Volume Mount
↓
Container
/data
구조가 된다.
SQLite는 /data/board.db에 데이터를 저장하도록 만들어놨기 때문에 실제 데이터는 Volume에 보관된다.
Docker Volume
board-data
│
└─ board.db
4. 컨테이너를 삭제해보자
이제 게시글을 몇 개 작성한다.
그리고 컨테이너를 삭제한다.
docker rm -f board-container
컨테이너는 사라진다.
하지만 Volume은 삭제되지 않는다.
Container
→ 삭제
board-data Volume
└─ board.db
→ 유지
다시 같은 Volume을 사용해서 컨테이너를 실행해보자.
docker run -d \
--name board-container \
-p 5000:5000 \
-v board-data:/data \
docker-board
브라우저에서 게시판을 다시 열면 이전 게시글이 그대로 남아 있는 것을 확인할 수 있다.
즉 컨테이너와 데이터의 생명주기를 분리한 것이다.
Container
→ 삭제하고 다시 생성 가능
Volume
→ 데이터 계속 유지
이게 Docker에서 Volume을 사용하는 가장 대표적인 이유다.
5. 전체 구조로 보면
현재 게시판 구조는 다음과 같다.
Host PC
│
└─ Docker
│
├─ board-container
│ │
│ └─ /data
│ │
│ │ Volume Mount
│ ↓
│
└─ board-data
│
└─ board.db
컨테이너는 프로그램을 실행하고,
Volume은 데이터를 저장한다.
역할이 분리된 셈이다.
6. 개발할 때 또 다른 문제가 있다
Volume을 사용해서 데이터 문제는 해결했다.
그런데 개발 과정에서는 또 다른 불편함이 있다.
app.py를 수정했다고 해보자.
현재 구조에서는 코드가 Docker 이미지 안에 복사되어 있다.
COPY app.py .
따라서 코드가 바뀌면 다음 과정을 다시 해야 한다.
app.py 수정
↓
docker build
↓
새 Image 생성
↓
Container 다시 실행
개발 중에 코드 한 줄 수정할 때마다 이미지를 다시 만드는 건 상당히 번거롭다.
이럴 때 사용할 수 있는 것이 Bind Mount다.
7. Bind Mount 사용하기
Bind Mount는 내 컴퓨터의 파일이나 디렉터리를 컨테이너 내부에 직접 연결하는 방식이다.
예를 들어 현재 프로젝트가 다음과 같다고 해보자.
Host PC
board/
├─ app.py
├─ requirements.txt
└─ Dockerfile
여기 있는 app.py를 컨테이너의 /app/app.py와 연결할 수 있다.
Linux나 macOS에서는 다음처럼 실행할 수 있다.
docker run -d \
--name board-container \
-p 5000:5000 \
-v "$(pwd)/app.py:/app/app.py" \
-v board-data:/data \
docker-board
여기에서는 -v가 두 번 사용됐다.
첫 번째는 Bind Mount다.
-v "$(pwd)/app.py:/app/app.py"
두 번째는 Docker Volume이다.
-v board-data:/data
8. 구조로 보면 더 쉽다
전체 구조는 다음과 같다.
Host PC
board/
└─ app.py
│
│ Bind Mount
↓
Container
/app/app.py
Docker Volume
board-data
│
│ Volume Mount
↓
Container
/data
└─ board.db
즉 하나의 컨테이너에서 Bind Mount와 Volume을 동시에 사용할 수 있다.
9. 각각 어떤 역할을 하고 있을까?
현재 구조에서는 용도가 명확하게 나뉜다.
app.py
→ Bind Mount
board.db
→ Volume
Bind Mount는 개발 중인 소스 코드를 연결한다.
내 컴퓨터에서 app.py 수정
↓
컨테이너에도 바로 반영
Volume은 데이터베이스 데이터를 저장한다.
Container 삭제
↓
Volume 유지
↓
게시판 데이터 유지
그래서 처음 Docker를 공부할 때는 다음처럼 이해하면 쉽다.
소스 코드는 Bind Mount, 데이터는 Volume
반드시 이렇게 사용해야 하는 것은 아니지만 개발 환경에서는 꽤 자연스러운 구조다.
10. Volume과 Bind Mount 비교
두 방식을 다시 비교해보자.
구분VolumeBind Mount
| 관리 주체 | Docker | 사용자 |
| 저장 위치 | Docker가 관리 | 사용자가 직접 지정 |
| 대표 용도 | DB 데이터 | 소스 코드 |
| 호스트 경로 의존성 | 낮음 | 높음 |
| 컨테이너 삭제 시 | 유지 가능 | 호스트 파일 그대로 유지 |
| 개발 환경 | 사용 가능 | 자주 사용 |
| 운영 환경 | 자주 사용 | 상황에 따라 사용 |
핵심적인 차이는 어디에 있는 데이터를 연결하는가다.
Volume
→ Docker가 만든 저장 공간 연결
Bind Mount
→ 내 컴퓨터의 파일 또는 폴더 연결
11. 현재 게시판의 전체 구조
지금까지 적용한 내용을 모두 합치면 다음과 같다.
Host PC
│
├─ board/
│ ├─ app.py
│ ├─ requirements.txt
│ └─ Dockerfile
│
│ app.py
│ │
│ │ Bind Mount
│ ↓
│
├──────────── Docker ─────────────┐
│ │
│ ┌─────────────────────────┐ │
│ │ board-container │ │
│ │ │ │
│ │ Python │ │
│ │ Flask │ │
│ │ │ │
│ │ /app/app.py │ │
│ │ │ │
│ │ /data/board.db │ │
│ │ ↑ │ │
│ └────────│────────────────┘ │
│ │ │
└────────────│───────────────────┘
│
│ Volume Mount
↓
┌───────────────┐
│ board-data │
│ Docker Volume │
└───────────────┘
앞에서 따로 공부했던 개념들이 하나의 애플리케이션 안에서 연결되는 것을 볼 수 있다.
12. 지금까지 사용한 Docker 명령어 정리
이미지를 만든다.
docker build -t docker-board .
이미지를 확인한다.
docker images
Volume을 만든다.
docker volume create board-data
Volume을 확인한다.
docker volume ls
Volume을 연결해서 컨테이너를 실행한다.
docker run -d \
--name board-container \
-p 5000:5000 \
-v board-data:/data \
docker-board
Bind Mount와 Volume을 동시에 사용하려면 다음처럼 실행할 수 있다.
docker run -d \
--name board-container \
-p 5000:5000 \
-v "$(pwd)/app.py:/app/app.py" \
-v board-data:/data \
docker-board
실행 중인 컨테이너를 확인한다.
docker ps
컨테이너를 삭제한다.
docker rm -f board-container
13. 여기까지의 전체 흐름
이번 게시판 실습에서 사용한 Docker의 개념을 모두 연결하면 다음과 같다.
Source Code
│
↓
Dockerfile
│
│ docker build
↓
Docker Image
│
│ docker run
↓
Docker Container
│
├─ Bind Mount → 개발 소스 코드
│
└─ Volume → 데이터 저장
처음에는 각각 별개의 개념처럼 보였던 Dockerfile, 이미지, 컨테이너, Bind Mount, Volume이 실제로는 하나의 흐름 안에서 사용되고 있다.
14. 다음 단계는 Docker Compose
현재 컨테이너는 하나뿐이다.
Flask
+
SQLite
하지만 실제 서비스에서는 보통 애플리케이션과 데이터베이스를 분리한다.
예를 들어
Flask Container
│
↓
MySQL Container
│
↓
Docker Volume
같은 구조를 사용할 수 있다.
컨테이너가 여러 개가 되면 매번 긴 docker run 명령어를 작성하기가 불편해진다.
이런 여러 컨테이너의 설정을 하나의 파일로 관리할 수 있도록 해주는 것이 Docker Compose다.
다음에는 현재 게시판을
Application Container
+
MySQL Container
구조로 나누고, Docker Compose를 사용해서 두 컨테이너를 한 번에 실행하는 방식으로 확장해볼 수 있다.
'개발 > Docker' 카테고리의 다른 글
| [Docker] Docker로 CRUD 게시판 만들어보기 1편 - Flask 게시판을 컨테이너로 실행하기 (0) | 2026.08.22 |
|---|---|
| [Docker] Dockerfile이란? (0) | 2026.08.20 |
| [Docker] Docker 볼륨과 바인드 마운트의 차이 (0) | 2026.08.20 |
| [Docker] Docker 이미지와 컨테이너 개념 정리 (0) | 2026.08.20 |
| [Docker] Docker는 무엇일까 (3) | 2025.08.16 |