Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .github/workflows/pr-setup-linux-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
matrix:
leia-test:
- setup-linux
- setup-linux-buildx
node-version:
- "20"
os:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## {{ UNRELEASED_VERSION }} - [{{ UNRELEASED_DATE }}]({{ UNRELEASED_LINK }})

* Updated `lando setup` to install `docker-buildx` if missing

## v3.26.2 - [December 17, 2025](https://github.com/lando/core/releases/tag/v3.26.2)

* Updated to use new Lando Alliance Apple Developer certificates
Expand Down
2 changes: 1 addition & 1 deletion docs/config/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ There are, however, a few different things you can do to improve performance.

## 1. VirtioFS on macOS

Docker Desktop [4.16.1](https://docs.docker.com/desktop/release-notes/#4161) finally makes VirtioFS file sharing generally available. VirtioFS offers [significant improvements in performance](https://www.jeffgeerling.com/blog/2022/new-docker-mac-virtiofs-file-sync-4x-faster) over the default gRPC FUSE mechanism. It's worth switching to but you will need at least Lando [3.9.0](https://github.com/lando/lando/releases/tag/v3.9.0) for it to work correctly.
Docker Desktop [4.16.1](https://docs.docker.com/desktop/release-notes/#4161) finally makes VirtioFS file sharing generally available. VirtioFS offers [significant improvements in performance](https://www.jeffgeerling.com/blog/2022/new-docker-mac-virtiofs-file-sync-4x-faster/) over the default gRPC FUSE mechanism. It's worth switching to but you will need at least Lando [3.9.0](https://github.com/lando/lando/releases/tag/v3.9.0) for it to work correctly.

If you see errors when using it we recommend the following corrective action:

Expand Down
2 changes: 1 addition & 1 deletion docs/services/l337.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ services:
imagefile: nginx:1.21
```

Note that if you do `buildkit: false` some image build features, specifically those in [Dockerfile 1.1.0+](https://docs.docker.com/build/buildkit/dockerfile-release-notes/#110) and the [ssh](#ssh) features of this service, may not be available. You can also use `buildx` as an alias for `buildkit`. If you use both it will evaluate to `true` if either is `true`. Really just don't use both ;)!
Note that if you do `buildkit: false` some image build features, specifically those in [Dockerfile 1.1.0+](https://github.com/moby/buildkit/releases/#110) and the [ssh](#ssh) features of this service, may not be available. You can also use `buildx` as an alias for `buildkit`. If you use both it will evaluate to `true` if either is `true`. Really just don't use both ;)!

You probably should just ignore this setting unless you have a well understood reason to do otherwise.

Expand Down
33 changes: 33 additions & 0 deletions examples/setup-linux-buildx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Setup Linux Buildx Tests

This example exists primarily to test that `lando setup` correctly installs buildx when it is not present.

* [lando setup](https://docs.lando.dev/cli/setup.html)

## Verification commands

Run the following commands to validate things are rolling as they should.

```bash
# Should dogfood the core plugin we are testing against
lando plugin-add "@lando/core@file:../.."

# Should have buildx installed by default on GitHub runners
docker buildx version

# Should be able to remove buildx
rm -f ~/.docker/cli-plugins/docker-buildx
sudo rm -f /usr/local/lib/docker/cli-plugins/docker-buildx
sudo rm -f /usr/local/libexec/docker/cli-plugins/docker-buildx
sudo rm -f /usr/lib/docker/cli-plugins/docker-buildx
sudo rm -f /usr/libexec/docker/cli-plugins/docker-buildx

# Should confirm buildx is no longer available
(docker buildx version 2>&1 || true) | tee >(cat) | grep -i "not found\|is not a docker command\|unknown command"

# Should be able to run lando setup and have it reinstall buildx
lando setup -y --skip-common-plugins

# Should have buildx installed again
docker buildx version
```
91 changes: 91 additions & 0 deletions hooks/lando-setup-buildx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
'use strict';

const axios = require('../utils/get-axios')();
const fs = require('fs');
const path = require('path');

/*
* Helper to get buildx download url
*/
const getBuildxDownloadUrl = (version = '0.30.1') => {
const arch = process.arch === 'arm64' ? 'arm64' : 'amd64';

switch (process.platform) {
case 'darwin':
return `https://github.com/docker/buildx/releases/download/v${version}/buildx-v${version}.darwin-${arch}`;
case 'linux':
return `https://github.com/docker/buildx/releases/download/v${version}/buildx-v${version}.linux-${arch}`;
case 'win32':
return `https://github.com/docker/buildx/releases/download/v${version}/buildx-v${version}.windows-${arch}.exe`;
}
};

/*
* Helper to get buildx download destination
*/
const getBuildxDownloadDest = home => {
const dir = path.join(home, '.docker', 'cli-plugins');
switch (process.platform) {
case 'linux':
case 'darwin':
return path.join(dir, 'docker-buildx');
case 'win32':
return path.join(dir, 'docker-buildx.exe');
}
};

module.exports = async (lando, options) => {
const debug = require('../utils/debug-shim')(lando.log);
const {color} = require('listr2');

// get stuff from config/opts
const {home} = lando.config;
const {buildx} = options;

// if buildx is set to false allow it to be skipped
if (buildx === false) return;

const dest = getBuildxDownloadDest(home);
const url = getBuildxDownloadUrl(buildx);

options.tasks.push({
title: `Downloading buildx`,
id: 'setup-buildx',
dependsOn: ['setup-build-engine'],
description: '@lando/buildx (docker-buildx)',
version: `Docker Buildx v${buildx}`,
hasRun: async () => {
try {
await require('../utils/run-command')('docker', ['buildx', 'version'], {debug});
return true;
} catch {
return false;
}
},
canRun: async () => {
// throw error if we cannot ping the download link
await axios.head(url);
// true if we get here
return true;
},
task: async (ctx, task) => new Promise((resolve, reject) => {
// ensure the cli-plugins directory exists
fs.mkdirSync(path.dirname(dest), {recursive: true});

const download = require('../utils/download-x')(url, {debug, dest, test: ['version']});
// success
download.on('done', data => {
task.title = `Installed buildx (Docker Buildx) to ${dest}`;
resolve(data);
});
// handle errors
download.on('error', error => {
reject(error);
});
// update title to reflect download progress
download.on('progress', progress => {
task.title = `Downloading buildx ${color.dim(`[${progress.percentage}%]`)}`;
});
}),
});
};
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ module.exports = async lando => {
// ensure we setup docker-compose if needed
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-orchestrator')(lando, options));

// ensure we setup buildx if needed
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-buildx')(lando, options));

// ensure we setup landonet
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-landonet')(lando, options));

Expand Down
6 changes: 6 additions & 0 deletions tasks/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ module.exports = lando => {
default: defaults.orchestrator,
string: true,
},
'buildx': {
describe: 'Sets the version of buildx to install',
default: defaults.buildx,
string: true,
},
'plugin': {
describe: 'Sets additional plugin(s) to install',
default: require('../utils/parse-to-plugin-strings')(defaults.plugins),
Expand Down Expand Up @@ -129,6 +134,7 @@ module.exports = lando => {
[--build-engine <version>]
[--build-engine-accept-license]
[--orchestrator <version>]
[--buildx <version>]
[--plugin <plugin>...]
[--skip-common-plugins]
[--skip-install-ca]
Expand Down
1 change: 1 addition & 0 deletions utils/get-config-defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const defaultConfig = options => ({
// @TODO: orchestrator works a bit differently because it predates lando.setup() we set it elsewhere
setup: {
buildEngine: getBuildEngineVersion(process.landoPlatform ?? process.platform),
buildx: '0.30.1',
buildEngineAcceptLicense: !require('is-interactive')(),
commonPlugins: {
'@lando/acquia': 'latest',
Expand Down
Loading