이 자습서에서는 컨테이너 애플리케이션에 데이터를 유지하는 방법을 알아봅니다. 실행하거나 업데이트할 때는 데이터를 계속 사용할 수 있습니다. 데이터를 유지하는 데 사용되는 볼륨에는 두 가지 주요 유형이 있습니다. 이 자습서는 명명된 볼륨에 중점을 둡니다.
호스트의 정확한 마운트 지점을 제어하는 바인드 마운트에 대해서도 알아봅니다. 바인딩 탑재를 사용하여 데이터를 유지할 수 있지만 컨테이너에 더 많은 데이터를 추가할 수도 있습니다. 애플리케이션에서 작업할 때 바인딩 탑재를 사용하여 소스 코드를 컨테이너에 탑재하여 코드 변경 내용을 보고, 응답하고, 변경 내용을 즉시 볼 수 있도록 할 수 있습니다.
이 자습서에서는 이미지 계층화, 계층 캐싱 및 다단계 빌드도 소개합니다.
이 자습서에서는 다음 방법을 알아봅니다.
- 컨테이너 간 데이터를 이해합니다.
- 명명된 볼륨을 사용하여 데이터를 유지합니다.
- 바인드 마운트를 사용하세요.
- 이미지 계층을 봅니다.
- 캐시 종속성.
- 다단계 빌드를 이해합니다.
필수 구성 요소
이 자습서에서는 이전 자습서인 Visual Studio Code를 사용하여 컨테이너 앱을 만들고 공유합니다. 필수 구성 요소를 포함하는 해당 항목으로 시작합니다.
컨테이너 간 데이터 이해
이 섹션에서는 두 개의 컨테이너를 시작하고 각각에 파일을 만듭니다. 한 컨테이너에서 만든 파일은 다른 컨테이너에서 사용할 수 없습니다.
다음 명령을 사용하여
ubuntu
컨테이너를 시작합니다.docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
이 명령은
&&
사용하여 두 개의 명령을 호출하기 시작합니다. 첫 번째 부분은 난수 하나를 선택하고/data.txt
에 기록합니다. 두 번째 명령은 컨테이너를 계속 실행하기 위해 파일을 감시하는 것입니다.VS Code의 컨테이너 탐색기에서 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 앱은 의 /etc/todos/todo.db
에 데이터를 저장합니다.
SQLite 데이터베이스는 데이터를 단일 파일에 저장하는 관계형 데이터베이스입니다.
이 방법은 소규모 프로젝트에 적합합니다.
호스트에 단일 파일을 유지할 수 있습니다. 다음 컨테이너에서 사용할 수 있도록 설정하면 애플리케이션이 중단된 위치부터 이어갈 수 있습니다. 볼륨을 만들고 연결하거나 탑재 데이터가 저장된 폴더에 연결하면 데이터를 유지할 수 있습니다. 컨테이너는 todo.db 파일에 쓰고 해당 데이터는 볼륨의 호스트에 유지됩니다.
이 섹션에서는 으로 명명된 볼륨을 사용합니다. Docker는 디스크의 볼륨을 실제 위치로 유지 관리합니다. 볼륨의 이름을 참조하고 Docker는 올바른 데이터를 제공합니다.
docker volume create
명령을 사용하여 볼륨을 만듭니다.docker volume create todo-db
콘테이너에서 시작하기를 선택하고 마우스 오른쪽 단추를 클릭합니다. 중지를 선택하여 앱 컨테이너를 중지합니다.
명령줄에서 컨테이너를 중지하려면
docker stop
명령을 사용합니다.다음 명령을 사용하여 시작 컨테이너를 시작합니다.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
볼륨 매개 변수는 탑재할 볼륨과 위치를
/etc/todos
지정합니다.브라우저를 새로 고쳐 앱을 다시 로드합니다. 브라우저 창을 닫은 경우
http://localhost:3000/
으로 이동하세요. 할 일 목록에 일부 항목을 추가합니다.todo 앱의 시작 안내 컨테이너를 제거합니다. 컨테이너 탐색기에서 컨테이너를 마우스 오른쪽 단추로 클릭하고 제거를 선택하거나 및
docker stop
명령을 사용합니다docker rm
.동일한 명령을 사용하여 새 컨테이너를 시작합니다.
docker run -dp 3000:3000 -v todo-db:/etc/todos 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:lts-alpine sh -c "yarn install && yarn run dev"
이 명령에는 다음 매개 변수가 포함됩니다.
-
-dp 3000:3000
이전과 동일합니다. 분리 모드에서 실행하고 포트 매핑을 만듭니다. -
-w /app
컨테이너 내의 작업 디렉터리입니다. -
-v ${PWD}:/app"
바인딩은 컨테이너의 호스트에서 현재 디렉터리를/app
디렉터리에 탑재합니다. -
node:lts-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 +선택합니다.
VS Code에서 src/static/js/app.js엽니다. 줄 109에서 항목 추가 단추의 텍스트를 변경합니다.
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
변경 내용을 저장합니다.
브라우저를 새로 고칩니다. 변경 내용을 보셔야 합니다.
node:lts-alpine
컨테이너를 제거합니다.app
폴더에서, 이전 단계에서 만든node_modules
폴더를 제거하기 위해 다음 명령어를 실행합니다.rm -r node_modules
이미지 계층 보기
이미지를 구성하는 레이어를 볼 수 있습니다.
docker image history
명령을 실행하여 이미지 내에서 각 레이어를 만드는 데 사용된 명령을 확인합니다.
docker image history
을 사용하여 자습서 초반에 만든 시작하기 이미지의 층을 확인하세요.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:lts-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]
Dockerfile 각 명령은 이미지의 새 레이어가 됩니다.
레이어 수를 최소화하기 위해 Dockerfile 재구성하여 종속성 캐싱을 지원할 수 있습니다.
노드 기반 애플리케이션의 경우 이러한 종속성은 package.json
파일에 정의됩니다.
이 방법은 먼저 해당 파일만 복사하고, 종속성을 설치한 다음, 다른 모든 파일을 복사하는 것입니다.
이 프로세스는 package.json
변경된 경우에만 원사 종속성을 다시 만듭니다.
먼저 복사하고 종속성을 설치한 다음 다른 모든 항목을 복사하도록
package.json
업데이트합니다. 새 파일은 다음과 같습니다.FROM node:lts-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:lts-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수정하세요. 예를 들어 제목을 "멋진 할 일 앱"으로 변경합니다.
이제
docker build
사용하여 Docker 이미지를 다시 빌드합니다. 이번에는 출력이 약간 다르게 표시됩니다.Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:lts-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로 컴파일하는 노드 환경이 필요합니다. 서버 쪽 렌더링을 수행하지 않는 경우 프로덕션 빌드를 위한 노드 환경도 필요하지 않습니다.
FROM node:lts-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:lts-alpine
이미지를 사용하여 계층 캐싱을 최대화한 다음 출력을 nginx 컨테이너에 복사하는 빌드를 수행합니다.
리소스 정리
지금까지 수행한 모든 작업을 유지하여 이 자습서 시리즈를 계속 진행합니다.
다음 단계
컨테이너 앱에 대한 데이터를 유지하는 옵션에 대해 알아보았습니다.
다음에 무엇을 하고 싶으신가요?
Docker Compose를 사용하여 여러 컨테이너 작업:
MySQL 및 Docker Compose 사용하여 다중 컨테이너 앱 만들기
Azure Container Apps에 배포:
Azure App Service에 배포
- Azure 컨테이너화된 앱 배포