Upload
chris-richardson
View
10.866
Download
1
Tags:
Embed Size (px)
Citation preview
@crichardson
Deploying Spring Boot applications with Docker
Chris Richardson
Author of POJOs in ActionFounder of the original CloudFoundry.com
@[email protected]://plainoldobjects.comhttp://microservices.io
@crichardson
About Chris
Founder of a buzzword compliant (stealthy, social, mobile, big data, machine learning, ...) startup
Consultant helping organizations improve how they architect and deploy applications using cloud, micro services, polyglot applications, NoSQL, ...
Creator of http://microservices.io
Organizer of @oakjug - http://bit.ly/ebjava
Co-organizer of http://meetup.com/oakland-scala
@crichardson
Agenda
Introduction to Spring Boot
Why immutable infrastructure/containerization
Spring Boot and Docker
Docker-based deployment pipeline
@crichardson
User registration microservices
User Registration
Service
RabbitMQ
MongoDB
POST /user
{ emailAddress: "[email protected]", password: "xyz"}
NewUserNotification
User Management Service Email Service
Exchange
Queue Queue
User Registration
Web App
RegistrationForm
Confirmation page
http://plainoldobjects.com/category/spring-boot/
@crichardson
Building microservices with Spring Boot
Makes it easy to create stand-alone, production ready Spring applications
Automatically configures Spring using Convention over Configuration
Externalizes configuration
Generates standalone executable JARs with embedded web server
Provides a standard foundation for all your microservices
@crichardson
Spring Boot simplifies configuration
Spring Container
Application components
Fully configured application
ConfigurationMetadata
•Typesafe JavaConfig•Annotations•Legacy XML
Default Configuration
Metadata
Spring BootYou write less
of this
Inferred from CLASSPATH
@crichardson
About auto-configurationBuilds on Spring framework features
@EnableAutoConfiguration - triggers the inclusion of default configuration
@Conditional - beans only active if condition is satisfied
Conditional on class defined on class path
e.g. Mongo Driver implies Mongo beans
Conditional on bean defined/undefined
e.g. define Mongo beans if you haven’t
@crichardson
Building with Gradle
buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE") }}
apply plugin: 'scala'apply plugin: 'spring-boot'
dependencies { compile "org.springframework.boot:spring-boot-starter-web" compile "org.springframework.boot:spring-boot-starter-data-mongodb" compile "org.springframework.boot:spring-boot-starter-amqp" compile "org.springframework.boot:spring-boot-starter-actuator"
testCompile "org.springframework.boot:spring-boot-starter-test"}...
Ensures correct dependencies
@crichardson
Running the microservice
$ java -jar build/libs/spring-boot-restful-service.jar --server.port=8081...2014-12-03 16:32:04.671 INFO 93199 --- [ main] n.c.m.r.main.UserRegistrationMain$ : Started UserRegistrationMain. in 5.707 seconds (JVM running for 6.553)
$ curl localhost:8081/health{"status":"UP", "mongo":{"status":"UP","version":"2.4.10"}, "rabbit":{"status":"UP", ...}}
Built in health checks
Command line arg processing
@crichardson
Agenda
Introduction to Spring Boot
Why immutable infrastructure/containerization
Spring Boot and Docker
Docker-based deployment pipeline
@crichardson
Spring Boot simplifies deployment
Spring Boot creates self-contained JAR file
No separate application server to install/configure
Externalize configuration = immutable application
Just need Java
But which version of Java? 7.x? 8.y?
And, what about the other applications?
Tomcat, Play, NodeJS, ...
Deploying a system is complex
@crichardson
Package service as an RPMBenefits:
Encapsulates language, framework, application server, ...
Handles dependencies
...
But
Conflicting dependency versions
Conflicting ports, ...
@crichardson
Package as AMI
http://boxfuse.com/learn/why.html
packer.io, github.com/Netflix/aminatorcloudnative.io
@crichardson
Service-as-AMI is great BUT...
Building is so slow!
Booting is so slow!
AMIs aren’t portable - need to build for multiple platforms
Heavy-weight: Not practical to run multiple VMs on a developer machine
...
@crichardson
Package a service as a Docker image
Lightweight, OS-level virtualization mechanism
Runs on Linux (directly or via, e.g., Virtual Box)
Docker image:
Portable application packaging format
Self-contained, read-only file-system image of an operating system + application
Layered structure = sharing and caching ⇒ very, very fast
5 seconds to package application!
Docker container:
Running Docker image
Group of sandboxed processes
Builds on control groups and namespaces
Contains entire OS but typically the only process is the application (JVM) ⇒ fast startup
https://www.docker.com/
@crichardson
Agenda
Introduction to Spring Boot
Why immutable infrastructure/containerization
Spring Boot and Docker
Docker-based deployment pipeline
@crichardson
Packaging a Spring Boot application as a Docker image
Install Java
Install application JAR file
Configure image to run Java on startup
Handle externalized configuration
@crichardson
Dockerfile for packaging a Spring Boot application
Base image
Copy JAR into image /data is base image’s CWD
Expose 8080
Bonus question: why is the ADD command last?
@crichardson
Building the Spring Boot application copy jar to subdir so it can be
referenced by Dockerfile
Build image using ./Dockerfile
@crichardson
Running the Spring Boot container
docker run -‐d -‐p 8080:8080 -‐e SPRING_DATA_MONGODB_URI=mongodb://192.168.59.103/userregistration -‐e SPRING_RABBITMQ_HOST=192.168.59.103 -‐-‐name sb_rest_svcsb_rest_svc
Map container port to host port
Run as daemon
Container name
Image nameSpecify environment
variables
@crichardson
Agenda
Introduction to Spring Boot
Why immutable infrastructure/containerization
Spring Boot and Docker
Docker-based deployment pipeline
@crichardson
My application architecture
API gateway Event
Store
Service 1
Service 2
Service ...
Event Archiver
Indexer AWS Cloud
S3
NodeJS Scala/Spring Boot
@crichardson
Jenkins-based deployment pipeline
Build & Testmicroservice
Build & TestDockerimage
Deploy Docker image
to registry
One pipeline per microservice
@crichardson
Smoke testing docker images
Smoke test
Docker daemon
ServicecontainerGET /health
POST /containers/create
creates
POST /containers/{id}/start
Docker daemon must listen on TCP port
@crichardson
Publishing Docker images
docker tag service-${VERSION}:latest \ ${REGISTRY_HOST_AND_PORT}/service-${VERSION}
docker push ${REGISTRY_HOST_AND_PORT}/service-${VERSION}
docker/publish.sh
Pushing only takes 25 seconds!
@crichardson
CI environment runs on Docker
EC2 Instance
Jenkins Container
Artifactory container
EBS volume
/jenkins-home
/gradle-home
/artifactory-home
@crichardson
Updating production environment
Large EC2 instance running Docker
Deployment tool:
1. Compares running containers with what’s been built by Jenkins
2. Pulls latest images from Docker registry
3. Stops old versions
4. Launches new versions
One day: use Docker clustering solution and a service discovery mechanism,
Most likely, AWS container service
Mesos and Marathon + Zookeeper, Kubernetes or ???
@crichardson
Summary
Spring Boot is a great way to build Spring-based microservices
Docker is a great way to package microservices