Skip to content

Commit af9c58c

Browse files
committed
Support image source on darwin
Signed-off-by: Paweł Gronowski <[email protected]>
1 parent b143889 commit af9c58c

File tree

4 files changed

+54
-20
lines changed

4 files changed

+54
-20
lines changed

__tests__/docker/install.test.itg.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ aarch64:https://cloud.debian.org/images/cloud/bookworm/20231013-1532/debian-12-g
4141
});
4242
// prettier-ignore
4343
test.each([
44-
{type: 'archive', version: 'v26.1.4', channel: 'stable'} as InstallSourceArchive,
4544
{type: 'image', tag: '27.3.1'} as InstallSourceImage,
45+
{type: 'image', tag: 'master'} as InstallSourceImage,
46+
{type: 'archive', version: 'v26.1.4', channel: 'stable'} as InstallSourceArchive,
4647
])(
4748
'install docker %s', async (source) => {
4849
if (process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) {

src/docker/assets.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ disk: 60GiB
176176
# This file: Mount the home as read-only, /tmp/lima as writable
177177
mounts:
178178
- location: "~"
179+
- location: "{{toolDir}}"
180+
mountPoint: /tool
179181
- location: "/tmp/lima"
180182
writable: true
181183
@@ -221,16 +223,35 @@ provision:
221223
EOF
222224
fi
223225
export DEBIAN_FRONTEND=noninteractive
224-
curl -fsSL https://get.docker.com | sh -s -- --channel {{dockerBinChannel}} --version {{dockerBinVersion}}
226+
if [ {{srcType}} == "archive" ]; then
227+
curl -fsSL https://get.docker.com | sh -s -- --channel {{srcArchiveChannel}} --version {{srcArchiveVersion}}
228+
elif [ {{srcType}} == "image" ]; then
229+
wget https://raw.githubusercontent.com/moby/moby/{{srcImageTag}}/contrib/init/systemd/docker.service \
230+
https://raw.githubusercontent.com/moby/moby/v{{srcImageTag}}/contrib/init/systemd/docker.service \
231+
-O /etc/systemd/system/docker.service || true
232+
wget https://raw.githubusercontent.com/moby/moby/{{srcImageTag}}/contrib/init/systemd/docker.socket \
233+
https://raw.githubusercontent.com/moby/moby/v{{srcImageTag}}/contrib/init/systemd/docker.socket \
234+
-O /etc/systemd/system/docker.socket || true
235+
236+
mkdir -p /usr/local/bin
237+
cp /tool/* /usr/local/bin/
238+
sed -i 's|^ExecStart=.*|ExecStart=/usr/local/bin/dockerd -H fd://|' /etc/systemd/system/docker.service
239+
sed -i 's|containerd.service||' /etc/systemd/system/docker.service
240+
if ! getent group docker; then
241+
groupadd --system docker
242+
fi
243+
systemctl daemon-reload
244+
if ! systemctl enable --now docker; then
245+
systemctl status docker.socket
246+
systemctl status docker.service
247+
fi
248+
fi
225249
226250
probes:
227251
- script: |
228252
#!/bin/bash
229253
set -eux -o pipefail
230-
if ! timeout 30s bash -c "until command -v docker >/dev/null 2>&1; do sleep 3; done"; then
231-
echo >&2 "docker is not installed yet"
232-
exit 1
233-
fi
254+
# Don't check for docker CLI as it's not installed in the VM (only on the host)
234255
if ! timeout 30s bash -c "until pgrep dockerd; do sleep 3; done"; then
235256
echo >&2 "dockerd is not running"
236257
exit 1

src/docker/install.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,16 @@ export class Install {
127127
const cli = await HubRepository.build('dockereng/cli-bin');
128128
extractFolder = await cli.extractImage(tag);
129129

130-
// Daemon is only available for Windows and Linux
131-
if (['win32', 'linux'].includes(platform)) {
130+
if (['win32', 'linux', 'darwin'].includes(platform)) {
132131
core.info(`Downloading dockerd from moby/moby-bin:${tag}`);
133132
const moby = await HubRepository.build('moby/moby-bin');
134-
await moby.extractImage(tag, extractFolder);
133+
134+
// On macOS, we extract the Linux version of dockerd which will be run in a lima VM.
135+
const extractPlatform = platform == 'darwin' ? 'linux' : undefined;
136+
137+
await moby.extractImage(tag, extractFolder, extractPlatform);
135138
} else {
136-
core.info(`dockerd not supported on ${platform}`);
139+
core.warning(`dockerd not supported on ${platform}, only the Docker cli will be available`);
137140
}
138141
break;
139142
}
@@ -192,14 +195,19 @@ export class Install {
192195
}
193196

194197
private async installDarwin(): Promise<string> {
195-
if (this.source.type !== 'archive') {
196-
throw new Error('Only archive source is supported on macOS');
197-
}
198-
const src = this.source as InstallSourceArchive;
198+
const src = this.source;
199199
const limaDir = path.join(os.homedir(), '.lima', this.limaInstanceName);
200200
await io.mkdirP(limaDir);
201201
const dockerHost = `unix://${limaDir}/docker.sock`;
202202

203+
// this.toolDir is a very long path which causes trouble when mounting it in lima.
204+
// Copy it to a shorter path.
205+
const limaToolsDir = path.join(os.homedir(), 'tools-' + this._version);
206+
207+
await core.group('Copy tools', async () => {
208+
await Exec.exec('cp', ['-rv', this.toolDir, limaToolsDir]);
209+
});
210+
203211
// avoid brew to auto update and upgrade unrelated packages.
204212
let envs = Object.assign({}, process.env, {
205213
HOMEBREW_NO_AUTO_UPDATE: '1',
@@ -226,12 +234,16 @@ export class Install {
226234
handlebars.registerHelper('stringify', function (obj) {
227235
return new handlebars.SafeString(JSON.stringify(obj));
228236
});
237+
const srcArchive = src as InstallSourceArchive;
229238
const limaCfg = handlebars.compile(limaYamlData)({
230239
customImages: Install.limaCustomImages(),
231240
daemonConfig: limaDaemonConfig,
232241
dockerSock: `${limaDir}/docker.sock`,
233-
dockerBinVersion: src.version.replace(/^v/, ''),
234-
dockerBinChannel: src.channel
242+
srcType: src.type,
243+
srcArchiveVersion: srcArchive.version?.replace(/^v/, ''),
244+
srcArchiveChannel: srcArchive.channel,
245+
srcImageTag: (src as InstallSourceImage).tag,
246+
toolDir: limaToolsDir
235247
});
236248
core.info(`Writing lima config to ${path.join(limaDir, 'lima.yaml')}`);
237249
fs.writeFileSync(path.join(limaDir, 'lima.yaml'), limaCfg);

src/hubRepository.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ export class HubRepository {
4242

4343
// Unpacks the image layers and returns the path to the extracted image.
4444
// Only OCI indexes/manifest list are supported for now.
45-
public async extractImage(tag: string, destDir?: string): Promise<string> {
45+
public async extractImage(tag: string, destDir?: string, osPlatform?: string): Promise<string> {
4646
const index = await this.getManifest<Index>(tag);
4747
if (index.mediaType != MEDIATYPE_IMAGE_INDEX_V1 && index.mediaType != MEDIATYPE_IMAGE_MANIFEST_LIST_V2) {
4848
throw new Error(`Unsupported image media type: ${index.mediaType}`);
4949
}
50-
const digest = HubRepository.getPlatformManifestDigest(index);
50+
const digest = HubRepository.getPlatformManifestDigest(index, osPlatform);
5151
const manifest = await this.getManifest<Manifest>(digest);
5252

5353
const paths = manifest.layers.map(async layer => {
@@ -115,9 +115,9 @@ export class HubRepository {
115115
return <T>JSON.parse(body);
116116
}
117117

118-
private static getPlatformManifestDigest(index: Index): string {
118+
private static getPlatformManifestDigest(index: Index, osPlatform?: string): string {
119119
// This doesn't handle all possible platforms normalizations, but it's good enough for now.
120-
let pos: string = os.platform();
120+
let pos: string = osPlatform || os.platform();
121121
if (pos == 'win32') {
122122
pos = 'windows';
123123
}

0 commit comments

Comments
 (0)