자습서: VS Code에서 볼륨을 사용하여 컨테이너 앱에 데이터 유지
이 자습서에서는 컨테이너 애플리케이션에 데이터를 유지하는 방법을 알아봅니다. 컨테이너 애플리케이션을 실행하거나 업데이트할 때 데이터를 계속 사용할 수 있습니다. 데이터를 유지하는 데 사용되는 두 가지 주요 볼륨 유형이 있습니다. 이 자습서에서는 명명된 볼륨에 중점을 둡니다.
호스트의 정확한 탑재 지점을 제어하는 바인드 탑재에 대해서도 알아봅니다. 바인드 탑재를 사용하여 데이터를 유지할 수 있지만, 컨테이너에 더 많은 데이터를 추가할 수도 있습니다. 애플리케이션 작업 시 바인드 탑재를 사용하여 소스 코드를 컨테이너에 탑재하면 변경 내용을 즉시 확인할 수 있으며, 컨테이너가 코드 변경을 확인하고 응답하게 할 수 있습니다.
이 자습서에서는 이미지 계층화, 계층 캐싱, 다단계 빌드도 소개합니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- 컨테이너 간 데이터를 이해합니다.
- 명명된 볼륨을 사용하여 데이터를 유지합니다.
- 바인드 탑재를 사용합니다.
- 이미지 계층을 봅니다.
- 종속성을 캐시합니다.
- 다단계 빌드를 이해합니다.
필수 조건
이 자습서에서는 이전 자습서인 Visual Studio Code를 사용하여 Docker 앱 만들기 및 공유를 계속 진행합니다. 필수 구성 요소가 포함된 해당 자습서로 시작합니다.
컨테이너 간 데이터 이해
이 섹션에서는 두 개의 컨테이너를 시작하고 각각에 파일을 만듭니다. 한 컨테이너에서 만들어진 파일은 다른 컨테이너에서 사용할 수 없습니다.
다음 명령을 사용하여
ubuntu
컨테이너를 시작합니다.docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
이 명령은
&&
를 사용하여 두 개의 명령 호출을 시작합니다. 첫 번째 명령은 난수 1개를 선택하여/data.txt
에 씁니다. 두 번째 명령은 컨테이너가 계속 실행되는지 파일을 감시합니다.VS Code의 Docker 영역에서 ubuntu 컨테이너를 마우스 오른쪽 단추로 클릭하고 셸 연결을 선택합니다.
Ubuntu 컨테이너의 셸을 실행하는 터미널이 열립니다.
다음 명령을 실행하여
/data.txt
파일 내용을 확인합니다.cat /data.txt
터미널에 1에서 10000 사이의 숫자가 표시됩니다.
명령줄을 사용하여 이 결과를 확인하려면
docker ps
명령을 사용하여 컨테이너 ID를 가져오고 다음 명령을 실행합니다.docker exec <container-id> cat /data.txt
다른
ubuntu
컨테이너를 시작합니다.docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
다음 명령을 사용하여 폴더 내용을 확인합니다.
docker run -it ubuntu ls /
data.txt
파일이 없는데 첫 번째 컨테이너의 스크래치 공간에만 작성되었기 때문입니다.이러한 두 개의 Ubuntu 컨테이너를 선택합니다. 마우스 오른쪽 단추를 클릭하고 제거를 선택합니다. 명령줄에서
docker rm -f
명령을 사용하여 제거할 수 있습니다.
명명된 볼륨을 사용하여 todo 데이터 유지
기본적으로 todo 앱은 /etc/todos/todo.db
에 있는 SQLite 데이터베이스에 데이터를 저장합니다.
SQLite 데이터베이스는 데이터를 단일 파일로 저장하는 관계형 데이터베이스입니다.
이 접근 방식은 소규모 프로젝트에 적합합니다.
호스트에 단일 파일을 유지할 수 있습니다. 다음 컨테이너에서 이 파일을 사용할 수 있도록 설정할 때 애플리케이션이 중단된 위치를 선택할 수 있습니다. 볼륨을 만들고 데이터를 저장하는 폴더에 볼륨을 연결하거나 탑재하면 데이터를 유지할 수 있습니다. 컨테이너는 todo.db 파일에 쓰고 해당 데이터는 볼륨의 호스트에 유지됩니다.
이 섹션에서는 명명된 볼륨을 사용합니다. Docker는 디스크에서 볼륨의 실제 위치를 유지 관리합니다. 볼륨의 이름을 참조하면 Docker가 올바른 데이터를 제공합니다.
docker volume create
명령을 사용하여 볼륨을 만듭니다.docker volume create todo-db
컨테이너 아래에서 시작 및 마우스 오른쪽 단추를 클릭합니다. 중지를 선택하여 앱 컨테이너를 중지합니다.
명령줄에서 컨테이너를 중지하려면
docker stop
명령을 사용합니다.다음 명령을 사용하여 getting-started 컨테이너를 시작합니다.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
볼륨 매개 변수는 탑재할 볼륨과 위치
/etc/todos
를 지정합니다.브라우저를 새로 고쳐 앱을 다시 로드합니다. 브라우저 창을 닫은 경우
http://localhost:3000/
로 이동합니다. todo 목록에 몇 가지 항목을 추가합니다.todo 앱의 getting-started 컨테이너를 제거합니다. Docker 영역에서 컨테이너를 마우스 오른쪽 단추로 클릭하고 제거를 선택하거나
docker stop
및docker rm
명령을 사용합니다.같은 명령을 사용하여 새 컨테이너를 시작합니다.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
이 명령은 이전과 같은 드라이브를 탑재합니다. 브라우저를 새로 고칩니다. 추가한 항목은 여전히 목록에 있습니다.
getting-started 컨테이너를 다시 제거합니다.
아래에 설명된 명명된 볼륨 및 바인드 탑재는 기본 Docker 엔진 설치에서 지원하는 주요 볼륨 유형입니다.
속성 | 명명된 볼륨 | 탑재 바인딩 |
---|---|---|
호스트 위치 | Docker 선택 | 사용자 제어 |
탑재 예(-v 사용) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
새 볼륨에 컨테이너 내용을 채웁니다. | 예 | 아니요 |
볼륨 드라이버 지원 | 예 | 아니요 |
NFS, SFTP, NetApp 등을 지원하는 데 사용할 수 있는 많은 볼륨 드라이버 플러그 인이 있습니다. 이러한 플러그 인은 Swarm 또는 Kubernetes와 같은 클러스터형 환경의 여러 호스트에서 컨테이너를 실행하는 데 특히 중요합니다.
Docker 에서 실제로 데이터를 저장하는 위치가 궁금한 경우 다음 명령을 실행합니다.
docker volume inspect todo-db
이 결과와 유사한 출력을 확인합니다.
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Mountpoint
가 데이터가 저장되는 실제 위치입니다.
대부분 컴퓨터에서 호스트에서 이 디렉터리에 액세스하려면 루트 액세스 권한이 필요합니다.
바인드 탑재 사용
바인드 탑재를 사용하면 호스트의 탑재 지점을 정확하게 제어할 수 있습니다. 이 접근 방식은 데이터를 유지하지만, 컨테이너에 더 많은 데이터를 제공하는 데 자주 사용됩니다. 바인드 탑재를 사용하여 소스 코드를 컨테이너에 탑재하면 코드 변경 내용을 확인하고 대응할 수 있으며 변경 내용을 즉시 확인할 수 있습니다.
컨테이너를 실행하여 개발 워크플로를 지원하려면 다음 단계를 수행합니다.
모든
getting-started
컨테이너를 제거합니다.app
폴더에서 다음 명령을 실행합니다.docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:20-alpine sh -c "yarn install && yarn run dev"
이 명령에는 다음 매개 변수가 포함됩니다.
-dp 3000:3000
이전과 같습니다. 분리 모드에서 실행하고 포트 매핑을 만듭니다.-w /app
컨테이너 내의 작업 디렉터리-v ${PWD}:/app"
컨테이너에 있는 호스트의 현재 디렉터리를/app
디렉터리에 바인드 탑재합니다.node:20-alpine
사용할 이미지. 이 이미지는 Dockerfile에 있는 앱의 기본 이미지입니다.sh -c "yarn install && yarn run dev"
명령.sh
를 사용하여 셸을 시작하고yarn install
을 실행하여 모든 종속성을 설치합니다. 그런 다음,yarn run dev
를 실행합니다.package.json
을 살펴보면dev
스크립트에서nodemon
이 시작되는 것을 확인할 수 있습니다.
docker logs
를 사용하여 로그를 확인할 수 있습니다.docker logs -f <container-id>
$ nodemon src/index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000
이 목록에 최종 항목이 표시되면 앱이 실행되고 있는 것입니다.
로그 확인을 마쳤으면 터미널 창에서 아무 키나 선택하거나 외부 창에서 Ctrl+C를 선택합니다.
VS Code에서 src/static/js/app.js를 엽니다. 줄 109에서 항목 추가 단추의 텍스트를 변경합니다.
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
변경 내용을 저장합니다.
브라우저를 새로 고칩니다. 변경 내용이 표시됩니다.
이미지 계층 보기
이미지를 구성하는 계층을 확인할 수 있습니다.
docker image history
명령을 실행하여 이미지 내의 각 계층을 만드는 데 사용된 명령을 확인합니다.
docker image history
를 사용하여, 자습서의 앞부분에서 만든 getting-started 이미지의 계층을 확인합니다.docker image history getting-started
결과는 이 출력과 유사합니다.
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
각 선은 이미지 계층을 나타냅니다. 출력은 맨 아래에 기준이 표시되고 맨 위에 최신 계층이 있습니다. 이 정보를 사용하여 각 계층의 크기를 확인할 수 있어 큰 이미지를 진단하는 데 도움이 됩니다.
여러 줄이 잘렸습니다.
--no-trunc
매개 변수를 추가하면 전체 출력이 표시됩니다.docker image history --no-trunc getting-started
캐시 종속성
계층이 변경되면 다운스트림 계층도 모두 다시 만들어야 합니다. 다시 Dockerfile은 다음과 같습니다.
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]
Dockerfile의 각 명령은 이미지의 새 계층이 됩니다.
계층 수를 최소화하기 위해 종속성 캐싱을 지원하도록 Dockerfile을 재구성할 수 있습니다.
노드 기반 애플리케이션의 경우 package.json
파일에서 해당 종속성이 정의됩니다.
이 방법은 먼저 해당 파일만 복사하고 종속성을 설치한 다음 다른 모든 항목을 복사하는 것입니다.
이 프로세스에서는 package.json
이 변경된 경우에만 yarn 종속성을 다시 만듭니다.
먼저
package.json
에서 복사할 Dockerfile을 업데이트하고 종속성을 설치한 후 다른 모든 항목을 복사합니다. 새 파일은 다음과 같습니다.FROM node:20-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "/app/src/index.js"]
docker build
를 사용하여 새 이미지를 빌드합니다.docker build -t getting-started .
다음 결과와 같은 출력이 표시됩니다.
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Running in d53a06c9e4c2 yarn install v1.17.3 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.9: The platform "linux" is incompatible with this module. info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 10.89s. Removing intermediate container d53a06c9e4c2 ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> a239a11f68d8 Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 49999f68df8f Removing intermediate container 49999f68df8f ---> e709c03bc597 Successfully built e709c03bc597 Successfully tagged getting-started:latest
모든 계층이 다시 빌드되었습니다. Dockerfile을 변경했으므로 이 결과가 예상됩니다.
src/static/index.html을 변경합니다. 예를 들어 제목을 “The Awesome Todo App”으로 변경합니다.
다시
docker build
를 사용하여 Docker 이미지를 빌드합니다. 이번에는 출력이 약간 다르게 표시됩니다.Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> Using cache ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Using cache ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> cccde25a3d9a Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 2be75662c150 Removing intermediate container 2be75662c150 ---> 458e5c6f080c Successfully built 458e5c6f080c Successfully tagged getting-started:latest
빌드 캐시를 사용하므로 훨씬 더 빠르게 진행되어야 합니다.
다단계 빌드
다단계 빌드는 여러 단계를 사용하여 이미지를 만드는 데 도움을 주는 매우 강력한 도구입니다. 다단계 빌드에는 다음과 같은 몇 가지 이점이 있습니다.
- 런타임 종속성과 빌드 시간 종속성 구분
- 앱을 실행하는 데 필요한 ‘항목’만 제공하여 전체 이미지 크기 축소
이 섹션에서는 간단한 예제를 제공합니다.
Maven/Tomcat 예제
Java 기반 애플리케이션을 빌드하는 경우 소스 코드를 Java 바이트코드로 컴파일하려면 JDK가 필요합니다. 프로덕션 환경에서는 JDK가 필요하지 않습니다. 앱 빌드를 위해 Maven 또는 Gradle과 같은 도구를 사용할 수 있습니다. 해당 도구도 최종 이미지에는 필요하지 않습니다.
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
이 예제에서는 build
한 단계를 사용하여 Maven으로 실제 Java 빌드를 수행합니다.
두 번째 단계(“FROM tomcat”에서 시작)는 build
단계의 파일을 복사합니다.
마지막으로 생성되는 단계만 최종 이미지입니다(--target
매개 변수를 사용하여 재정의할 수 있음).
React 예제
React 애플리케이션을 빌드하는 경우 JavaScript 코드, SASS 스타일시트 등을 정적 HTML, JavaScript, CSS로 컴파일하려면 Node 환경이 필요합니다. 서버 쪽 렌더링을 수행하지 않는 경우 프로덕션 빌드에도 노드 환경이 필요하지 않습니다.
FROM node:20-alpine AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
이 예제에서는 node:20
이미지를 사용하여 계층 캐싱을 최대화한 후 출력을 nginx 컨테이너에 복사하는 빌드를 수행합니다.
리소스 정리
이 자습서 시리즈를 계속 진행하기 위해 지금까지 수행한 모든 작업을 유지합니다.
다음 단계
컨테이너 앱의 데이터를 유지하는 옵션에 대해 알아봤습니다.
다음에 무엇을 하고 싶으신가요?
Docker Compose를 사용하여 여러 컨테이너 작업:
Azure Container Apps에 배포:
Azure App Service에 배포
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기