Skip to content

Commit

Permalink
Merge pull request #531 from crazy-max/docker-install-local-tcp
Browse files Browse the repository at this point in the history
docker(install): opt to expose local tcp address
  • Loading branch information
crazy-max authored Dec 12, 2024
2 parents ba72b5a + 51e6621 commit 1d49775
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 32 deletions.
30 changes: 22 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,18 @@ jobs:
let includes = [];
for (const os of ['ubuntu-latest', 'macos-13', 'windows-latest']) {
for (const test of tests) {
if (os === 'macos-13' && test === 'docker/install.test.itg.ts') {
includes.push({ os: os, test: test, docker_install_type: 'image', docker_install_version: '27.3.1' });
includes.push({ os: os, test: test, docker_install_type: 'image', docker_install_version: 'master' });
includes.push({ os: os, test: test, docker_install_type: 'image', docker_install_version: 'latest' });
includes.push({ os: os, test: test, docker_install_type: 'archive', docker_install_version: 'v26.1.4' });
includes.push({ os: os, test: test, docker_install_type: 'archive', docker_install_version: 'latest' });
if (test === 'docker/install.test.itg.ts') {
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: '27.3.1' });
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: 'master' });
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: 'latest' });
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'archive', docker_install_version: 'v26.1.4' });
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'archive', docker_install_version: 'latest' });
if (os === 'ubuntu-latest') {
includes.push({ os: os, test: test, test_name: 'rootless', docker_install_type: 'image', docker_install_version: 'latest' });
includes.push({ os: os, test: test, test_name: 'rootless', docker_install_type: 'archive', docker_install_version: 'latest' });
}
includes.push({ os: os, test: test, test_name: 'tcp', docker_install_type: 'image', docker_install_version: 'latest' });
includes.push({ os: os, test: test, test_name: 'tcp', docker_install_type: 'archive', docker_install_version: 'latest' });
} else {
includes.push({ os: os, test: test });
}
Expand Down Expand Up @@ -176,8 +182,16 @@ jobs:
run: yarn install
-
name: Test
run: |
yarn test:itg-coverage --runTestsByPath __tests__/${{ matrix.test }} --coverageDirectory=./coverage
uses: actions/github-script@v7
with:
script: |
const testName = `${{ matrix.test_name }}`;
let args = ['test:itg-coverage'];
if (testName) {
args.push(`--testNamePattern=^${testName} `);
}
args.push(`--runTestsByPath`, `__tests__/${{ matrix.test }}`, `--coverageDirectory=./coverage`);
await exec.exec('yarn', args);
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CTN_BUILDER_NAME: ${{ steps.builder.outputs.name }}
Expand Down
30 changes: 30 additions & 0 deletions __tests__/docker/install.test.itg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,36 @@ describe('rootless', () => {
);
});

describe('tcp', () => {
// prettier-ignore
test.each(getSources(false))(
'install %s', async (source) => {
await ensureNoSystemContainerd();
const install = new Install({
source: source,
runDir: tmpDir(),
contextName: 'foo',
daemonConfig: `{"debug":true}`,
localTCPPort: 2378
});
await expect(
tryInstall(install, async () => {
const out = await Docker.getExecOutput(['info'], {
env: Object.assign({}, process.env, {
DOCKER_HOST: 'tcp://localhost:2378',
DOCKER_CONTENT_TRUST: 'false'
}) as {
[key: string]: string;
}
});
expect(out.exitCode).toBe(0);
})
).resolves.not.toThrow();
},
30 * 60 * 1000
);
});

async function tryInstall(install: Install, extraCheck?: () => Promise<void>): Promise<void> {
try {
await install.download();
Expand Down
37 changes: 27 additions & 10 deletions src/docker/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ param(
[string]$RunDir,
[Parameter(Mandatory = $true)]
[string]$DockerHost,
[string]$DockerHostSocket,
[Parameter(Mandatory = $false)]
[string]$DockerHostTCP,
[Parameter(Mandatory = $false)]
[string]$DaemonConfig)
Expand Down Expand Up @@ -82,7 +85,7 @@ if (Get-Service docker -ErrorAction SilentlyContinue) {
$env:Path = "$ToolDir;" + [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Write-Host "Path: $env:Path"
$env:DOCKER_HOST = $DockerHost
$env:DOCKER_HOST = $DockerHostSocket
Write-Host "DOCKER_HOST: $env:DOCKER_HOST"
if ($DaemonConfig) {
Expand All @@ -91,16 +94,21 @@ if ($DaemonConfig) {
$DaemonConfig | Out-File -FilePath "$env:ProgramData\\Docker\\config\\daemon.json"
}
$arguments = @(
"--host=$DockerHostSocket",
"--data-root=$RunDir\\\\moby-root",
"--exec-root=$RunDir\\\\moby-exec",
"--pidfile=$RunDir\\\\docker.pid",
"--register-service"
)
if ($DockerHostTCP) {
$arguments += "--host=$DockerHostTCP"
}
Write-Host "Creating service"
New-Item -ItemType Directory "$RunDir\\moby-root" -ErrorAction SilentlyContinue | Out-Null
New-Item -ItemType Directory "$RunDir\\moby-exec" -ErrorAction SilentlyContinue | Out-Null
Start-Process -Wait -NoNewWindow "$ToolDir\\dockerd" \`
-ArgumentList \`
"--host=$DockerHost", \`
"--data-root=$RunDir\\moby-root", \`
"--exec-root=$RunDir\\moby-exec", \`
"--pidfile=$RunDir\\docker.pid", \`
"--register-service"
Start-Process -Wait -NoNewWindow "$ToolDir\\dockerd" -ArgumentList $arguments
Write-Host "Starting service"
Start-Service -Name docker
Write-Host "Service started successfully!"
Expand Down Expand Up @@ -231,6 +239,11 @@ provision:
export DEBIAN_FRONTEND=noninteractive
if [ "{{srcType}}" == "archive" ]; then
curl -fsSL https://get.docker.com | sh -s -- --channel {{srcArchiveChannel}} --version {{srcArchiveVersion}}
sed -i 's|^ExecStart=.*|ExecStart=/usr/bin/dockerd -H fd://{{#if localTCPPort}} -H tcp://0.0.0.0:2375{{/if}} --containerd=/run/containerd/containerd.sock|' /usr/lib/systemd/system/docker.service
systemctl daemon-reload
systemctl restart docker
systemctl status docker.socket || true
systemctl status docker.service || true
elif [ "{{srcType}}" == "image" ]; then
arch=$(uname -m)
case $arch in
Expand All @@ -250,7 +263,7 @@ provision:
wget https://raw.githubusercontent.com/moby/moby/{{gitCommit}}/contrib/init/systemd/docker.socket \
-O /etc/systemd/system/docker.socket
sed -i 's|^ExecStart=.*|ExecStart=/usr/local/bin/dockerd -H fd://|' /etc/systemd/system/docker.service
sed -i 's|^ExecStart=.*|ExecStart=/usr/local/bin/dockerd -H fd://{{#if localTCPPort}} -H tcp://0.0.0.0:2375{{/if}}|' /etc/systemd/system/docker.service
sed -i 's|containerd.service||' /etc/systemd/system/docker.service
if ! getent group docker; then
groupadd --system docker
Expand Down Expand Up @@ -285,6 +298,10 @@ hostResolver:
portForwards:
- guestSocket: "/var/run/docker.sock"
hostSocket: "{{dockerSock}}"
{{#if localTCPPort}}
- guestPort: 2375
hostPort: {{localTCPPort}}
{{/if}}
audio:
# EXPERIMENTAL
Expand Down
40 changes: 26 additions & 14 deletions src/docker/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export interface InstallOpts {
contextName?: string;
daemonConfig?: string;
rootless?: boolean;
localTCPPort?: number;
}

interface LimaImage {
Expand All @@ -65,28 +66,31 @@ interface LimaImage {
}

export class Install {
private runDir: string;
private readonly runDir: string;
private readonly source: InstallSource;
private readonly contextName: string;
private readonly daemonConfig?: string;
private readonly rootless: boolean;
private readonly localTCPPort?: number;

private _version: string | undefined;
private _toolDir: string | undefined;
private rootless: boolean;

private gitCommit: string | undefined;

private readonly limaInstanceName = 'docker-actions-toolkit';

constructor(opts: InstallOpts) {
this.runDir = opts.runDir;
this.rootless = opts.rootless || false;
this.source = opts.source || {
type: 'archive',
version: 'latest',
channel: 'stable'
};
this.contextName = opts.contextName || 'setup-docker-action';
this.daemonConfig = opts.daemonConfig;
this.rootless = opts.rootless || false;
this.localTCPPort = opts.localTCPPort;
}

get toolDir(): string {
Expand Down Expand Up @@ -268,6 +272,7 @@ export class Install {
customImages: Install.limaCustomImages(),
daemonConfig: limaDaemonConfig,
dockerSock: `${limaDir}/docker.sock`,
localTCPPort: this.localTCPPort,
gitCommit: this.gitCommit,
srcType: src.type,
srcArchiveVersion: this._version, // Use the resolved version (e.g. latest -> 27.4.0)
Expand Down Expand Up @@ -376,8 +381,10 @@ export class Install {
await Exec.exec('sudo', ['sh', '-c', 'echo 0 > /proc/sys/kernel/apparmor_restrict_unprivileged_userns']);
}
}

const cmd = `${dockerPath} --host="${dockerHost}" --config-file="${daemonConfigPath}" --exec-root="${this.runDir}/execroot" --data-root="${this.runDir}/data" --pidfile="${this.runDir}/docker.pid"`;
let cmd = `${dockerPath} --host="${dockerHost}" --config-file="${daemonConfigPath}" --exec-root="${this.runDir}/execroot" --data-root="${this.runDir}/data" --pidfile="${this.runDir}/docker.pid"`;
if (this.localTCPPort) {
cmd += ` --host="tcp://127.0.0.1:${this.localTCPPort}"`;
}
core.info(`[command] ${cmd}`); // https://github.com/actions/toolkit/blob/3d652d3133965f63309e4b2e1c8852cdbdcb3833/packages/exec/src/toolrunner.ts#L47
let sudo = 'sudo';
if (this.rootless) {
Expand Down Expand Up @@ -438,7 +445,7 @@ EOF`,
}

private async installWindows(): Promise<string> {
const dockerHost = 'npipe:////./pipe/setup_docker_action';
const dockerHostSocket = 'npipe:////./pipe/setup_docker_action';

let daemonConfig = undefined;
const daemonConfigPath = path.join(this.runDir, 'daemon.json');
Expand All @@ -460,24 +467,29 @@ EOF`,
});
}

const params = {
ToolDir: this.toolDir,
RunDir: this.runDir,
DockerHostSocket: dockerHostSocket,
DaemonConfig: daemonConfigStr
};
if (this.localTCPPort) {
params['DockerHostTCP'] = `tcp://127.0.0.1:${this.localTCPPort}`;
}

await core.group('Install Docker daemon service', async () => {
const setupCmd = await Util.powershellCommand(setupDockerWinPs1(), {
ToolDir: this.toolDir,
RunDir: this.runDir,
DockerHost: dockerHost,
DaemonConfig: daemonConfigStr
});
const setupCmd = await Util.powershellCommand(setupDockerWinPs1(), params);
await Exec.exec(setupCmd.command, setupCmd.args);
const logCmd = await Util.powershellCommand(dockerServiceLogsPs1());
await Exec.exec(logCmd.command, logCmd.args);
});

await core.group('Create Docker context', async () => {
await Docker.exec(['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]);
await Docker.exec(['context', 'create', this.contextName, '--docker', `host=${dockerHostSocket}`]);
await Docker.exec(['context', 'use', this.contextName]);
});

return dockerHost;
return dockerHostSocket;
}

public async tearDown(): Promise<void> {
Expand Down

0 comments on commit 1d49775

Please sign in to comment.