다음을 통해 공유


자습서: VS Code의 볼륨을 사용하여 컨테이너 앱에 데이터 유지

이 자습서에서는 컨테이너 애플리케이션에 데이터를 유지하는 방법을 알아봅니다. 실행하거나 업데이트할 때는 데이터를 계속 사용할 수 있습니다. 데이터를 유지하는 데 사용되는 볼륨에는 두 가지 주요 유형이 있습니다. 이 자습서는 명명된 볼륨에 중점을 둡니다.

호스트의 정확한 마운트 지점을 제어하는 바인드 마운트에 대해서도 알아봅니다. 바인딩 탑재를 사용하여 데이터를 유지할 수 있지만 컨테이너에 더 많은 데이터를 추가할 수도 있습니다. 애플리케이션에서 작업할 때 바인딩 탑재를 사용하여 소스 코드를 컨테이너에 탑재하여 코드 변경 내용을 보고, 응답하고, 변경 내용을 즉시 볼 수 있도록 할 수 있습니다.

이 자습서에서는 이미지 계층화, 계층 캐싱 및 다단계 빌드도 소개합니다.

이 자습서에서는 다음 방법을 알아봅니다.

  • 컨테이너 간 데이터를 이해합니다.
  • 명명된 볼륨을 사용하여 데이터를 유지합니다.
  • 바인드 마운트를 사용하세요.
  • 이미지 계층을 봅니다.
  • 캐시 종속성.
  • 다단계 빌드를 이해합니다.

필수 구성 요소

이 자습서에서는 이전 자습서인 Visual Studio Code를 사용하여 컨테이너 앱을 만들고 공유합니다. 필수 구성 요소를 포함하는 해당 항목으로 시작합니다.

컨테이너 간 데이터 이해

이 섹션에서는 두 개의 컨테이너를 시작하고 각각에 파일을 만듭니다. 한 컨테이너에서 만든 파일은 다른 컨테이너에서 사용할 수 없습니다.

  1. 다음 명령을 사용하여 ubuntu 컨테이너를 시작합니다.

    docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
    

    이 명령은 &&사용하여 두 개의 명령을 호출하기 시작합니다. 첫 번째 부분은 난수 하나를 선택하고 /data.txt에 기록합니다. 두 번째 명령은 컨테이너를 계속 실행하기 위해 파일을 감시하는 것입니다.

  2. VS Code의 컨테이너 탐색기에서 ubuntu 컨테이너를 마우스 오른쪽 단추로 클릭하고 셸 연결을 선택합니다.

    스크린샷은 컨테이너가 선택된 컨테이너 도구 확장과 셸 연결이 선택된 상황에 맞는 메뉴를 보여줍니다.

    Ubuntu 컨테이너에서 셸을 실행하는 터미널이 열립니다.

  3. 다음 명령을 실행하여 /data.txt 파일의 내용을 확인합니다.

    cat /data.txt
    

    터미널은 1에서 10000 사이의 숫자를 표시합니다.

    명령줄을 사용하여 이 결과를 보려면 docker ps 명령을 사용하여 컨테이너 ID를 가져오고 다음 명령을 실행합니다.

    docker exec <container-id> cat /data.txt
    
  4. 다른 ubuntu 컨테이너를 시작합니다.

    docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
    
  5. 이 명령을 사용하여 폴더 내용을 확인합니다.

    docker run -it ubuntu ls /
    

    첫 번째 컨테이너에 대해서만 스크래치 공간에 기록되었으므로 data.txt 파일이 없어야 합니다.

  6. 이러한 두 Ubuntu 컨테이너를 선택합니다. 마우스 오른쪽 단추를 클릭하고 제거선택합니다. 명령줄에서 docker rm -f 명령을 사용하여 제거할 수 있습니다.

명명된 볼륨을 사용하여 할 일 데이터 유지

기본적으로 todo 앱은 /etc/todos/todo.db에 데이터를 저장합니다. SQLite 데이터베이스는 데이터를 단일 파일에 저장하는 관계형 데이터베이스입니다. 이 방법은 소규모 프로젝트에 적합합니다.

호스트에 단일 파일을 유지할 수 있습니다. 다음 컨테이너에서 사용할 수 있도록 설정하면 애플리케이션이 중단된 위치부터 이어갈 수 있습니다. 볼륨을 만들고 연결하거나 탑재 데이터가 저장된 폴더에 연결하면 데이터를 유지할 수 있습니다. 컨테이너는 todo.db 파일에 쓰고 해당 데이터는 볼륨의 호스트에 유지됩니다.

이 섹션에서는 으로 명명된 볼륨을 사용합니다. Docker는 디스크의 볼륨을 실제 위치로 유지 관리합니다. 볼륨의 이름을 참조하고 Docker는 올바른 데이터를 제공합니다.

  1. docker volume create 명령을 사용하여 볼륨을 만듭니다.

    docker volume create todo-db
    
  2. 콘테이너에서 시작하기를 선택하고 마우스 오른쪽 단추를 클릭합니다. 중지를 선택하여 앱 컨테이너를 중지합니다.

    명령줄에서 컨테이너를 중지하려면 docker stop 명령을 사용합니다.

  3. 다음 명령을 사용하여 시작 컨테이너를 시작합니다.

    docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    

    볼륨 매개 변수는 탑재할 볼륨과 위치를 /etc/todos지정합니다.

  4. 브라우저를 새로 고쳐 앱을 다시 로드합니다. 브라우저 창을 닫은 경우 http://localhost:3000/으로 이동하세요. 할 일 목록에 일부 항목을 추가합니다.

    스크린샷은 목록에 여러 항목이 추가된 샘플 앱을 보여줍니다.

  5. todo 앱의 시작 안내 컨테이너를 제거합니다. 컨테이너 탐색기에서 컨테이너를 마우스 오른쪽 단추로 클릭하고 제거를 선택하거나 및 docker stop 명령을 사용합니다docker rm.

  6. 동일한 명령을 사용하여 새 컨테이너를 시작합니다.

    docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    

    이 명령은 이전과 동일한 드라이브를 탑재합니다. 브라우저를 새로 고칩니다. 추가한 항목은 여전히 목록에 있습니다.

  7. 초기 설정 컨테이너를 다시 제거합니다.

아래에 설명된 명명된 볼륨 및 바인딩 탑재는 기본 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 데이터가 저장되는 실제 위치입니다. 대부분의 컴퓨터에서 호스트에서 이 디렉터리에 액세스하려면 루트 액세스 권한이 필요합니다.

바인드 마운트 사용

바인드 마운트를 사용하면 호스트에서 정확한 마운트 지점을 제어할 수 있습니다. 이 방법은 데이터를 유지하지만 컨테이너에 더 많은 데이터를 제공하는 데 자주 사용됩니다. 바인딩 탑재를 사용하여 소스 코드를 컨테이너에 탑재하여 코드 변경 내용을 보고, 응답하고, 변경 내용을 즉시 볼 수 있도록 할 수 있습니다.

개발 워크플로를 지원하기 위해 컨테이너를 실행하려면 다음 단계를 수행합니다.

  1. getting-started 컨테이너를 제거합니다.

  2. 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시작하고 있습니다.
  3. 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 +선택합니다.

  4. VS Code에서 src/static/js/app.js엽니다. 줄 109에서 항목 추가 단추의 텍스트를 변경합니다.

    - {submitting ? 'Adding...' : 'Add Item'}
    + {submitting ? 'Adding...' : 'Add'}
    

    변경 내용을 저장합니다.

  5. 브라우저를 새로 고칩니다. 변경 내용을 보셔야 합니다.

    스크린샷은 단추에 새 텍스트가 있는 샘플 앱을 보여줍니다.

  6. node:lts-alpine 컨테이너를 제거합니다.

  7. app 폴더에서, 이전 단계에서 만든 node_modules 폴더를 제거하기 위해 다음 명령어를 실행합니다.

    rm -r node_modules
    

이미지 계층 보기

이미지를 구성하는 레이어를 볼 수 있습니다. docker image history 명령을 실행하여 이미지 내에서 각 레이어를 만드는 데 사용된 명령을 확인합니다.

  1. 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   
    

    각 선은 이미지의 레이어를 나타냅니다. 출력은 맨 아래에 있는 기본을 표시하고 맨 위에 최신 계층을 표시합니다. 이 정보를 사용하여 각 계층의 크기를 확인하여 큰 이미지를 진단할 수 있습니다.

  2. 일부 줄은 잘립니다. --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변경된 경우에만 원사 종속성을 다시 만듭니다.

  1. 먼저 복사하고 종속성을 설치한 다음 다른 모든 항목을 복사하도록 package.json 업데이트합니다. 새 파일은 다음과 같습니다.

    FROM node:lts-alpine
    WORKDIR /app
    COPY package.json yarn.lock ./
    RUN yarn install --production
    COPY . .
    CMD ["node", "/app/src/index.js"]
    
  2. 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을 변경했기 때문에 예상된 것입니다.

  3. src/static/index.html수정하세요. 예를 들어 제목을 "멋진 할 일 앱"으로 변경합니다.

  4. 이제 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 컨테이너에 복사하는 빌드를 수행합니다.

리소스 정리

지금까지 수행한 모든 작업을 유지하여 이 자습서 시리즈를 계속 진행합니다.

다음 단계

컨테이너 앱에 대한 데이터를 유지하는 옵션에 대해 알아보았습니다.

다음에 무엇을 하고 싶으신가요?