我正在尝试构建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
等等。
由于Docker容器的性质,每次我运行一个新容器时,都将不得不再次下载所有这些依赖项,就好像这是第一次。 (我可以重复使用一个容器,但是我希望使用此图像的每个人都不必下载这些文件;由于其他原因,每次都使用一个新鲜的容器是可取的。)因此,我想让它们“烘焙”进入“ Docker镜像”。最好的方法是什么?
一个想法是向Dockerfile添加指令以复制到我的项目的源代码中并进行构建(然后从映像中删除项目文件)。但是,这似乎很棘手(我们应该忽略未被.git跟踪的文件)并且浪费(为什么要真正进行整个构建;我只想下载这些文件并将其放在适当的位置)。
另一种选择是进行构建,从构建输出中获取所有这些URL,弄清楚它们应该在磁盘上的位置(不确定如何做),然后在Dockerfile中添加指令以手动复制他们到位。但这似乎是很多工作,并且当我的应用程序依赖项更改时,将需要手动更新。
似乎应该有一种方法可以在gradle包装器中进行复制,并提供最少的gradle构建文件集,并要求其“仅恢复依赖关系”,但是我一直无法找到这样的目标。有办法吗?
答案 0 :(得分:0)
您可以使用Artifactory运行自己的Maven工件本地缓存。
答案 1 :(得分:0)
I got the downloads cached by creating a cut-down, hacked-up version the build.gradle
script, and used that to trigger the downloads from my Dockerfile. So the directory with my Dockerfile also contained the gradle wrapper (gradlew script and associated gradle directory with the .jar in it), my minimal build.gradle file, and also a minimal dummy AndroidManifest.xml file which was needed to satisfy the android plugin.
(This is not ideal IMO, so I'd still love to hear if someone has a better way.)
From my Dockerfile, I trigger download like so:
# 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
Content of ./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>
Content of my build.gradle file:
// 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'
}