2. Some stuff about me...
● Mostly doing cloud related stuff
○ Java, Groovy, Scala, Spring Boot, IOT, AWS, Terraform, Infrastructure
● Enjoying the good things
● Chef leuke dingen doen == “trying out cool and new stuff”
● Currently involved in a big IOT project
● Wannabe chef, movie & Netflix addict
6. Something that runs into production
● Docker
● Security
● Service Discovery
● Logging & Monitoring
● Rolling Deployments
● Networking
● Supervision
● Container hosting
● Docker
Development Production
Learning
cliff
15. // file: build.gradle ~ some code intentionally removed
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-actuator') → add spring boot actuator
testCompile('org.springframework.boot:spring-boot-starter-test')
}
String dockerImageName = "spring-boot-docker-helloworld" → set the image name
task buildDockerImage(type:Exec) { → task to create an image
group = 'docker'
description = 'Build a docker image'
commandLine 'docker', 'build', '-f', 'build/docker/Dockerfile', '-t', "${dockerImageName}", 'build/docker'
doFirst {
println ">> Creating image: ${dockerImageName}"
// some code intentionally removed
}
}
16. // file: build.gradle ~ some code intentionally removed
doFirst {
println ">> Creating image: ${dockerImageName}"
copy {
// copy files to build location, Dockerfile - Jar file
}
copy {
// process Dockerfile to replace labels (Dockerfile label: @name@, @version@, @build-date@, …
// copy files to build location, Dockerfile - Jar file
from('src/main/docker/') {
include 'Dockerfile'
filter(ReplaceTokens, tokens: [
'version': version,
'build-date': new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC")),
'git-branch': gitBranch(),
'git-commit': gitCommitHash()
])
}
file("build/docker/app/${jar.archiveName}").renameTo("build/docker/app/application.jar")
}
17. // file: Dockerfile example ~ some code intentionally removed
FROM java:8u66-jdk
LABEL com.acme.build-date="@build-date@" → provide data to the Dockerfile
EXPOSE 8080 → expose port 8080, so the host can map this port
# Create app that holds the application.jar file
RUN mkdir -p /app → do some housekeeping, creating directories
WORKDIR /app
COPY /app/application.jar application.jar → copy the application.jar file into the container
COPY /app/docker-entrypoint.sh docker-entrypoint.sh → copy startup script into the container
# Set file permissions
RUN chmod +x docker-entrypoint.sh → make the shel script executable
# Set start script as default command
CMD ["./docker-entrypoint.sh"] → execute the startup script when we start the container
18. // file: build.gradle
project.ext.dockerRegistry = System.env.DOCKER_REGISTRY → get the docker registry from environment
String dockerImageName = "spring-boot-docker-helloworld" → set the image name
task pushDockerImage(type: Exec) {
group = 'docker'
description = 'Push a docker image'
commandLine 'docker', 'push', "${project.ext.dockerRegistry}/${dockerImageName}"
doFirst {
println ">> Checking dockerRepository"
if (!project.ext.dockerRegistry) {
throw new GradleException("Unable to push image, please provide correct 'dockerRegistry'")
}
println ">> Pushing image: ${dockerImageName}"
}
}
19. Running the image using Docker Compose
// file: docker-compose.yml
version: '2'
services:
springboot-demo: → name if container
image: spring-boot-docker-helloworld:latest → the image that is going to be used
ports:
- "8080:8080” → port mapping 8080 host -> 8080 container
23. Container Services
● Most used Container Services
○ Amazon ECS
○ Kubernetes by Google
○ Docker Swarm
○ Hashicorp Nomad
○ Azure Container Service
All have the some focus:
Run your Services / Containers
25. Placement Strategies
● Strategy name
○ node selected
● Spread
○ has the fewest containers,
disregarding their states
● Binpack
○ most packed (i.e. has the minimum
amount of free CPU/RAM)
● Random
○ chosen randomly
29. ● Amazon’s version of a Docker Registry
● Registry contains Repositories
○ unique namespace
● Logins generated on demand with
limited session length
● Images:
○ can be shared with AWS accounts
○ at rest are encrypted and stored in S3
○ transmitted over HTTPS
Container Registry
37. Demo Description
● Create the infrastructure
● Deploy “HelloWorld”
container to an
ECS Container Instance
● Make the endpoint
publicly available via
ALB
● Scale the container
instances
38. How to create the environment?
“Infrastructure as Code”
43. All fine, we have the infrastructure
Now get some apps deployed :)
Deployment of a Dockerized
app on ECS
44. Describing your Docker deployment
Describes one or more Docker
Containers that form your
application (blueprint)
Runs and maintains a desired
number of tasks from a
specified task definition
Running container with
the settings defined in
the Task Definition
45. Example: Task Definition
45
{ "family": "webserver", → family of containers
"containerDefinitions": [{
"name": "web", → name of the container
"image": "nginx", → the image used for the container
"cpu": 99, → cpu + memory credits
"memory": 100,
"portMappings": [{ → port mappings (expose port 80 in container to port 80 on host)
"containerPort": 80,
"hostPort": 80
}],
"environment": [{ → environment variables, used in the container
"name": "MYSQL_ROOT_PASSWORD",
"value": "password"
}]
}]
}
Can you spot the problem?
48. Run a task/service on ECS Container Service
● AWS Console
○ Use the AWS console and use the UI
● Manual
○ Using the AWS CLI / ECS CLI
● Automated
○ Using Cloudwatch or Terraform
49. Demo Description
● Create the infrastructure
● Deploy “HelloWorld”
container to an
ECS Container Instance
● Make the endpoint
publicly available via
ALB
● Scale the container
instances
54. Autoscaling your containers
● Scaling is based upon metrics → Application Autoscaling
○ Metrics on ECS/Service
■ cpu load, memory usage, io, …
● CloudWatch Alarm
○ cpu > 80% for 1 minute
○ cpu < 50% for 1 minute
● Scaling Policy → “ChangeInCapacity”
○ up +1 instance
○ down -1 instance
55. Demo Description
● Create the infrastructure
● Deploy “HelloWorld”
container to an
ECS Container Instance
● Make the endpoint
publicly available via
ALB
● Scale the container
instances
62. Configuring the Log Driver
62
{ "family": "webserver", → family of containers
"containerDefinitions": [{
"name": "web", → name of the container
"image": "nginx", → the image used for the container
// some intentionally omitted
"logConfiguration": { → log configuration
"logDriver": "awslogs", → to be used logdriver
"options": { → logdriver options
"awslogs-group": "awslogs-nginx",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "awslogs-example"
}
}
}]
}
67. Recap
● Running Docker containers on ECS is not hard
○ Build your Dockerized Spring Boot applications and push them to ECS
○ ECS Cluster with EC2 instances
● Use a “Infrastructure as Code” approach to keep a grasp on what needs to
be deployed
● Do not forget about Logging and Monitoring these steps are important
○ use CloudWatch or other monitoring tools to keep an eye on your infrastructure
● Service Discovery using DNS or Consul