Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref(docker): Use docker buildx (BuildKit) to publish docker images #556

Merged
merged 2 commits into from
Sep 26, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 44 additions & 4 deletions src/targets/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class DockerTarget extends BaseTarget {
* Pushes the the source image into local
* @param revision Image tag, usually the git revision
*/
public async pull(revision: string): Promise<any> {
async pull(revision: string): Promise<any> {
this.logger.debug('Pulling source image...');
const sourceImage = renderTemplateSafe(this.dockerConfig.sourceTemplate, {
...this.dockerConfig,
Expand All @@ -105,7 +105,7 @@ export class DockerTarget extends BaseTarget {
* @param sourceRevision The tag/revision for the source image
* @param version The release version for the target image
*/
public async push(sourceRevision: string, version: string): Promise<any> {
async push(sourceRevision: string, version: string): Promise<any> {
const sourceImage = renderTemplateSafe(this.dockerConfig.sourceTemplate, {
...this.dockerConfig,
revision: sourceRevision,
Expand All @@ -124,6 +124,40 @@ export class DockerTarget extends BaseTarget {
);
}

/**
* Checks whether Docker BuildKit is installed.
*/
async hasBuildKit(): Promise<boolean> {
return spawnProcess(DOCKER_BIN, ['buildx', 'version']).then(() => true).catch(() => false);
}

/**
* Copies an existing local or remote docker image to a new destination.
*
* Requires BuildKit / `docker buildx` to be installed.
*
* @param sourceRevision The tag/revision for the source image
* @param version The release version for the target image
*/
async copy(sourceRevision: string, version: string): Promise<any> {
const sourceImage = renderTemplateSafe(this.dockerConfig.sourceTemplate, {
...this.dockerConfig,
revision: sourceRevision,
});
const targetImage = renderTemplateSafe(this.dockerConfig.targetTemplate, {
...this.dockerConfig,
version,
});

this.logger.debug(`Copying image from ${sourceImage} to ${targetImage}...`);
return spawnProcess(
DOCKER_BIN,
['buildx', 'imagetools', 'create', '--tag', targetImage, sourceImage],
{},
{ showStdout: true }
);
}

/**
* Pushes a source image to Docker Hub
*
Expand All @@ -132,8 +166,14 @@ export class DockerTarget extends BaseTarget {
*/
public async publish(version: string, revision: string): Promise<any> {
await this.login();
await this.pull(revision);
await this.push(revision, version);

if (await this.hasBuildKit()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to just require buildkit and clean up the old code -- it's been around for half a decade

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately that will fail on OSX, at least it does on my colima install.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does docker version give you? I'd be pretty surprised if it's older than 2017

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

└─ % docker version
Client: Docker Engine - Community
 Version:           27.0.3
 API version:       1.43 (downgraded from 1.46)
 Go version:        go1.22.4
 Git commit:        7d4bcd863a
 Built:             Fri Jun 28 14:56:30 2024
 OS/Arch:           darwin/arm64
 Context:           colima

Server:
 Engine:
  Version:          24.0.5
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.7
  Git commit:       24.0.5-0ubuntu1
  Built:            Wed Aug 16 21:32:36 2023
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.7.2
  GitCommit:        
 runc:
  Version:          1.1.7-0ubuntu2.2
  GitCommit:        
 docker-init:
  Version:          0.19.0
  GitCommit:        
└─ % docker buildx version
docker: 'buildx' is not a docker command.
See 'docker --help'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on macos you'll need the docker-buildx package (it's a plugin -- that's usually shipped with core but is separate for some reason there)

Copy link
Member Author

@Dav1dde Dav1dde Sep 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah it's installable, but it means the change will become breaking even for current docker installs. I am totally fine with that though.

Let me know if you want me to change the code and drop the old pull/push method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I think it's reasonable -- arguably the non-buildx behaviour is broken

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 👍

await this.copy(revision, version);
} else {
// Fall back to slow/old pull and push method.
await this.pull(revision);
await this.push(revision, version);
}

this.logger.info('Docker release complete');
}
Expand Down
Loading