라트노팜 차크라바티 는 현재 에릭슨에서 근무하는 소프트웨어 개발자입니다. 그는 오랫동안 IoT, 기계 간 기술, 커넥티드 카, 스마트 시티 분야에 집중해 왔습니다. 그는 새로운 기술을 배우고 이를 실무에 적용하는 것을 좋아합니다. 일하지 않을 때는 3살 난 아들과 함께 시간을 보내는 것을 즐깁니다.
소개
이 시리즈의 2부에서는 Docker 도구 세트를 사용하여 Couchbase 기반의 완전한 기능을 갖춘 Spring Boot 웹 애플리케이션을 개발하고 실행하는 방법을 설명합니다. In 파트 1 시리즈에서는 두 개의 Docker 컨테이너를 실행하여 보기 좋은 UI를 갖춘 기능적인 애플리케이션을 실행하는 방법을 보여드렸습니다. 실행한 두 개의 Docker 컨테이너는 다음과 같습니다:
- A 카우치베이스 컨테이너 사전 구성된 설정으로
- 카우치베이스 컨테이너와 대화하는 애플리케이션 컨테이너(1단계에서 실행)
이 방법은 유용하지만 완전히 자동화된 것은 아니므로 자동화된 오케스트레이션이 제공되지 않습니다. 전체 설정을 실행하려면 두 개의 서로 다른 Docker 실행 명령을 실행해야 합니다.
애플리케이션 컨테이너를 빌드하고 실행하는 동시에 Couchbase 컨테이너의 실행을 트리거하는 방법이 있나요? 물론 방법이 있습니다.
Docker 작성 시작
사용 도커 컴포즈를 사용하면 다중 컨테이너 환경의 실행을 오케스트레이션할 수 있으며, 이것이 바로 우리 사용 사례에 필요한 것입니다. 먼저 Couchbase 컨테이너를 실행한 다음 애플리케이션 컨테이너가 실행되어 Couchbase 컨테이너와 통신해야 합니다.
다음은 이를 위한 docker-compose.yml 파일입니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
version: "2" services: app: build: . ports: - 8080:8080 environment: - BUCKET_NAME=books - HOST=192.168.99.100 depends_on: - db db: image: chakrar27/couchbase:books ports: - 8091:8091 - 8092:8092 - 8093:8093 - 8094:8094 - 11210:11210 |
우리 앱은 Couchbase 컨테이너인 DB 이미지에 "의존"합니다. 즉, Couchbase 컨테이너가 먼저 실행된 다음 앱 컨테이너가 실행되기 시작합니다. 여기서 한 가지 잠재적인 문제가 있습니다. "depends_on" 키워드는 Couchbase 컨테이너가 이미지 구성을 완료하고 실행을 시작했다는 것을 보장하지 않습니다. 컨테이너가 먼저 시작되었다는 것만 보장할 뿐, 컨테이너가 실제로 실행 중인지 또는 애플리케이션의 요청을 수락할 준비가 되었는지 여부는 확인하지 않습니다. Couchbase 컨테이너가 실제로 실행 중이고 쿼리, 인덱스 서비스 및 버킷 설정과 같은 모든 사전 구성 단계가 완료되었는지 확인하려면 애플리케이션 컨테이너에서 확인해야 합니다.
다음은 버킷이 이미 설정되었는지 여부를 차례로 확인하는 스크립트를 호출하는 앱 컨테이너의 Docker파일입니다. 이 스크립트는 버킷이 설정될 때까지 루프로 이동한 다음 앱 컨테이너를 트리거합니다.
https://github.com/ratchakr/bookstoreapp/blob/master/Dockerfile-v1
스크립트는 다음에서 확인할 수 있습니다. https://github.com/ratchakr/bookstoreapp/blob/master/run_app.sh
스크립트는 다음과 같은 작업을 수행합니다:
버킷을 쿼리하기 위해 Couchbase에서 지원하는 REST 엔드포인트를 사용합니다.
컬은 REST 엔드포인트를 호출하는 데 사용됩니다. curl의 설치는 애플리케이션의 Docker파일에서 다룹니다.
이 스크립트는 jq라는 도구를 사용하여 REST 호출의 JSON 응답을 구문 분석합니다.
버킷이 설정되어 있으면 앱 컨테이너를 실행하고, 그렇지 않으면 버킷이 먼저 설정될 때까지 기다립니다.
인덱스 서비스와 쿼리 서비스가 제대로 설정되었는지 여부와 같은 더 많은 검사를 셸 스크립트에 추가하여 더 강력하게 만들 수 있다는 점을 언급할 가치가 있습니다. 한 가지 주의할 점은 docker-compose 접근 방식을 따르기 전에 특정 사용 사례와 요구 사항을 확인하는 것입니다. Couchbase db 컨테이너가 완전히 실행 중이고 클라이언트 애플리케이션의 요청을 처리할 준비가 되어 있는지 확인할 수 있는 확실한 방법은 없습니다. 작동할 수 있는 몇 가지 접근 방식은 다음과 같습니다:
- 미리 구성된 버킷이 있는 경우 버킷이 존재하는지 테스트할 수 있습니다.
- 인덱스가 제자리에 있는지 확인
- 버킷의 레코드 수를 알고 있다면(초기 데이터 로드 시 버킷으로 가져온 .csv 파일을 예로 들어 보겠습니다), 그 수가 .csv 파일의 레코드 수와 일치하는지 확인할 수 있습니다.) 저희 사용 사례의 경우, 위에서 언급한 방법이 잘 작동합니다.
빌드 및 실행
이제 도커 컴포즈 파일과 도커파일을 준비했으니, 이제 간단한 도커-컴포지트 업 명령을 사용합니다.
다음은 Docker 콘솔의 출력 스니펫입니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
$ docker-compose up Creating network "bookstoreapp_default" with the default driver Pulling db (chakrar27/couchbase:books)... books: Pulling from chakrar27/couchbase Digest: sha256:4bc356a1f2b5b3d7ee3daf10cd5c55480ab831a0a147b07f5b14bea3de909fd9 Status: Downloaded newer image for chakrar27/couchbase:books Building app Step 1/8 : FROM frolvlad/alpine-oraclejdk8:full full: Pulling from frolvlad/alpine-oraclejdk8 Digest: sha256:a344745faa77a9aa5229f26bc4f5c596d13bcfc8fcac051a701b104a469aff1f Status: Downloaded newer image for frolvlad/alpine-oraclejdk8:full ---> 5f7037acb78d Step 2/8 : VOLUME /tmp ---> Running in 7d18e0b90bfd ---> 6a43ccb712dc Removing intermediate container 7d18e0b90bfd Step 3/8 : ADD target/bookstore-1.0.0-SNAPSHOT.jar app.jar ---> a3b4bf7745e0 Removing intermediate container 0404f1d094d3 Step 4/8 : RUN sh -c 'touch /app.jar' ---> Running in 64d1c82a0694 ---> 1ec5a68cafa9 Removing intermediate container 64d1c82a0694 Step 5/8 : RUN apk update && apk add curl ---> Running in 1f912e8341bd fetch https://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz v3.5.2-16-g53ad101cf8 [https://dl-cdn.alpinelinux.org/alpine/v3.5/main] v3.5.2-14-gd7ba0e189f [https://dl-cdn.alpinelinux.org/alpine/v3.5/community] OK: 7961 distinct packages available (1/4) Installing ca-certificates (20161130-r1) (2/4) Installing libssh2 (1.7.0-r2) (3/4) Installing libcurl (7.52.1-r2) (4/4) Installing curl (7.52.1-r2) Executing busybox-1.25.1-r0.trigger Executing ca-certificates-20161130-r1.trigger Executing glibc-bin-2.25-r0.trigger OK: 12 MiB in 18 packages ---> 8f99863af926 Removing intermediate container 1f912e8341bd Step 6/8 : ADD run_app.sh . ---> cedb8d545070 Removing intermediate container 8af5ac3ab0a0 Step 7/8 : RUN chmod +x run_app.sh ---> Running in 74a141de2f52 ---> 77ffd7425bea Removing intermediate container 74a141de2f52 Step 8/8 : CMD sh run_app.sh ---> Running in 6f81c8ebaa37 ---> 56a3659005ef Removing intermediate container 6f81c8ebaa37 Successfully built 56a3659005ef Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating bookstoreapp_db_1 Creating bookstoreapp_app_1 Attaching to bookstoreapp_db_1, bookstoreapp_app_1 db_1 | docker host ip = 192.168.99.100 db_1 | sleeping... app_1 | Starting application run script........... app_1 | couchbase is running on 192.168.99.100 app_1 | bucket to check is books db_1 | < Date: Fri, 24 Mar 2017 06:53:00 GMT db_1 | < Content-Length: 0 db_1 | < Cache-Control: no-cache db_1 | < 100 55 0 0 100 55 0 827 --:--:-- --:--:-- --:--:-- 833 db_1 | * Connection #0 to host 127.0.0.1 left intact db_1 | bucket set up done app_1 | response from cb app_1 | ************************************************ app_1 | ************************************************ app_1 | response from cb books app_1 | ************************************************ app_1 | ************************************************ app_1 | bucket is now ready bucket name books app_1 | Run application container now app_1 | ************************************************ app_1 | app_1 | . ____ _ __ _ _ app_1 | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ app_1 | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ app_1 | \\/ ___)| |_)| | | | | || (_| | ) ) ) ) app_1 | ' |____| .__|_| |_|_| |_\__, | / / / / app_1 | =========|_|==============|___/=/_/_/_/ app_1 | :: Spring Boot :: (v1.4.2.RELEASE) app_1 | app_1 | 2017-03-24 06:53:59.839 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=06bad9c4-85fc-4c0b-83a7-ad21b2fdd405, title=The Immortal Irishman, author=Timothy Egan, isbn=ISBN444, category=History] app_1 | 2017-03-24 06:53:59.839 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=328eaf44-edff-43c6-9f55-62d7e095256d, title=The Kite Runner, author=Khaled Hosseini, isbn=ISBN663, category=Fiction] app_1 | 2017-03-24 06:53:59.839 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=56882f5a-d466-457f-82c1-1c3bca0c6d75, title=Breaking Blue, author=Timothy Egan, isbn=ISBN777, category=Thriller] app_1 | 2017-03-24 06:53:59.839 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=845a2fe8-cbbf-4780-b216-41abf86d7d61, title=History of Mankind, author=Gabriel Garcia, isbn=ISBN123, category=History] app_1 | 2017-03-24 06:53:59.840 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=9d2833c3-e005-4c4f-98f9-75b69bbb7bf5, title=The Night Gardener, author=Eric Fan, isbn=ISBN333, category=Kids Books] app_1 | 2017-03-24 06:53:59.840 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=5756bf4d-551c-429e-8bc3-2339dc065ff8, title=Grit: The Power of Passion and Perseverance, author=Angela Duckworth, isbn=ISBN555, category=Business] app_1 | 2017-03-24 06:53:59.840 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Details = Book [id=e8e34f30-6fdf-4ca7-9cef-e06f504f8778, title=War and Turpentine, author=Stefan Hertmans, isbn=ISBN222, category=Fiction] app_1 | 2017-03-24 06:54:00.234 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Books by Timothy Egan = Book [id=06bad9c4-85fc-4c0b-83a7-ad21b2fdd405, title=The Immortal Irishman, author=Timothy Egan, isbn=ISBN444, category=History] app_1 | 2017-03-24 06:54:00.238 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Books by Timothy Egan = Book [id=56882f5a-d466-457f-82c1-1c3bca0c6d75, title=Breaking Blue, author=Timothy Egan, isbn=ISBN777, category=Thriller] app_1 | 2017-03-24 06:54:00.346 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Starting with title 'The' = Book [id=06bad9c4-85fc-4c0b-83a7-ad21b2fdd405, title=The Immortal Irishman, author=Timothy Egan, isbn=ISBN444, category=History] app_1 | 2017-03-24 06:54:00.349 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Starting with title 'The' = Book [id=328eaf44-edff-43c6-9f55-62d7e095256d, title=The Kite Runner, author=Khaled Hosseini, isbn=ISBN663, category=Fiction] app_1 | 2017-03-24 06:54:00.349 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book Starting with title 'The' = Book [id=9d2833c3-e005-4c4f-98f9-75b69bbb7bf5, title=The Night Gardener, author=Eric Fan, isbn=ISBN333, category=Kids Books] app_1 | 2017-03-24 06:54:00.443 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book in Fiction = Book [id=328eaf44-edff-43c6-9f55-62d7e095256d, title=The Kite Runner, author=Khaled Hosseini, isbn=ISBN663, category=Fiction] app_1 | 2017-03-24 06:54:00.453 INFO 31 --- [ main] c.chakrar.sample.books.BookStoreRunner : Book in Fiction = Book [id=e8e34f30-6fdf-4ca7-9cef-e06f504f8778, title=War and Turpentine, author=Stefan Hertmans, isbn=ISBN222, category=Fiction] app_1 | 2017-03-24 06:54:02.745 INFO 31 --- [nio-8080-exec-1] o.v.spring.servlet.Vaadin4SpringServlet : Could not find a SystemMessagesProvider in the application context, using default app_1 | 2017-03-24 06:54:02.753 INFO 31 --- [nio-8080-exec-1] o.v.spring.servlet.Vaadin4SpringServlet : Custom Vaadin4Spring servlet initialization completed app_1 | 2017-03-24 06:54:02.864 INFO 31 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' app_1 | 2017-03-24 06:54:02.865 INFO 31 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started |
이 시점에서 애플리케이션은 단일 docker-compose 오케스트레이션 명령으로 실행됩니다.
유형 192.168.99.100:8080 를 브라우저에 입력하면 다음 화면이 표시됩니다:

Docker Compose는 멀티 컨테이너 Docker 환경을 오케스트레이션하는 좋은 방법입니다. "docker" 명령 집합과 거의 유사한 명령 체인을 가지고 있습니다. 예를 들어, 실행 중인 컨테이너 목록을 보려면 간단히 입력하기만 하면 됩니다:
docker-compose ps >를 실행하면 다음과 같은 결과가 나타납니다.
|
1 2 3 4 5 6 7 8 9 |
$ docker-compose ps Name Command State Ports --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- bookstoreapp_app_1 /bin/sh -c sh run_app.sh Up 0.0.0.0:8080->8080/tcp bookstoreapp_db_1 /entrypoint.sh /opt/couchb ... Up 11207/tcp, 0.0.0.0:11210->11210/tcp, 11211/tcp, 18091/tcp, 18092/tcp, 18093/tcp, 0.0.0.0:8091->8091/tcp, 0.0.0.0:8092->8092/tcp, 0.0.0.0:8093->8093/tcp, 0.0.0.0:8094->8094/tcp |
여기에는 컨테이너 이름이 굵은 글씨로 표시되어 있습니다.
Docker Compose로 오케스트레이션된 환경을 중지하거나 해체해야 하는 경우, 다음을 사용하여 이를 수행할 수 있습니다. 도커-컴포지트 다운 명령을 실행합니다:
샘플 실행이 생성됩니다:
|
1 2 3 4 5 6 7 8 9 10 11 |
$ docker-compose down Stopping bookstoreapp_app_1 ... done Stopping bookstoreapp_db_1 ... done Removing bookstoreapp_app_1 ... done Removing bookstoreapp_db_1 ... done Removing network bookstoreapp_default |
이제 docker-compose ps를 실행하면 현재 실행 중인 컨테이너가 없음을 보여줍니다.
|
1 2 3 4 5 |
$ docker-compose ps Name Command State Ports --------------------------------------------------------------- |
또한, 자동화된 테스트 환경에서 Docker 컨테이너를 시작하고, 테스트를 실행한 다음, 전체 인프라를 해체하는 데 Docker compose를 사용할 수 있으며, 이 모든 작업을 Compose로 수행할 수 있습니다. Docker Compose에 대한 자세한 개요를 보려면 공식 웹사이트.