Skip to content

Commit 64c9e45

Browse files
authored
Added support for BuildX (#528)
1 parent c8af4b2 commit 64c9e45

File tree

8 files changed

+116
-7
lines changed

8 files changed

+116
-7
lines changed

.circleci/config.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,25 @@
55
version: 2.1
66
jobs:
77
build:
8-
machine: { docker_layer_caching: true }
8+
machine:
9+
docker_layer_caching: true
10+
image: ubuntu-2004:202104-01
911
environment:
1012
CIRCLE_TEST_REPORTS: /home/circleci/junit
1113
CIRCLE_ARTIFACTS: /home/circleci/artifacts
1214
_JAVA_OPTIONS: -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Xmx8192m
15+
DOCKER_BUILDKIT: 1
16+
BUILDX_PLATFORMS: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
1317
steps:
1418
- checkout
19+
- run:
20+
name: Install buildx
21+
command: |
22+
export DOCKER_BUILDKIT=1
23+
docker build --platform=local -o . "https://github.com/docker/buildx.git"
24+
mkdir -p ~/.docker/cli-plugins
25+
mv buildx ~/.docker/cli-plugins/docker-buildx
26+
docker buildx create --name mybuilder --use
1527
- run:
1628
name: delete_unrelated_tags
1729
command: |
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
type: improvement
2+
improvement:
3+
description: Add ability to do multi platform docker builds using buildx
4+
links:
5+
- https://github.com/palantir/gradle-docker/pull/528
6+
- https://github.com/palantir/gradle-docker/issues/353

readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ build/
6363
a newer version of the base image before building; defaults to `false`
6464
- `noCache` (optional) a boolean argument which defines whether Docker build should add the option --no-cache,
6565
so that it rebuilds the whole image from scratch; defaults to `false`
66+
- `buildx` (optional) a boolean argument which defines whether Docker build should use buildx for cross platform builds; defaults to `false`
67+
- `platform` (optional) a list of strings argument which defines which platforms buildx should target; defaults to empty
68+
- `builder` (optional) a string argument which defines which builder buildx should use; defaults to `null`
69+
- `load` (optional) a boolean argument which defines whether Docker buildx builder should add --load flag,
70+
loading the image into the local repository; defaults to `false`
6671

6772
To build a docker container, run the `docker` task. To push that container to a
6873
docker repository, run the `dockerPush` task.

src/main/groovy/com/palantir/gradle/docker/DockerExtension.groovy

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class DockerExtension {
4242
private boolean pull = false
4343
private boolean noCache = false
4444
private String network = null
45+
private boolean buildx = false
46+
private Set<String> platform = ImmutableSet.of()
47+
private boolean load = false
48+
private String builder = null
4549

4650
private File resolvedDockerfile = null
4751
private File resolvedDockerComposeTemplate = null
@@ -175,4 +179,36 @@ class DockerExtension {
175179
public void noCache(boolean noCache) {
176180
this.noCache = noCache
177181
}
182+
183+
public boolean getLoad() {
184+
return pull
185+
}
186+
187+
public void load(boolean pull) {
188+
this.pull = pull
189+
}
190+
191+
boolean getBuildx() {
192+
return buildx
193+
}
194+
195+
public void buildx(boolean buildx) {
196+
this.buildx = buildx
197+
}
198+
199+
public Set<String> getPlatform() {
200+
return platform
201+
}
202+
203+
public void platform(String... args) {
204+
this.platform = ImmutableSet.copyOf(args)
205+
}
206+
207+
String getBuilder() {
208+
return builder
209+
}
210+
211+
public void builder(String builder) {
212+
this.builder = builder
213+
}
178214
}

src/main/groovy/com/palantir/gradle/docker/PalantirDockerPlugin.groovy

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,21 @@ class PalantirDockerPlugin implements Plugin<Project> {
172172
}
173173

174174
private List<String> buildCommandLine(DockerExtension ext) {
175-
List<String> buildCommandLine = ['docker', 'build']
175+
List<String> buildCommandLine = ['docker']
176+
if (ext.buildx) {
177+
buildCommandLine.addAll(['buildx', 'build'])
178+
if (!ext.platform.isEmpty()) {
179+
buildCommandLine.addAll('--platform', String.join(',', ext.platform))
180+
}
181+
if (ext.load) {
182+
buildCommandLine.add '--load'
183+
}
184+
if (ext.builder != null) {
185+
buildCommandLine.addAll('--builder', ext.builder)
186+
}
187+
} else {
188+
buildCommandLine.add 'build'
189+
}
176190
if (ext.noCache) {
177191
buildCommandLine.add '--no-cache'
178192
}

src/test/groovy/com/palantir/gradle/docker/DockerComposePluginTests.groovy

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ class DockerComposePluginTests extends AbstractPluginTest {
173173
with('dockerComposeUp').build()
174174
then:
175175
file("foobarbaz").exists()
176+
execCond("docker stop helloworld")
177+
execCond("docker rm helloworld")
176178
}
177179

178180
def 'docker-compose successfully creates docker image from custom file'() {
@@ -200,6 +202,8 @@ class DockerComposePluginTests extends AbstractPluginTest {
200202
with('dockerComposeUp').build()
201203
then:
202204
file("qux").exists()
205+
execCond("docker stop helloworld2")
206+
execCond("docker rm helloworld2")
203207
}
204208

205209
def 'can set custom properties on generateDockerCompose.ext'() {
@@ -236,10 +240,9 @@ class DockerComposePluginTests extends AbstractPluginTest {
236240
id 'com.palantir.docker-compose'
237241
}
238242
'''.stripIndent()
239-
with('dockerComposeUp').build()
240243
when:
241-
with('dockerComposeDown').build()
244+
BuildResult buildResult = with('dockerComposeUp', 'dockerComposeDown').build()
242245
then:
243-
processCount() == 0
246+
buildResult.task(':dockerComposeDown').outcome == TaskOutcome.SUCCESS
244247
}
245248
}

src/test/groovy/com/palantir/gradle/docker/DockerRunPluginTests.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class DockerRunPluginTests extends AbstractPluginTest {
212212
buildResult.output =~ /(?m)\/test/
213213

214214
buildResult.task(':dockerRunStatus').outcome == TaskOutcome.SUCCESS
215-
buildResult.output =~ /(?m):dockerRunStatus\nDocker container 'foo' is STOPPED./
215+
buildResult.output =~ /(?m):dockerRunStatus\s+Docker container 'foo' is STOPPED./
216216
}
217217

218218
def 'can mount volumes'() {

src/test/groovy/com/palantir/gradle/docker/PalantirDockerPluginTests.groovy

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,37 @@ class PalantirDockerPluginTests extends AbstractPluginTest {
142142
execCond("docker rmi -f ${id}")
143143
}
144144

145+
def 'check multiarch'() {
146+
given:
147+
String id = 'id4'
148+
String filename = "foo.txt"
149+
file('Dockerfile') << """
150+
FROM alpine
151+
MAINTAINER ${id}
152+
ADD ${filename} /tmp/
153+
""".stripIndent()
154+
buildFile << """
155+
plugins {
156+
id 'com.palantir.docker'
157+
}
158+
docker {
159+
name '${id}'
160+
files "${filename}"
161+
buildx true
162+
load true
163+
platform 'linux/arm64'
164+
}
165+
""".stripIndent()
166+
new File(projectDir, filename).createNewFile()
167+
when:
168+
BuildResult buildResult = with('docker').build()
169+
then:
170+
buildResult.task(':dockerPrepare').outcome == TaskOutcome.SUCCESS
171+
buildResult.task(':docker').outcome == TaskOutcome.SUCCESS
172+
exec("docker inspect --format '{{.Architecture}}' ${id}") == "'arm64'\n"
173+
execCond("docker rmi -f ${id}")
174+
}
175+
145176
// Gradle explicitly disallows the test case, fails with the following:
146177
//Could not determine the dependencies of task ':publishDockerPublicationPublicationToMavenLocal'.
147178
//> Publishing is not able to resolve a dependency on a project with multiple publications that have different coordinates.
@@ -457,7 +488,7 @@ class PalantirDockerPluginTests extends AbstractPluginTest {
457488

458489
then:
459490
buildResult.task(':docker').outcome == TaskOutcome.SUCCESS
460-
buildResult.output.contains 'Pulling from library/alpine'
491+
buildResult.output.contains 'load metadata for docker.io/library/alpine'
461492
execCond("docker rmi -f ${id}")
462493
}
463494

@@ -488,6 +519,8 @@ class PalantirDockerPluginTests extends AbstractPluginTest {
488519
buildResult.task(':docker').outcome == TaskOutcome.FAILED
489520
buildResult.output.contains('network foobar not found') or(
490521
buildResult.output.contains('No such network: foobar')
522+
) or(
523+
buildResult.output.contains('network mode "foobar" not supported by buildkit')
491524
)
492525
execCond("docker rmi -f ${id}")
493526
}

0 commit comments

Comments
 (0)