Compiling Android In Jenkins In Docker (nearly!)
Tags: learning, softwaredevelopment, docker, devops
Published: 2024-01-30 23:09:46

Part two of an N part series: My first steps into trying to compile an Android app via Jenkins in docker. Covers the initial set up of a Jenkins server on a QNAP NAS in docker and the realisation that this project can be so much more...

## Step One: Creating and connecting the server to GitHub

To begin our journey, I knew that first I would need to head on over to the Docker hub and to find the official Jenkins image: https://hub.docker.com/r/jenkins/jenkins

This should have everything we need to set up some pipelines on my QNAP NAS in Container Station - and even better! There's a tag with the JDK already installed - this might be perfect for building an Android app no? (Spoiler, it wasn't!)

So let's get the jenkins/jenkins:lts-jdk17 image pulled locally to our NAS...

![Jenkins downloaded in Container Station](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jn682x14hxezjmg2s4qv.png)

Okay, so far so good, now let's create a new volume for our Jenkins server's future home directory, so we don't lose any data between container restarts:
![Creating a volume for the home directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/smvqibh86kovco5ynrd4.png)

And finally, with the basics done, we can move on to the good stuff: Creating a container that will have a running server inside of it! First, let's tell Container Station that we want to use the image we just downloaded:

![Image Selection Dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pufsqsc7jrj0kzf1m6as.png)

And then let's configure our container with a name & ensure that port 8080 is exposed (but not 50000 as we're not interested in allowing any Jenkins workers to connect to our main server in this setup)

![Container configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/toxa22fuwksthsxjdflj.png)

And thinking of stuff we probably don't need... Full access to our RAM is likely overkill too - this is still a media server too after all - so let's try limiting it to 1GB for now to see how that handles the load:

![Restricting the memory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf7tcnyu0i44cu8e8lua.png)

And for the last step, let's configure the home directory to use that volume that we created earlier:

![Home directory volume configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ztndx7jrklwd0h4brzm1.png)
Annnnnnnnd bingo!

![Jenkins welcome screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/myjecriscijdp7moqj14.png)

Once the initial setup wizard is taken care of, it's a simple case of creating our first pipeline! Let's just add the SSH key to clone my repo annnnnd oh. Okay, well, problems are normal and to be expected:

![No host key error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x38r358qddnxztsnmn6k.png)

Let's see, Google, StackExchange - aha! [Got you!](https://askubuntu.com/a/1431887)

A bit of SSH magic later via a terminal inside of our container et voilà!

![Adding GitHub to known hosts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qatz6xv0wnzv8pmrnb69.png)

Let's try running against our script (stored in a Jenkinsfile inside of git of course!)...

```
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
                sh './gradlew clean build'
            }
        }
    }
}
```
And we are in business!

![Gradle starting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h18nrlc92f7v671i73rh.png)

But oh. I should've seen this coming... Jenkins may have the JDK but it definitely doesn't have the Android SDK... So the build fails...

![Cannot find Android SDK](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ox9bsn0cx0wblb6c2986.png)

Well, this could be as simple as [writing a new Dockerfile](https://github.com/WindSekirun/Jenkins-Android-Docker)... But let's face it - this [tutorial ](https://devjorgecastro.medium.com/how-to-build-a-ci-cd-pipeline-for-android-with-jenkins-part-1-265b62b706e6) is much closer to what would actually be useful.

I started this project with a goal, but why should I build a one trick pony? A Jenkins server that can only build my Android apps? What if I write some TypeScript? .NET? <Insert whatever tech here>? Will I always restart my Jenkins server/make one big, complex, Dockerfile/image?

No. We can do better than that and should do better than that:
- Jenkins server running in a container - Done already ✔
- Builds running in ephemeral Jenkins container agents defined by Dockerfiles/images - I've done this before ✔
- Container with docker installed managing docker on the host - I've done this before too ✔

The result of this should be:
- A single Dockerfile that defines how to create my Jenkins server, that can be stored in git!
- A Dockerfile/Image reference per project, that can contain all of the tooling I need, stored in git!

Which when I consider the [origins of this little project](https://dev.to/dotdashnotdot/setting-up-android-cicd-the-intro-insurance-for-a-rainy-day-6mb) I think I'm sold! My own build system, almost entirely defined as & reproducible as code

[Until part three](https://dev.to/dotdashnotdot/compiling-android-in-jenkins-in-docker-a-bitter-victory-1n4e)

![Live and Learn](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExOHFiejBrdWh0dmxwd3VqN3pwbTMzbno0MXc4aHYxdWFudm1xZHZociZlcD12MV9naWZzX3NlYXJjaCZjdD1n/Uun3HIZM8KSz69jhJt/giphy.gif)