Skip to content

Commit

Permalink
Refactors build to use a parent pom and not rely on Docker Build Kit
Browse files Browse the repository at this point in the history
This simplifies the build a lot by using a parent pom (as suggested by @trustin)

This simplifies further by moving some configuration management to `build_image`.
  • Loading branch information
adriancole committed Oct 9, 2020
1 parent 7860a66 commit ed1c9b7
Show file tree
Hide file tree
Showing 21 changed files with 316 additions and 453 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**/target

**/.idea
**/*.iml
**/*.md

**/Dockerfile
Expand Down
14 changes: 5 additions & 9 deletions .github/workflows/docker-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
build-on-linux:
strategy:
matrix:
docker-target: [armeria, webmvc25-jetty, webmvc3-jetty, webmvc4-boot, webmvc4-jetty]
project: [armeria, webmvc25-jetty, webmvc3-jetty, webmvc4-boot, webmvc4-jetty]
runs-on: ubuntu-latest
name: Build and verify Docker images
steps:
Expand All @@ -30,16 +30,12 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Build Docker image openzipkin/example-brave:${{ matrix.docker-target }}-test
run: |
TARGET=${{ matrix.docker-target }}
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile \
-t openzipkin/example-brave:${TARGET}-test \
--target ${TARGET} --build-arg target=${TARGET} .
- name: Verify Docker image openzipkin/example-brave:${{ matrix.docker-target }}-test
- name: Build Docker image openzipkin/example-brave:${{ matrix.project }}-test
run: docker/build_image ${{ matrix.project }} ${{ matrix.project }}-test
- name: Verify Docker image openzipkin/example-brave:${{ matrix.project }}-test
run: |
# This just makes sure containers run and the HEALTHCHECK works (for now..)
IMAGE=openzipkin/example-brave:${{ matrix.docker-target }}-test
IMAGE=openzipkin/example-brave:${{ matrix.project }}-test
docker run --rm --name frontend -d ${IMAGE} frontend
docker run --rm --name backend -d ${IMAGE} backend
docker/bin/block-on-health frontend || exit 1
Expand Down
53 changes: 9 additions & 44 deletions armeria/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.zipkin.brave.example</groupId>
<artifactId>brave-example-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent-pom.xml</relativePath>
</parent>

<groupId>io.zipkin.brave.example</groupId>
<artifactId>brave-example-armeria</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>brave-example-armeria</name>
<description>Tracing Example: Armeria</description>
<description>Tracing Example: Armeria/ Java 15</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<jre.version>15</jre.version>
<maven.compiler.release>8</maven.compiler.release>

<!-- temporarily revert 1.1.0 until https://github.com/line/armeria/pull/3023 is discussed -->
<armeria.version>1.0.0</armeria.version>
<brave.version>5.12.6</brave.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -60,42 +61,6 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>${brave.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<optimize>true</optimize>
<debug>true</debug>
</configuration>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
</project>
119 changes: 26 additions & 93 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# These examples are setup minimally. In order to reduce repetition, these do not setup
# non-root users and such as they are not intended to run in production anyway.
ARG jre_image

# We copy files from the context into a scratch container first to avoid a problem where docker and
# docker-compose don't share layer hashes https://github.com/docker/compose/issues/883 normally.
Expand All @@ -11,113 +12,45 @@ COPY . /code/
## Use JDK 11 to build projects, as that can still compile Java 6
FROM openzipkin/java:11.0.8-11.41.23 as install

# The final stage to build. Mandatory: ex webmvc4-jetty
ARG target
RUN test -z "$target" && \
echo "'--build-arg target' must be set to same value as '--target'" && exit 1 || true
ARG project

WORKDIR /code
COPY --from=scratch /code .

# We copy the result of the build into a target-specific install directory.
# Each end phase looks for this convention. This strategy enforces a match
# between --target and the --build-arg target.
WORKDIR /install/${target}

# invoke the platfom-specific install script and copy the results
RUN cd /code/$target && mvn -q --batch-mode -DskipTests package && \
platform=$(echo $target|cut -d- -f2) && \
if [ "$platform" = "armeria" ]; then platform=java;fi && \
RUN cd $project && \
# Invoke the platform-specific install script
platform=$(echo "${project}"|cut -d- -f2) && \
if [ "${platform}" = "armeria" ]; then platform=java;fi && \
mvn -q --batch-mode -DskipTests package && \
/code/docker/bin/install-${platform}-example && \
cp -rp install/* /install/${target}/ && \
# Add start and health check scripts
mkdir /install/${target}/docker-bin && cd /install/${target}/docker-bin && \
cp -p /code/docker/bin/docker-healthcheck . && \
cp -p /code/docker/bin/start-${platform}-example start-brave-example

FROM openzipkin/java:15.0.0-15.27.17-jre as armeria
LABEL description="Tracing Example: Armeria/Java 15"

WORKDIR /brave-example
COPY --from=install /install/armeria/ .
# Add HEALTHCHECK and ENTRYPOINT scripts into the default search path
RUN mv docker-bin/* /usr/local/bin/ && rmdir docker-bin
# Move the completed installation root
mv install /install && \
# Add scripts used at runtime
cd /install/bin && \
cp -p /code/docker/bin/start-example-header start-brave-example && \
cat /code/docker/bin/start-${platform}-example >> start-brave-example && \
cp -p /code/docker/bin/docker-healthcheck .

EXPOSE 8081 9000
# Make the final layer that the example will run in
FROM $jre_image

ENV JAVA_OPTS="-Xms16m -Xmx16m -XX:+ExitOnOutOfMemoryError"
# All content including binaries and logs write under WORKDIR
ARG USER=brave-example
WORKDIR /${USER}

ENTRYPOINT ["start-brave-example"]
# Copy binaries and config we installed earlier
COPY --from=install --chown=${USER} /install .

# We use start period of 30s to avoid marking the container unhealthy on slow or contended CI hosts
HEALTHCHECK --interval=1s --start-period=30s --timeout=5s CMD ["docker-healthcheck"]

FROM azul/zulu-openjdk-alpine:6u119-6.22.0.3 as webmvc25-jetty
LABEL description="Tracing Example: Spring WebMVC 2.5/Servlet 2.5/Jetty 7/Java 6"
# Adding maintainer label as we are using a 3rd party base layer
LABEL maintainer="OpenZipkin https://zipkin.io/"

WORKDIR /brave-example
COPY --from=install /install/webmvc25-jetty/ .
# Add HEALTHCHECK and ENTRYPOINT scripts into the default search path
RUN mv docker-bin/* /usr/local/bin/ && rmdir docker-bin

EXPOSE 8081 9000
RUN mv bin/* /usr/local/bin/ && rm -rf bin

# When using JRE 1.6, we cannot use -XX:+ExitOnOutOfMemoryError
ENV JAVA_OPTS="-Xms16m -Xmx16m"
ENTRYPOINT ["start-brave-example"]
# Ensure the process doesn't run as root
RUN adduser -g '' -h ${PWD} -D ${USER}
USER ${USER}

# We use start period of 30s to avoid marking the container unhealthy on slow or contended CI hosts
HEALTHCHECK --interval=1s --start-period=30s --timeout=5s CMD ["docker-healthcheck"]

FROM openzipkin/java:1.7.0_261-b02-jre as webmvc3-jetty
LABEL description="Tracing Example: Spring WebMVC 3/Servlet 3.0/Jetty 8/Java 7"

WORKDIR /brave-example
COPY --from=install /install/webmvc3-jetty/ .
# Add HEALTHCHECK and ENTRYPOINT scripts into the default search path
RUN mv docker-bin/* /usr/local/bin/ && rmdir docker-bin

EXPOSE 8081 9000

ENV JAVA_OPTS="-Xms16m -Xmx16m -XX:+ExitOnOutOfMemoryError"

ENTRYPOINT ["start-brave-example"]

# We use start period of 30s to avoid marking the container unhealthy on slow or contended CI hosts
HEALTHCHECK --interval=1s --start-period=30s --timeout=5s CMD ["docker-healthcheck"]

FROM openzipkin/java:1.8.0_252-b09-jre as webmvc4-boot
LABEL description="Tracing Example: Spring WebMVC 4/Spring Boot 1.5/Java 8"

WORKDIR /brave-example
COPY --from=install /install/webmvc4-boot/ .
# Add HEALTHCHECK and ENTRYPOINT scripts into the default search path
RUN mv docker-bin/* /usr/local/bin/ && rmdir docker-bin

# Expose the default ports for the frontend and backend
EXPOSE 8081 9000

ENV JAVA_OPTS="-Xms32m -Xmx64m -XX:+ExitOnOutOfMemoryError"

ENTRYPOINT ["start-brave-example"]

# We use start period of 30s to avoid marking the container unhealthy on slow or contended CI hosts
HEALTHCHECK --interval=1s --start-period=30s --timeout=5s CMD ["docker-healthcheck"]

FROM openzipkin/java:1.8.0_252-b09-jre as webmvc4-jetty
LABEL description="Tracing Example: Spring WebMVC 4/Servlet 3.1/Jetty 9/Java 8"

WORKDIR /brave-example
COPY --from=install /install/webmvc4-jetty/ .
# Add HEALTHCHECK and ENTRYPOINT scripts into the default search path
RUN mv docker-bin/* /usr/local/bin/ && rmdir docker-bin

EXPOSE 8081 9000

ENV JAVA_OPTS="-Xms16m -Xmx16m -XX:+ExitOnOutOfMemoryError"

ENTRYPOINT ["start-brave-example"]

# We use start period of 30s to avoid marking the container unhealthy on slow or contended CI hosts
HEALTHCHECK --interval=1s --start-period=30s --timeout=5s CMD ["docker-healthcheck"]
14 changes: 5 additions & 9 deletions docker/RATIONALE.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# docker rationale

## Why do we set `--build-arg target` to the same value as `--target`?
## Why does `build_image` manually parse XML?

There are very few differences in our docker images from a scripting point of
view. However, each has different contents, and most have a different base
layer. We need to know the target stage before we create it, so that we can
build the right contents. There's no known way to read the value of the
`--target` parameter. Hence, we duplicate it as a build argument.

One impact of doing this is `DOCKER_BUILDKIT=1` or similar is required to skip
unused phases present in the process of building the image.
`build_image` is a script used to build Docker images per project. We need
some details from the pom file for build arguments. Rather than require
installing an XML parser or invoking Maven, this uses `sed` which is commonly
present on developer laptions and CI nodes.
24 changes: 3 additions & 21 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,9 @@ services:
## Building images
To build the Armeria/Java 15 example:
```bash
$ DOCKER_BUILDKIT=1 docker build -t openzipkin/example-brave:armeria -f docker/Dockerfile --target armeria --build-arg target=armeria .
```

To build the Spring WebMVC 2.5/Servlet 2.5/Jetty 7/Java 6 example:
```bash
$ DOCKER_BUILDKIT=1 docker build -t openzipkin/example-brave:webmvc25-jetty -f docker/Dockerfile --target webmvc25-jetty --build-arg target=webmvc25-jetty .
```

To build the Spring WebMVC 3/Servlet 3.0/Jetty 8/Java 7 example:
```bash
$ DOCKER_BUILDKIT=1 docker build -t openzipkin/example-brave:webmvc3-jetty -f docker/Dockerfile --target webmvc3-jetty --build-arg target=webmvc3-jetty .
```

To build the Spring WebMVC 4/Spring Boot 1.5/Java 8 example:
```bash
$ DOCKER_BUILDKIT=1 docker build -t openzipkin/example-brave:webmvc4-boot -f docker/Dockerfile --target webmvc4-boot --build-arg target=webmvc4-boot .
```
To build an example, from the root directory, invoke `docker/build_image YOUR_PROJECT`:

To build the Spring WebMVC 4/Servlet 3.1/Jetty 9/Java 8 example:
Ex. To build the Armeria example as the image 'openzipkin/example-brave:test'
```bash
$ DOCKER_BUILDKIT=1 docker build -t openzipkin/example-brave:webmvc4-jetty -f docker/Dockerfile --target webmvc4-jetty --build-arg target=webmvc4-jetty .
$ docker/build_image armeria test
```
2 changes: 1 addition & 1 deletion docker/bin/install-boot-example
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh
set -eu

mkdir install
mkdir -p install/bin

# extract the exec jar
cd install && jar xf ../target/*-exec.jar
2 changes: 2 additions & 0 deletions docker/bin/install-java-example
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/bin/sh
set -eu

mkdir -p install/bin

# Copy dependencies and compiled classes
mvn -q --batch-mode dependency:copy-dependencies -DoutputDirectory=install/lib
cp -r target/classes install/
2 changes: 1 addition & 1 deletion docker/bin/install-jetty-example
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -eu

mkdir install
mkdir -p install/bin

# extract the war under /root
cp -r target/*-SNAPSHOT install/root
Expand Down
26 changes: 3 additions & 23 deletions docker/bin/start-boot-example
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
#!/bin/sh

set -eu

case "$1" in
f|frontend|Frontend )
CLASS_NAME=Frontend
PORT=8081
;;
b|backend|Backend )
CLASS_NAME=Backend
PORT=9000
;;
* )
echo "Invalid argument: specify frontend or backend"
exit 1
esac

# write the docker-healthcheck url to a file
IP="$(hostname -i || echo '127.0.0.1')"
echo http://${IP}:${PORT}/health > health_url
JAVA_OPTS=${JAVA_OPTS:-"-Xms32m -Xmx64m -XX:+ExitOnOutOfMemoryError"}

exec java ${JAVA_OPTS} -cp . \
-Dzipkin.endpoint=${ZIPKIN_ENDPOINT:=http://zipkin:9411/api/v2/spans} \
-Dzipkin.supportsJoin=${ZIPKIN_SUPPORTS_JOIN:=true} \
-Dbackend.endpoint=${BACKEND_ENDPOINT:=http://backend:9000/api} \
-Dloader.main=brave.webmvc.${CLASS_NAME} org.springframework.boot.loader.PropertiesLauncher \
--server.port=${PORT}
-Dloader.main=brave.webmvc.$(echo "${ZIPKIN_SERVICE}" | sed 's/.*/\u&/') \
org.springframework.boot.loader.PropertiesLauncher --server.port=${PORT}
21 changes: 21 additions & 0 deletions docker/bin/start-example-header
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh

set -eu

case "$1" in
frontend )
ZIPKIN_SERVICE=frontend
PORT=8081
;;
backend )
ZIPKIN_SERVICE=backend
PORT=9000
;;
* )
echo "Invalid argument: specify frontend or backend"
exit 1
esac

# write the docker-healthcheck url to a file
IP="$(hostname -i || echo '127.0.0.1')"
echo http://${IP}:${PORT}/health > health_url
Loading

0 comments on commit ed1c9b7

Please sign in to comment.