When developing a project for the Android platform, even the smallest one, sooner or later you have to deal with the development environment. In addition to the Android SDK, it is necessary to have the latest version of Kotlin, Gradle, platform-tools, build-tools. And if on the developer's machine all these dependencies are solved to a greater extent using the Android Studio IDE, then on the CI / CD server, each update can turn into a headache. And if in web development, Docker has become the standard solution to the environment problem, then why not try to solve a similar problem with it in Android development ...
For those who do not know what Docker is - if it is quite simple, then this is a tool for creating the so-called. "Containers" which contain the minimum OS kernel and the necessary set of software that we can deploy wherever we want, while maintaining the environment. What exactly will be in our container is determined in the Dockerfile, which is then assembled into an image that can be launched anywhere and has idempotency properties.
The installation process and the basics of Docker are beautifully described on his
# Π’.ΠΊ. ΠΎΡΠ½ΠΎΠ²Π½ΡΠΌ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ Π΄Π»Ρ ΡΠ±ΠΎΡΠΊΠΈ Android-ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ² ΡΠ²Π»ΡΠ΅ΡΡΡ Gradle,
# ΠΈ ΠΏΠΎ ΡΡΠ°ΡΡΠ»ΠΈΠ²ΠΎΠΌΡ ΡΡΠ΅ΡΠ΅Π½ΠΈΡ ΠΎΠ±ΡΡΠΎΡΡΠ΅Π»ΡΡΡΠ² Π΅ΡΡΡ ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠΉ Docker-ΠΎΠ±ΡΠ°Π·
# ΠΌΡ ΡΠ΅ΡΠΈΠ»ΠΈ Π·Π° ΠΎΡΠ½ΠΎΠ²Ρ Π²Π·ΡΡΡ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΅Π³ΠΎ Ρ Π½ΡΠΆΠ½ΠΎΠΉ Π½Π°ΠΌ Π²Π΅ΡΡΠΈΠ΅ΠΉ Gradle
FROM gradle:5.4.1-jdk8
# ΠΠ°Π΄Π°Π΅ΠΌ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ Ρ Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎΠΉ ΠΏΠ°ΠΏΠΊΠΎΠΉ Π΄Π»Ρ Android SDK ΠΈ
# Π²Π΅ΡΡΠΈΡΠΌΠΈ ΠΏΠ»Π°ΡΡΠΎΡΠΌΡ ΠΈ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ
ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip"
ANDROID_HOME="/usr/local/android-sdk"
ANDROID_VERSION=28
ANDROID_BUILD_TOOLS_VERSION=28.0.3
# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΠ°ΠΏΠΊΡ, ΡΠΊΠ°ΡΠΈΠ²Π°Π΅ΠΌ ΡΡΠ΄Π° SDK ΠΈ ΡΠ°ΡΠΏΠ°ΠΊΠΎΠ²ΡΠ²Π°Π΅ΠΌ Π°ΡΡ
ΠΈΠ²,
# ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΡΠ»Π΅ ΡΠ±ΠΎΡΠΊΠΈ ΡΠ΄Π°Π»ΡΠ΅ΠΌ
RUN mkdir "$ANDROID_HOME" .android
&& cd "$ANDROID_HOME"
&& curl -o sdk.zip $SDK_URL
&& unzip sdk.zip
&& rm sdk.zip
# Π ΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΡΡΡΠΎΡΠΊΠ°Ρ
ΠΌΡ ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΠ°ΠΏΠΊΡ ΠΈ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠ΅ ΡΠ°ΠΉΠ»Ρ
# Ρ Π»ΠΈΡΠ΅Π½Π·ΠΈΡΠΌΠΈ. ΠΠ° ΠΎΡ. ΡΠ°ΠΉΡΠ΅ Android Π½Π°ΠΏΠΈΡΠ°Π½ΠΎ ΡΡΠΎ ΠΌΡ
# ΠΌΠΎΠΆΠ΅ΠΌ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΡΡΠΈ ΡΠ°ΠΉΠ»Ρ Ρ ΠΌΠ°ΡΠΈΠ½ Π³Π΄Π΅ Π²ΡΡΡΠ½ΡΡ ΡΡΠΈ
# Π»ΠΈΡΠ΅Π½Π·ΠΈΠΈ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠ΄ΠΈΠ»ΠΈ ΠΈ ΡΡΠΎ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ
# ΠΈΡ
ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ Π½Π΅Π»ΡΠ·Ρ
&& mkdir "$ANDROID_HOME/licenses" || true
&& echo "24333f8a63b6825ea9c5514f83c2829b004d1" > "$ANDROID_HOME/licenses/android-sdk-license"
&& echo "84831b9409646a918e30573bab4c9c91346d8" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
# ΠΠ°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ SDK ΠΈ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΡ build-tools, platform-tools
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}"
"platforms;android-${ANDROID_VERSION}"
"platform-tools"
We save it to the folder with our Android project and start building the container with the command
docker build -t android-build:5.4-28-27 .
Parameter -t sets the tag or name of our container, which usually consists of its name and version. In our case, we called it android-build and in the version we specified a combination of gradle, android-sdk and platform-tools versions. In the future, it will be easier for us to search for the image we need by name using such a βversionβ.
After the build has passed, we can use our image locally, we can download it with the command docker push to a public or private image repository in order to download it to other machines.
As an example, let's build a local project. To do this, in the project folder, run the command
docker run --rm -v "$PWD":/home/gradle/ -w /home/gradle android-build:5.4.1-28-27 gradle assembleDebug
Let's figure out what it means:
dockerrun - the image launch command itself
-rm - means that after stopping the container, it deletes everything that was created during its life
-v "$PWD":/home/gradle/ - mounts the current folder with our Android project to the container's internal folder /home/gradle/
-w /home/gradle - sets the working directory of the container
android-build:5.4.1-28-27 - the name of our container that we have collected
gradle assembleDebug - the build team itself, which assembles our project
If everything goes well, then after a couple of seconds / minutes you will see something like BUILD SUCCESSFUL in 8m 3s! And in the app/build/output/apk folder there will be an assembled application.
Similarly, you can perform other gradle tasks - check the project, run tests, etc. The main advantage is that if we need to build the project on any other machine, we do not need to worry about installing the entire environment, and it will be enough to download the necessary image and run the build in it.
The container does not store any changes, and each assembly is launched from scratch, which, on the one hand, guarantees the identity of the assembly regardless of where it is launched, on the other hand, every time you have to download all the dependencies and compile all the code again, and this can sometimes take a significant amount of time. Therefore, in addition to the usual "cold" start, we have the option of starting the assembly while maintaining the so-called. "cache", where we save the ~/.gradle folder by simply copying it to the working folder of the project, and at the beginning of the next build we return it back. We moved all copying procedures into separate scripts and the launch command itself began to look like this
docker run --rm -v "$PWD":/home/gradle/ -w /home/gradle android-build:5.4.1-28-27 /bin/bash -c "./pre.sh; gradle assembleDebug; ./post.sh"
As a result, the average project build time was reduced by several times (depending on the number of dependencies on the project, but the average project thus began to build in 1 minute instead of 5 minutes).
All this by itself only makes sense if you have your own internal CI / CD server, which you yourself support. But now there are many cloud services in which all these problems are solved and you donβt have to worry about it, and the necessary build properties can also be specified in the project settings.
Only registered users can participate in the survey.
Do you keep your CI/CD system internal or use a third party service
-
Using an internal server
-
Using an external service
-
We don't use CI/CD
-
Other
42 users voted. 16 users abstained.
Source: habr.com