Skip to content

Commit f5e5a02

Browse files
authored
Merge pull request #16 from observabilitystack/native-image
Run geoip as native GraalVM image
2 parents 44d762c + eedf5dd commit f5e5a02

File tree

9 files changed

+247
-24
lines changed

9 files changed

+247
-24
lines changed

.dockerignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
**
2-
!target/*.jar
1+
.*
2+
examples
3+
target
4+
#!target/*.jar

.travis.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ env:
1515

1616
script:
1717
- mvn clean verify -Drevisison=$(date +%Y-%V)
18-
- docker build --build-arg MAXMIND_LICENSE_KEY=${MAXMIND_LICENSE_KEY} -t observabilitystack/geoip-api:latest -t observabilitystack/geoip-api:$(date +%Y-%V) .
18+
- docker build --build-arg MAXMIND_LICENSE_KEY=${MAXMIND_LICENSE_KEY} -t observabilitystack/geoip-api:latest -t observabilitystack/geoip-api:native -t observabilitystack/geoip-api:$(date +%Y-%V) .
19+
- ./test-native-image.sh
1920

2021
before_deploy:
2122
- export TRAVIS_TAG=${TRAVIS_TAG:-$(date +%Y-%V)}
2223
- GIT_COMMITTER_DATE=$(date -R) git tag -fm '${TRAVIS_TAG}' ${TRAVIS_TAG}
2324

2425
deploy:
2526
- provider: script
26-
script: bash push-to-dockerhub.sh
27+
script: ./push-to-dockerhub.sh
2728
on:
2829
branch: master
2930
- provider: releases
@@ -34,4 +35,4 @@ deploy:
3435
skip_cleanup: true
3536
body: Updated MaxMind GeoLite database as of ${TRAVIS_TAG}
3637
on:
37-
branch: master
38+
branch: master

Dockerfile

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,41 @@
1-
FROM openjdk:11.0.8
2-
ARG MAXMIND_LICENSE_KEY
1+
# build stage
2+
FROM oracle/graalvm-ce:20.2.0-java11 AS builder
3+
4+
ADD . /build
5+
WORKDIR /build
6+
7+
# For SDKMAN to work we need unzip & zip
8+
RUN yum -y install unzip zip
9+
RUN \
10+
# Install SDKMAN
11+
curl -s "https://get.sdkman.io" | bash; \
12+
source "$HOME/.sdkman/bin/sdkman-init.sh" && \
13+
sdk install maven && \
14+
# Install GraalVM Native Image
15+
gu install native-image && \
16+
native-image --version && \
17+
mvn --version && \
18+
java -version && \
19+
ls -la .
320

4-
# place app
5-
COPY target/*.jar /opt/geoip-api.jar
21+
# build image
22+
RUN source "$HOME/.sdkman/bin/sdkman-init.sh" && mvn -P native clean package
23+
24+
# run stage
25+
FROM centos:7.8.2003
26+
ARG MAXMIND_LICENSE_KEY
627

728
# download current maxmind databases
829
WORKDIR /srv
9-
RUN curl -sSL "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&suffix=tar.gz&license_key=${MAXMIND_LICENSE_KEY}" | tar -xz && \
30+
#RUN apk add curl && \
31+
RUN yum install -y tar gzip && \
32+
curl -sfSL "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&suffix=tar.gz&license_key=${MAXMIND_LICENSE_KEY}" | tar -xz && \
1033
ln -s GeoLite2-City_*/GeoLite2-City.mmdb .
1134

35+
# place app
36+
COPY --from=builder "/build/target/geoip-api" /srv/geoip-api
37+
1238
ENV CITY_DB_FILE /srv/GeoLite2-City.mmdb
13-
HEALTHCHECK --interval=5s --timeout=2s CMD curl -f http://localhost:8080/actuator/health
39+
HEALTHCHECK --interval=5s --timeout=1s CMD curl -f http://localhost:8080/actuator/health
1440
EXPOSE 8080
15-
CMD exec java ${JAVA_GC_OPTS} ${JAVA_OPTS} -jar /opt/geoip-api.jar
41+
CMD exec /srv/geoip-api

pom.xml

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<parent>
1414
<groupId>org.springframework.boot</groupId>
1515
<artifactId>spring-boot-starter-parent</artifactId>
16-
<version>2.3.3.RELEASE</version>
16+
<version>2.3.4.RELEASE</version>
1717
</parent>
1818

1919
<licenses>
@@ -63,8 +63,26 @@
6363
<!-- This build builds a docker image, there is no maven artifact to install or deploy -->
6464
<maven.install.skip>true</maven.install.skip>
6565
<maven.deploy.skip>true</maven.deploy.skip>
66+
67+
<start-class>com.s24.geoip.GeoIpApi</start-class>
6668
</properties>
6769

70+
<!-- for spring-graal-native -->
71+
<repositories>
72+
<repository>
73+
<id>spring-milestones</id>
74+
<name>Spring Milestones</name>
75+
<url>https://repo.spring.io/milestone</url>
76+
</repository>
77+
</repositories>
78+
<pluginRepositories>
79+
<pluginRepository>
80+
<id>spring-milestones</id>
81+
<name>Spring Milestones</name>
82+
<url>https://repo.spring.io/milestone</url>
83+
</pluginRepository>
84+
</pluginRepositories>
85+
6886
<dependencies>
6987
<dependency>
7088
<groupId>com.google.guava</groupId>
@@ -74,12 +92,14 @@
7492
<dependency>
7593
<groupId>org.springframework.boot</groupId>
7694
<artifactId>spring-boot-starter-web</artifactId>
95+
<!--
7796
<exclusions>
7897
<exclusion>
7998
<groupId>org.springframework.boot</groupId>
8099
<artifactId>spring-boot-starter-logging</artifactId>
81100
</exclusion>
82101
</exclusions>
102+
-->
83103
</dependency>
84104
<dependency>
85105
<groupId>org.springframework.boot</groupId>
@@ -89,10 +109,22 @@
89109
<groupId>io.micrometer</groupId>
90110
<artifactId>micrometer-registry-prometheus</artifactId>
91111
</dependency>
112+
<!--
92113
<dependency>
93114
<groupId>org.springframework.boot</groupId>
94115
<artifactId>spring-boot-starter-log4j2</artifactId>
95116
</dependency>
117+
-->
118+
<dependency>
119+
<groupId>org.springframework.experimental</groupId>
120+
<artifactId>spring-graalvm-native</artifactId>
121+
<version>0.7.1</version>
122+
</dependency>
123+
<dependency>
124+
<groupId>org.springframework</groupId>
125+
<artifactId>spring-context-indexer</artifactId>
126+
<optional>true</optional>
127+
</dependency>
96128
<dependency>
97129
<groupId>com.maxmind.geoip2</groupId>
98130
<artifactId>geoip2</artifactId>
@@ -108,15 +140,51 @@
108140
</dependencies>
109141

110142
<build>
111-
<plugins>
112-
<plugin>
113-
<groupId>org.springframework.boot</groupId>
114-
<artifactId>spring-boot-maven-plugin</artifactId>
115-
</plugin>
116-
<plugin>
117-
<artifactId>maven-failsafe-plugin</artifactId>
118-
</plugin>
119-
</plugins>
143+
<pluginManagement>
144+
<plugins>
145+
<plugin>
146+
<groupId>org.springframework.boot</groupId>
147+
<artifactId>spring-boot-maven-plugin</artifactId>
148+
</plugin>
149+
<plugin>
150+
<artifactId>maven-failsafe-plugin</artifactId>
151+
</plugin>
152+
</plugins>
153+
</pluginManagement>
120154
</build>
121155

156+
<profiles>
157+
<profile>
158+
<id>native</id>
159+
<build>
160+
<plugins>
161+
<plugin>
162+
<groupId>org.graalvm.nativeimage</groupId>
163+
<artifactId>native-image-maven-plugin</artifactId>
164+
<version>20.2.0</version>
165+
<configuration>
166+
<buildArgs>
167+
-J-Xmx4G
168+
-H:+TraceClassInitialization
169+
-H:+ReportExceptionStackTraces
170+
-H:ReflectionConfigurationFiles=/build/src/main/resources/reflection-config.json
171+
-Dspring.graal.remove-unused-autoconfig=true
172+
-Dspring.graal.remove-yaml-support=true
173+
</buildArgs>
174+
<imageName>${project.artifactId}</imageName>
175+
</configuration>
176+
<executions>
177+
<execution>
178+
<goals>
179+
<goal>native-image</goal>
180+
</goals>
181+
<phase>package</phase>
182+
</execution>
183+
</executions>
184+
</plugin>
185+
</plugins>
186+
</build>
187+
</profile>
188+
</profiles>
189+
122190
</project>

push-to-dockerhub.sh

100644100755
File mode changed.

src/main/java/com/s24/geoip/GeoIpApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import org.slf4j.Logger;
1818
import org.slf4j.LoggerFactory;
1919

20-
@SpringBootApplication
20+
@SpringBootApplication(proxyBeanMethods = false)
2121
public class GeoIpApi {
2222

2323
private static final Logger logger = LoggerFactory.getLogger(GeoIpApi.class);

src/main/java/com/s24/geoip/web/GeoIpRestController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ public ResponseEntity<Void> handleKnownNotFounds() {
5353
/**
5454
* Lookup the geolocation information for an ip address.
5555
*/
56+
5657
@GetMapping("/{address:.+}")
57-
public ResponseEntity<GeoIpEntry> lookup(@PathVariable InetAddress address) {
58+
public ResponseEntity<GeoIpEntry> lookup(@PathVariable("address") InetAddress address) {
5859
return ResponseEntity.of(geolocations.lookup(address));
5960
}
6061

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
[
2+
{
3+
"name" : "com.s24.geoip.GeoIpEntry",
4+
"allDeclaredConstructors" : true,
5+
"allPublicConstructors" : true,
6+
"allDeclaredMethods" : true,
7+
"allPublicMethods" : true,
8+
"allDeclaredFields" : true,
9+
"allPublicFields" : true
10+
},
11+
{
12+
"name" : "com.maxmind.geoip2.model.CityResponse",
13+
"allDeclaredConstructors" : true,
14+
"allPublicConstructors" : true,
15+
"allDeclaredMethods" : true,
16+
"allPublicMethods" : true,
17+
"allDeclaredFields" : true,
18+
"allPublicFields" : true
19+
},
20+
{
21+
"name" : "com.maxmind.geoip2.record.City",
22+
"allDeclaredConstructors" : true,
23+
"allPublicConstructors" : true,
24+
"allDeclaredMethods" : true,
25+
"allPublicMethods" : true,
26+
"allDeclaredFields" : true,
27+
"allPublicFields" : true
28+
},
29+
{
30+
"name" : "com.maxmind.geoip2.record.Continent",
31+
"allDeclaredConstructors" : true,
32+
"allPublicConstructors" : true,
33+
"allDeclaredMethods" : true,
34+
"allPublicMethods" : true,
35+
"allDeclaredFields" : true,
36+
"allPublicFields" : true
37+
},
38+
{
39+
"name" : "com.maxmind.geoip2.record.Location",
40+
"allDeclaredConstructors" : true,
41+
"allPublicConstructors" : true,
42+
"allDeclaredMethods" : true,
43+
"allPublicMethods" : true,
44+
"allDeclaredFields" : true,
45+
"allPublicFields" : true
46+
},
47+
{
48+
"name" : "com.maxmind.geoip2.record.Postal",
49+
"allDeclaredConstructors" : true,
50+
"allPublicConstructors" : true,
51+
"allDeclaredMethods" : true,
52+
"allPublicMethods" : true,
53+
"allDeclaredFields" : true,
54+
"allPublicFields" : true
55+
},
56+
{
57+
"name" : "com.maxmind.geoip2.record.Country",
58+
"allDeclaredConstructors" : true,
59+
"allPublicConstructors" : true,
60+
"allDeclaredMethods" : true,
61+
"allPublicMethods" : true,
62+
"allDeclaredFields" : true,
63+
"allPublicFields" : true
64+
},
65+
{
66+
"name" : "com.maxmind.geoip2.record.RepresentedCountry",
67+
"allDeclaredConstructors" : true,
68+
"allPublicConstructors" : true,
69+
"allDeclaredMethods" : true,
70+
"allPublicMethods" : true,
71+
"allDeclaredFields" : true,
72+
"allPublicFields" : true
73+
},
74+
{
75+
"name" : "com.maxmind.geoip2.record.Subdivision",
76+
"allDeclaredConstructors" : true,
77+
"allPublicConstructors" : true,
78+
"allDeclaredMethods" : true,
79+
"allPublicMethods" : true,
80+
"allDeclaredFields" : true,
81+
"allPublicFields" : true
82+
},
83+
{
84+
"name" : "com.maxmind.geoip2.record.Traits",
85+
"allDeclaredConstructors" : true,
86+
"allPublicConstructors" : true,
87+
"allDeclaredMethods" : true,
88+
"allPublicMethods" : true,
89+
"allDeclaredFields" : true,
90+
"allPublicFields" : true
91+
},
92+
{
93+
"name" : "com.maxmind.geoip2.NetworkDeserializer",
94+
"allDeclaredConstructors" : true,
95+
"allPublicConstructors" : true,
96+
"allDeclaredMethods" : true,
97+
"allPublicMethods" : true,
98+
"allDeclaredFields" : true,
99+
"allPublicFields" : true
100+
}
101+
]
102+

test-native-image.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# clean up after test
5+
function shutdown {
6+
docker rm -f geoip-native-test
7+
}
8+
trap shutdown EXIT
9+
10+
# launch docker
11+
docker run -dp 18080:8080 --name geoip-native-test observabilitystack/geoip-api:native
12+
sleep 1
13+
14+
# execute some curls
15+
curl -fso /dev/null "http://localhost:18080/actuator"
16+
curl -fso /dev/null "http://localhost:18080/actuator/health"
17+
curl -fso /dev/null "http://localhost:18080/actuator/prometheus"
18+
curl -fso /dev/null "http://localhost:18080/$(curl -s https://ifconfig.me/ip)"
19+
curl -fso /dev/null "http://localhost:18080/8.8.4.4"
20+
curl -fso /dev/null "http://localhost:18080/8.8.8.8"
21+
curl -fso /dev/null "http://localhost:18080/206.80.238.253"
22+
curl -fso /dev/null "http://localhost:18080/2.161.45.64"
23+
curl -fso /dev/null "http://localhost:18080/5.4.55.34"

0 commit comments

Comments
 (0)