-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
343 lines (222 loc) · 8.21 KB
/
index.html
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
<!DOCTYPE html>
<html>
<head>
<title>Docker in Java development</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
body { font-family: 'Droid Serif'; }
h1, h2, h3 {
font-family: 'Yanone Kaffeesatz';
font-weight: normal;
}
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
</style>
</head>
<body>
<textarea id="source">
<pre>
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
| |
__ | __ __ | _ __ _
/ \| / \ / |/ / _\ |
\__/| \__/ \__ |\_ \__ |
</pre>
# Docker in Java development
## Krystian Nowak
###### Ascii art by https://github.com/dhrp
---
# Agenda:
* Why Docker?
* Docker setup
* Hello Guinea Pig!
* Docker Maven plugin
* Marathon Maven plugin
* TestContainers
---
# Why Docker
## in Java development
* should we really care?
* c'mon! (I am) dev != DevOps ?
* everyone (rly?) uses it nowadays
* what do I care? (buzzwords come and go...)
* but it needs to be secured properly (we have already learned it the hard way)
* but maybe not in development yet?
* we do Java apps, not Docker apps, that's the contract
---
# Why Docker
## in Java development
### no buzzwords - in reality
* separation/sandboxing for possibly unwanted or temporary tools
* I just need to try this thing - not to bloat my machine
* getting up to speed with Docker technology
* maybe I just want to evaluate if my app should be _dockerized_
* reproducing issues in an environment as close to production setup as possible
* in case my production already is _dockerized_
* write once, debug everywhere
---
# Docker setup
* runs as a daemon
* _native_ on Linux platform
* on Windows and Mac uses various forms of virtualization to _proxy_ the commands
* Boot2Docker, Docker Machine, Docker Toolbox, Docker for Windows/Mac
* more advanced setup - out of scope
* exposes API via HTTP(S) or UNIX socket
* mostly REST - https://docs.docker.com/engine/reference/api/docker_remote_api/
---
# Docker setup
* direct access from Java
* multiple libraries exist e.g.
```xml
<dependency>
<groupId>com.spotify</groupId>
<artifactId>docker-client</artifactId>
<version>6.0.0</version>
</dependency>
```
* most of them properly detect Docker daemon
* on Linux _unix:///var/run/docker.sock_ existence check is obvious
* on Windows/Mac `DOCKER_HOST` env variable setting might be handy
* recently on Mac also Unix socket is used (detected properly)
---
# Hello Guinea Pig
## Let's meet our simple application
* simple behaviour
```shell
curl -i http://localhost:8080/application/hello-world
HTTP/1.1 200 OK
Date: Wed, 12 Oct 2016 17:51:42 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Content-Length: 30
Hello World! Counter value = 1
```
* simple deployment
```shell
java -jar myapp.jar
```
---
# Inside our Guinea Pig
* Using http://dropwizard.io/ to make it simple.
* one [JAX-RS GET resource](https://github.com/krystiannowak/Docker-in-Java-development/blob/master/src/main/java/krystiannowak/helloworld/HelloWorldResource.java)
* one `java.util.concurrent.atomic.AtomicLong` counter
* one [simple config file](https://github.com/krystiannowak/Docker-in-Java-development/blob/master/helloworld.yml)
* Run by a similar command:
```shell
java -jar target/helloworld-1.0-SNAPSHOT.jar server helloworld.yml
```
---
# Docker Maven plugin
## Maven project + Docker Maven plugin -> _dockerized_
* https://github.com/spotify/docker-maven-plugin
* the plugin in use - [project's POM](https://github.com/krystiannowak/Docker-in-Java-development/blob/master/pom.xml)
* let's see what it does:
```shell
mvn clean package docker:build -DskipTests
```
* and what we have just created:
```shell
docker images | grep helloworld
helloworld latest sha256:5b86d 2 minutes ago 124.8 MB
```
---
# Docker Maven plugin
## Let's run it!
* using command line
```shell
docker run -p 8080:8080 helloworld server helloworld.yml
```
* does Docker confirm it is running?
```shell
docker ps | grep helloworld
238252aee8c1 helloworld "java -jar /helloworl" 2 minutes ago
Up 51 seconds 0.0.0.0:8080->8080/tcp condescending_easley
```
---
# Docker Maven plugin
## Let's run it!
* is it accessible again?
* with a small help of `hosts` file in some cases:
```shell
curl -i http://docker:8080/application/hello-world
HTTP/1.1 200 OK
Date: Wed, 12 Oct 2016 18:57:30 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Content-Length: 30
Hello World! Counter value = 1
```
---
# Marathon Maven plugin
* https://github.com/holidaycheck/marathon-maven-plugin
* why to use?
* orchestration, [blue-green deployments](http://martinfowler.com/bliki/BlueGreenDeployment.html) and other buzzwords...
* but why in development already?
* prepare your application for being used from within Marathon and Mesos ecosystem
* reproduce issues hard to investigate without distributed environment
* why Maven plugin?
* integrates well with Docker Maven plugin e.g. tags for versioning
---
# Marathon Maven plugin
## How does it work?
* uses [Marathon REST API](http://mesosphere.github.io/marathon/docs/rest-api.html)
* processes a template of Marathon config file before using it in Deployment
* possibility to change Docker image tag used by previously run Docker Maven plugin
* see http://techblog.holidaycheck.com/2015/04/ for more examples
---
# Marathon Maven plugin
## Healthcheck
* remember about healthcheck URL for Marathon in your app e.g.
```shell
curl -i http://docker:8080/admin/healthcheck
HTTP/1.1 200 OK
Date: Wed, 12 Oct 2016 21:43:48 GMT
Content-Type: application/json
Cache-Control: must-revalidate,no-cache,no-store
Vary: Accept-Encoding
Content-Length: 61
{"Hello World":{"healthy":true},"deadlocks":{"healthy":true}}
```
* example naive implementation in [HelloWorldHealthCheck](https://github.com/krystiannowak/Docker-in-Java-development/blob/master/src/main/java/krystiannowak/helloworld/HelloWorldHealthCheck.java)
* real check should probe something meaningful for availability of the application e.g. accessibility of external resources
---
# TestContainers
## JUnit + Docker -> throwaway instances of dependencies
* https://github.com/testcontainers/testcontainers-java
* when is it needed?
* real instances e.g. of DBs, servers (when Java in-memory implementations or similar API lightweight implementations are not enough)
* isolated testing - available only for given test, no unwanted concurrent modifications (no external instance, tests should be self-contained)
* throwaway instances to be recreated from scratch by other tests (so not provided e.g. by Maven plugins pre and post test phases hooks)
---
# TestContainers
## How does it work?
* JUnit's `org.junit.Rule` (and the family)
* comes with already predefined test containers e.g. PostgreSQL, MySQL, Nginx or Selenium
exposing specific properties to be used in tests e.g. `java.sql.Connection`
* an example of testing PostgreSQL built-in procedures - [PostgresqlDBTest](https://github.com/krystiannowak/Docker-in-Java-development/blob/master/src/test/java/krystiannowak/helloworld/db/PostgresqlDBTest.java)
* a generic test container can be used (or extended) to support e.g. MongoDB
* an example of testing MongoDB server metadata - [MongoDBTest](https://github.com/krystiannowak/Docker-in-Java-development/blob/master/src/test/java/krystiannowak/helloworld/db/MongoDBTest.java)
* multiple test containers depending on each other -> use `org.junit.rules.RuleChain` to chain them together
---
# Q&A
---
# Thank you!
## Krystian Nowak
</textarea>
<script src="https://remarkjs.com/downloads/remark-latest.min.js">
</script>
<script>
var slideshow = remark.create();
</script>
</body>
</html>