Dockerizing the project is challanging because of two things:
1. the classpath setup done in [start_component.sh](implementation/start_component.sh)
2. the GPIO pins of the Raspberry Pi must be accessable from inside the container for the lights
## Dockerfile walkthrough
The Dockerfile is used to build the container.
It hold instructions which files to copy and commands to run.
I choosed a multistage approach.
This means first in a dedicated container all dependencies get resolved and files compiled.
They are copied to a second container which serves the purpose of the runtime environment.
### Build stage
```Dockerfile
FROMmaven:3-jdk-11-slimasbuild
```
In the first line is defined which container we use for our (build) stage.
The `as build` names the stage.
Because the project uses Maven as dependency manager and Java 11 as version we use the [Apache Maven container](https://hub.docker.com/_/maven) with the tag (a tag is like a version) `3-jdk-11-slim`.
```Dockerfile
WORKDIR /root/app
```
This sets the current working directory inside the container.
When we run a command inside the container it is executed in this context.
```Dockerfile
COPY pom.xml .
```
This copies the `pom.xml` file from our project inside the container.
Because we set a working directory `.` actually means `/root/app`, so the file is located at `/root/app/pom.xml` inside the container.
```Dockerfile
RUN mvn dependency:resolve
```
This downloads all dependencies defined in the `pom.xml`.
As default location they are saved to `$HOME/.m2`.
Because we are the user `root` inside the container the dependencies are saved at `/root/.m2`.
```Dockerfile
RUN mvn dependency:build-classpath -Dmdep.outputFile=classpath.txt
```
This builds the classpath and saves it to `classpath.txt` in the working directory.
```Dockerfile
COPY src src
```
This copies the `src` folder from our project directory to current working directory inside the container.
```Dockerfile
RUN mvn compile
```
Here we finally build all our class files.
Our build stage is done.
It followes the container defintion for our final container.
###
```Dockerfile
FROM openjdk:11-jre
```
For this container we use the [OpenJDK container](https://hub.docker.com/_/openjdk) as base. And because everything is already compiled we only need the `jre` variant.
```Dockerfile
WORKDIR /root/app
```
Again, this sets the current working directory inside the container.
```Dockerfile
COPY --from=build /root/.m2 /root/.m2
COPY --from=build /root/app/classes classes
COPY --from=build /root/app/classpath.txt .
```
Here all files we need from the build stage are copied to our container.
```Dockerfile
COPY start_component_docker.sh start_component.sh
```
This copies the `start_component_docker.sh` file into the container, renaming it in the process.
This sets the entrypoint of the container that is executed when the container is started.
The first part of the command exports the `CLASSPATH` that needs to be set to resolve all the used packages inside the Java files.
It would probably be cleaner to use the `ENV` definition in the Dockerfile but setting an environment based on command output is [currently not possible](https://github.com/moby/moby/issues/29110).