Как заполнить кэш Gradle в образе Docker? - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь создать образ Docker для разработки приложения для Android. У меня есть образ, который устанавливает JDK, Android SDK + NDK.

Когда я запускаю образ и запускаю оболочку Gradle (gradlew), оболочка загружает последнюю версию Gradle, а затем все зависимости моего приложения, поэтому я вижу сообщения типа:

Download https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.4/gradle-3.1.4.pom
Download https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.1.4/builder-3.1.4.pom
...
Download https://jcenter.bintray.com/org/jetbrains/kotlin/kotlin-stdlib-jre8/1.2.0/kotlin-stdlib-jre8-1.2.0.pom
Download https://jcenter.bintray.com/com/squareup/javawriter/2.5.0/javawriter-2.5.0.pom
...
Download https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.4/gradle-3.1.4.jar
Download https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-core/3.1.4/gradle-core-3.1.4.jar

1007 * Etc. *

В связи с природой контейнеров Docker, каждый раз, когда я запускаю новый контейнер, ему придется снова загружать все эти зависимости, как будто это первый раз. (Я мог бы повторно использовать контейнер, но я бы предпочел, чтобы всем, кто использует это изображение, не приходилось загружать эти файлы; и использование нового контейнера каждый раз желательно по другим причинам.) Поэтому я хотел бы получить их "запеченными" в "образ докера. Какой лучший способ сделать это?

Одна идея состоит в том, чтобы добавить инструкции в Dockerfile, чтобы скопировать в исходный код моего проекта и выполнить сборку (а затем удалить файлы проекта из образа). Тем не менее, это кажется хитрым (мы должны игнорировать файлы, которые не отслеживаются .git) и расточительным (зачем на самом деле делать целую сборку; я просто хочу, чтобы эти файлы были загружены и помещены в соответствующее место).

Другой вариант - сделать сборку, извлечь все эти URL из вывода сборки, выяснить, куда они должны попасть на диск (не уверен, как это сделать), а затем добавить инструкции в Dockerfile для копирования вручную. их на место. Но это похоже на большую работу и потребует ручного обновления, когда меняются зависимости моего приложения.

Кажется, должен быть способ скопировать в оболочке Gradle и минимальный набор файлов сборки Gradle и попросить его "просто восстановить зависимости", но я не смог найти такую ​​цель. Есть ли способ сделать это?

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Я кэшировал загрузки, создав урезанную, взломанную версию сценария build.gradle, и использовал его для запуска загрузок из моего файла Dockerfile. Таким образом, каталог с моим Dockerfile также содержал упаковщик gradle (скрипт gradlew и связанный каталог gradle с .jar в нем), мой минимальный файл build.gradle, а также минимальный фиктивный файл AndroidManifest.xml, который был необходим для удовлетворения плагина android .

(Это не идеальная ИМО, поэтому я бы хотел услышать, есть ли у кого-нибудь способ получше.)

Из моего Dockerfile я запускаю загрузку так:

# The following steps use some dummy build files to trigger gradle to download depencies,
# so that they will be available in the image.
COPY . /tmp/triggerGradleDownloads/

RUN     cd /tmp/triggerGradleDownloads
    && ./gradlew --no-daemon --refresh-dependencies androidDependencies lint
    && rm -rf /tmp/triggerGradleDownloads

Содержимое ./src/main/AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- we just need a package name in this file to satisfy the android plugin -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.dummy">
</manifest>

Содержимое моего файла build.gradle:

// This is a cut-down and hacked-together build script used only to trigger download of dependencies.
// From your Dockerfile, run "./gradlew --no-daemon --refresh-dependencies androidDependencies lint".

buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.4'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 28
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:28.0.0-rc02'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
0 голосов
/ 18 сентября 2018

Вы можете запустить свой собственный локальный кеш артефактов Maven, используя Artifactory .

...