Slide 1

Slide 1 text

SmartNews ʹ͓͚Δ container friendly ͳ Spring Boot ΞϓϦέʔγϣϯ։ൃ JSUG ษڧձ 2019 ͦͷ5 / 2019-05-31 KOMIYA Atsushi

Slide 2

Slide 2 text

@komiya_atsushi

Slide 3

Slide 3 text

SmartNews ʹ͓͚Δ container friendly ͳ Spring Boot ΞϓϦέʔγϣϯ։ൃ

Slide 4

Slide 4 text

SmartNews ʹ͓͚Δ container friendly ͳ Spring Boot ΞϓϦέʔγϣϯ։ൃ (container friendly ݴ͏΄Ͳͷൃද಺༰͡Όͳ͍ͳ ) (Spring Boot ͕ओ໾ͱ͍͏ײ͡Ͱ΋ͳ͍ͳ… )

Slide 5

Slide 5 text

Spring Boot Docker Έ͍ͨͳ࿩Λظ଴͞Εͯͨํ ͢Έ·ͤΜ

Slide 6

Slide 6 text

Docker Λ·͋·͋׆༻ͨ͠ Spring Boot ΞϓϦέʔγϣϯ։ൃ ͷࣄྫΛ͓࿩͠·͢

Slide 7

Slide 7 text

http://about.smartnews.com/ja/2019/05/21/20190521/

Slide 8

Slide 8 text

SmartNews ͷ ඪ४తͳٕज़ελοΫ

Slide 9

Slide 9 text

http://bit.ly/smartnews-tech-stack-2019

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

ૡ͍ఠΜͰ࿩Λ͢Δͱ… • AWS + AmazonLinux • ALB/CLB + ASG + EC2 • nginx + Spring Boot w/ embedded Tomcat • Java 8 (Java, Scala, Kotlin) • Terraform, CircleCI, CodeDeploy, Nexus, Datadog

Slide 12

Slide 12 text

λΠϜηʔϧ։ൃͷ෣୆ཪ

Slide 13

Slide 13 text

։ൃ౰ॳͷঢ়گ • 2019 Q1 தʹ։࢝ͯ͠ Q1 தʹϦϦʔε༧ఆ • ࣮ࡍʹϦϦʔεͰ͖ͨͷ͸ Q2 ಄ • ϦϦʔε·Ͱͷ࣌ؒత༛༧͕গͳ͍ • ׳Ε਌͠Έɺ։ൃޮ཰Α͍ϑϨʔϜϫʔΫ / ݴޠΛ બ୒ • Spring Boot + Kotlin

Slide 14

Slide 14 text

։ൃ౰ॳͷঢ়گ • 2019 Q1 ࣌఺ͷࣾ಺֎ͷঢ়گ • Java 11 ͕ϦϦʔε͞Εͯ 1Q Ҏ্ܦա • ࣾ಺తʹ͸·ͩ Java 8 ͕ݱ໾ͷγεςϜ͕େ൒ Λ઎Ί͍ͯͨ • ৽ن։ൃ͢ΔαʔϏεͳͷͰɺ͍·͞Β Java 8 ͸ બ୒ͨ͘͠ͳ͍

Slide 15

Slide 15 text

։ൃ౰ॳͷঢ়گ • ࣾ಺ͷඪ४తͳٕज़ελοΫ͸ Java 8 લఏ • طଘγεςϜͷ Java 11 ҠߦΛݕ౼ • ඪ४తͳٕज़ελοΫͷԸܙ͸ڗड͍ͨ͠ • Spring Boot ΞϓϦέʔγϣϯ & JDK Λ
 ߹ΘͤͯίϯςφԽͤ͞Δ͜ͱʹͨ͠

Slide 16

Slide 16 text

͜ͷޙͷ͓࿩ • ։ൃ • Ϗϧυ • σϓϩΠɾ؂ࢹ

Slide 17

Slide 17 text

։ൃ

Slide 18

Slide 18 text

API ※࣮ࡍͷߏ੒ΛҰ෦؆ུԽ͍ͯ͠·͢ όοΫΤϯυγεςϜͷ֓ཁ

Slide 19

Slide 19 text

։ൃ؀ڥͷ੔උ • ։ൃ؀ڥͷݸਓࠩΛ࠷খԽ͍ͨ͠ • MySQL αʔόΛखݩͷ؀ڥʹ༻ҙ͢Δ • ଞαʔϏεͰ΋ MySQL Λར༻͍ͯ͠Δ͕ɺ
 όʔδϣϯ͕ҟͳΓಘΔͨΊڞ༻͠೉͍ • Datadog agent (ͷ DogStatsD) ͕ඞཁʹͳΔ • ϝτϦΫεͷ؂ࢹʹ Datadog Λར༻͍ͯ͠Δ

Slide 20

Slide 20 text

։ൃ؀ڥͷ੔උ • Vagrant / VirtualBox Λ༻͍Δखஈ΋͋Γ͏Δ • ϓϩϏδϣχϯάνϣοτδΧϯΧΧϧ • ࠷ۙ͸৽نʹ։ൃ؀ڥΛߏங͢Δͱ͖ʹ
 όʔδϣϯབྷΈͷτϥϒϧʹר͖ࠐ·Ε
 ͕ͪͳͷͰܟԕ͍ͨ͠

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

# docker-compose.yml version: '3.1' services: db: image: mysql:5.7.25 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: main_db volumes: - ./tmp/mysql:/var/lib/mysql ports: - "13307:3306" dogstatsd: image: datadog/docker-dd-agent:12.7.5321-dogstatsd environment: API_KEY: ${DATADOG_API_KEY} ports: - “8125:8125/udp"

Slide 23

Slide 23 text

$ docker stack deploy \ -c docker-compose.yml \ stack-name $ docker stack rm stack-name

Slide 24

Slide 24 text

# application.yml spring: profiles: local-dev datasource: url: jdbc:mysql://127.0.0.1:3306/main_db username: root password: password management.metrics.export.statsd.host: 127.0.0.1 --- spring: profiles: docker-dev datasource: url: jdbc:mysql://host.docker.internal:3306/main_db username: root password: password management.metrics.export.statsd.host: host.docker.internal

Slide 25

Slide 25 text

Ϗϧυ

Slide 26

Slide 26 text

Spring Boot ΞϓϦέʔγϣϯΛ Docker Πϝʔδͱͯ͠Ϗϧυ͢Δ

Slide 27

Slide 27 text

Ұൠతͳ Spring Boot app ͷϏϧυ • Spring Boot Gradle plugin Λಋೖ͢Δ • ./gradlew build ͢Δ • fat jar ͕࡞ΒΕΔ

Slide 28

Slide 28 text

# Dockerfile FROM adoptopenjdk/openjdk11:jdk-11.0.3_7 COPY build/libs/spring-boot-app.jar /app/ CMD ["java", "-jar", “/app/spring-boot-app.jar”]

Slide 29

Slide 29 text

Docker Πϝʔδͱͯ͠Ϗϧυ͢Δ • Docker Gradle plugin (Palantir) Λಋೖ͢Δ • ./gradlew build docker Ͱ Docker
 ΠϝʔδΛϏϧυ͢Δ • ./gradlew dockerPush Ͱ Docker
 ΠϝʔδΛϨδετϦʹ push ͢Δ

Slide 30

Slide 30 text

# build.gradle plugins { id 'org.springframework.boot' id 'com.palantir.docker' id 'net.researchgate.release' } // ... docker { name “$dockerNamespace/spring-boot-app:$version” copySpec.from(“build/libs/spring-boot-app—${version}.jar”) .into('build/libs') .rename { “spring-boot-app.jar” } } docker.dependsOn(build) // ... afterReleaseBuild.dependsOn(dockerPush)

Slide 31

Slide 31 text

Docker ϕʔεΠϝʔδΛબͿ

Slide 32

Slide 32 text

ϕʔεΠϝʔδɺԿΛબͿʁ • ༷ʑͳ૊৫͕͍ΖΜͳΠϝʔδΛఏڙ͍ͯͯ͠ɺ ͱͯ΋ ΧΦε ଟ༷ੑʹ෋ΜͰ͍Δ • OS: Debian, Ubuntu, Alpine Linux, Oracle Linux, Amazon Linux, … • ૊৫: Docker official, Oracle, AdoptOpenJDK, Azul systems, … • ͦͷଞ: LTS ͷ༗ແ, JRE/JDK, …

Slide 33

Slide 33 text

ϕʔεΠϝʔδɺԿΛબͿʁ • AdoptOpenJDK ΛબΜͩ • “LTS ͕͋ͬͯ JDK ͷΠϝʔδͰ͋Ε͹ԿͰ΋Α͔ͬ ͨɻࠓʹͯ͠ΈΕ͹ Amazon Corretto ΛબΜͰ΋Α ͔͔ͬͨ΋͠Εͳ͍ͱ൓ল͍ͯ͠Δ” • OS ͸ (Alpine Ͱ͸ͳ͘) Ubuntu Λબ୒, slim ͸બ͹ͣ • slim Πϝʔδͩͱ jstack ͳͲ͕ೖ͍ͬͯͳ͍

Slide 34

Slide 34 text

λΠϜηʔϧͷ ϏϧυύΠϓϥΠϯ

Slide 35

Slide 35 text

Docker image CodeDeploy artifact Jar git push

Slide 36

Slide 36 text

ΑΓΑ͍ Docker ΠϝʔδΛ ࡞Δ

Slide 37

Slide 37 text

ྑ࣭ͳ৘ใ͕ͪ͜Βʹ… • https://spring.io/guides/topicals/spring-boot-docker/ • https://spring.io/guides/gs/spring-boot-docker/

Slide 38

Slide 38 text

ϨΠϠΛ͋͑ͯ෼͚Δ FROM adoptopenjdk/openjdk11:jdk-11.0.3_7 ARG DEPENDENCY=build/dependency COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY ${DEPENDENCY}/META-INF /app/META-INF COPY ${DEPENDENCY}/BOOT-INF/classes /app CMD ["java", "-cp", "app:app/lib/*", "foo.bar.EntryPoint"]

Slide 39

Slide 39 text

ϨΠϠΛ͋͑ͯ෼͚Δ $ ./gradlew build $ mkdir build/dependency $ (cd build/dependency; jar -xf ../libs/spring-boot-app.jar) $ ./gradlew docker

Slide 40

Slide 40 text

ϨΠϠΛ͋͑ͯ෼͚Δ • ґଘϥΠϒϥϦʹมߋ͕ੜ͡ͳ͍ݶΓɺ
 ΠϝʔδͷϏϧυߴ଎Խ͕ظ଴Ͱ͖Δ • JarLauncher Λܦ༝ͤͣ௚઀ main Ϋϥε͔Β
 ࣮ߦ͢ΔͷͰɺىಈͷߴ଎Խ΋ظ଴Ͱ͖Δ

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

σϓϩΠɾ؂ࢹ

Slide 43

Slide 43 text

Docker image start.sh CodeDeploy artifact create-deployment docker run

Slide 44

Slide 44 text

Spring Boot app ͷίϯςφΛಈ͔͢ $ docker run -d —name spring-boot-app \ -p 8080:8080 \ -e SPRING_PROFILES_ACTIVE=production \ -v /path/to/host/log:/path/to/container/log \ spring-boot-app:X.Y.Z

Slide 45

Slide 45 text

Spring Boot app ͷίϯςφΛಈ͔͢ $ docker run -d —name spring-boot-app \ -p 8080:8080 \ -e SPRING_PROFILES_ACTIVE=production \ -v /path/to/host/log:/path/to/container/log \ spring-boot-app:X.Y.Z

Slide 46

Slide 46 text

# application.yml spring.profiles: production spring: profiles: include: common, aws, prd-db --- spring.profiles: staging spring: profiles: include: common, aws, stg-db --- spring.profiles: local spring: profiles: include: common, local-db

Slide 47

Slide 47 text

ϗετͷϑΝΠϧγεςϜʹϩάग़ྗ͢Δ $ docker run -d —name spring-boot-app \ -p 8080:8080 \ -e SPRING_PROFILES_ACTIVE=production \ -v /path/to/host/log:/path/to/container/log \ spring-boot-app:X.Y.Z

Slide 48

Slide 48 text

Datadog ʹΑΔϝτϦΫε؂ࢹ Datadog agent VEQ

Slide 49

Slide 49 text

# build.gradle dependencies { // ... implementation ‘org.springframework.boot:spring-boot-starter-actuator’ implementation ‘io.micrometer:micrometer-registry-statsd’ } # application.yml management: metrics: export: statsd: flavor: datadog host: host.docker.internal # 18.03 ΑΓલͷ docker Λ࢖͏৔߹͸ --network=host ͷΦϓγϣϯ෇͚ͯ # docker run ͱ͢Δɻ·ͨ host ͷࢦఆ͸ҎԼͷΑ͏ʹ 127.0.0.1 ͱ͢Δ host: 127.0.0.1

Slide 50

Slide 50 text

jstack ͨ͘͠ͳͬͨͱ͖͸ʁ $ docker exec spring-boot-app jstack 1

Slide 51

Slide 51 text

·ͱΊ

Slide 52

Slide 52 text

·ͱΊ • Java 11 + Spring Boot + Kotlin ͱ͍͏ߏ੒ͷ
 ৽نαʔϏεͷ։ൃͰ Docker Λ׆༻ͨ͠ • ։ൃ؀ڥͷ੔උ • Docker Πϝʔδͷߏஙํ๏ • σϓϩΠɾΞϓϦέʔγϣϯ࣮ߦํ๏