Merge pull request #531 from crazy-max/docker-install-local-tcp
docker(install): opt to expose local tcp address
This commit is contained in:
30
.github/workflows/test.yml
vendored
30
.github/workflows/test.yml
vendored
@@ -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 });
|
||||
}
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -51,7 +51,10 @@ param(
|
||||
[string]$RunDir,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$DockerHost,
|
||||
[string]$DockerHostSocket,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$DockerHostTCP,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$DaemonConfig)
|
||||
@@ -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) {
|
||||
@@ -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!"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -285,6 +298,10 @@ hostResolver:
|
||||
portForwards:
|
||||
- guestSocket: "/var/run/docker.sock"
|
||||
hostSocket: "{{dockerSock}}"
|
||||
{{#if localTCPPort}}
|
||||
- guestPort: 2375
|
||||
hostPort: {{localTCPPort}}
|
||||
{{/if}}
|
||||
|
||||
audio:
|
||||
# EXPERIMENTAL
|
||||
|
||||
@@ -56,6 +56,7 @@ export interface InstallOpts {
|
||||
contextName?: string;
|
||||
daemonConfig?: string;
|
||||
rootless?: boolean;
|
||||
localTCPPort?: number;
|
||||
}
|
||||
|
||||
interface LimaImage {
|
||||
@@ -65,13 +66,15 @@ 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;
|
||||
|
||||
@@ -79,7 +82,6 @@ export class Install {
|
||||
|
||||
constructor(opts: InstallOpts) {
|
||||
this.runDir = opts.runDir;
|
||||
this.rootless = opts.rootless || false;
|
||||
this.source = opts.source || {
|
||||
type: 'archive',
|
||||
version: 'latest',
|
||||
@@ -87,6 +89,8 @@ export class Install {
|
||||
};
|
||||
this.contextName = opts.contextName || 'setup-docker-action';
|
||||
this.daemonConfig = opts.daemonConfig;
|
||||
this.rootless = opts.rootless || false;
|
||||
this.localTCPPort = opts.localTCPPort;
|
||||
}
|
||||
|
||||
get toolDir(): string {
|
||||
@@ -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)
|
||||
@@ -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) {
|
||||
@@ -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');
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user