Skip to content
Merged
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ const executor = new DockerExecutor({

For more information on `start`, `stop`, and `stats` please see the [executor-base].

### Job annotations

| Annotation | Type | Description |
| :--------- | :--- | :----------- |
| `screwdriver.cd/dockerEnabled` | Boolean | Opts the build container into `Privileged` mode with the host's Docker socket (`/var/run/docker.sock`) bind-mounted in. Off by default — only enable this for jobs that specifically need to build or run Docker containers, since it grants the build full host-level access. |

## Testing

```bash
Expand Down
9 changes: 7 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ class DockerExecutor extends Executor {
* @param {Integer} config.buildId ID for the build
* @param {String} config.container Container for the build to run in
* @param {String} config.token JWT for the Build
* @param {Object} [config.annotations] Job annotations. `screwdriver.cd/dockerEnabled` opts
* the build container into `Privileged` mode with the host's
* Docker socket mounted in; both are off by default.
* @return {Promise}
*/

Expand All @@ -141,6 +144,8 @@ class DockerExecutor extends Executor {
let buildImage = piecesParts.name;
const buildTimeout = hoek.reach(config, 'annotations>screwdriver.cd/timeout', { separator: '>' });
const timeout = parseInt(buildTimeout || DEFAULT_BUILD_TIMEOUT, 10);
const dockerEnabled =
hoek.reach(config, 'annotations>screwdriver.cd/dockerEnabled', { separator: '>' }) === true;

/**
*
Expand Down Expand Up @@ -209,8 +214,8 @@ class DockerExecutor extends Executor {
// 3 GB of memory + swap (aka, 1 GB of swap)
MemoryLimit: 3 * 1024 * 1024 * 1024,
VolumesFrom: [`${launchContainer.id}:rw`],
Privileged: true,
Binds: ['/var/run/docker.sock:/var/run/docker.sock']
Privileged: dockerEnabled,
Binds: dockerEnabled ? ['/var/run/docker.sock:/var/run/docker.sock'] : []
}
})
)
Expand Down
75 changes: 71 additions & 4 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ describe('index', function () {
Memory: 2 * 1024 * 1024 * 1024,
MemoryLimit: 3 * 1024 * 1024 * 1024,
VolumesFrom: ['launcherID:rw'],
Privileged: true,
Binds: ['/var/run/docker.sock:/var/run/docker.sock']
Privileged: false,
Binds: []
}
};
});
Expand Down Expand Up @@ -212,6 +212,73 @@ describe('index', function () {
});
});

it('defaults to Privileged: false and no docker socket bind', () => {
dockerMock.createContainer.yieldsAsync(new Error('bad container args'));
dockerMock.createContainer.withArgs(launcherArgs).yieldsAsync(null, launcherContainer);
dockerMock.createContainer.withArgs(buildArgs).yieldsAsync(null, buildContainer);

return executor
.start({
buildId,
container,
apiUri,
token
})
.then(() => {
const containerArgs = dockerMock.createContainer.secondCall.args[0];

assert.isFalse(containerArgs.HostConfig.Privileged);
assert.deepEqual(containerArgs.HostConfig.Binds, []);
});
});

it('enables Privileged mode and the docker socket bind when screwdriver.cd/dockerEnabled is set', () => {
buildArgs.HostConfig.Privileged = true;
buildArgs.HostConfig.Binds = ['/var/run/docker.sock:/var/run/docker.sock'];

dockerMock.createContainer.yieldsAsync(new Error('bad container args'));
dockerMock.createContainer.withArgs(launcherArgs).yieldsAsync(null, launcherContainer);
dockerMock.createContainer.withArgs(buildArgs).yieldsAsync(null, buildContainer);

return executor
.start({
buildId,
container,
apiUri,
token,
annotations: {
'screwdriver.cd/dockerEnabled': true
}
})
.then(() => {
assert.calledWith(dockerMock.createContainer, buildArgs);
assert.callCount(buildContainer.start, 1);
});
});

it('keeps Privileged: false and no docker socket bind when screwdriver.cd/dockerEnabled is the string "false"', () => {
dockerMock.createContainer.yieldsAsync(new Error('bad container args'));
dockerMock.createContainer.withArgs(launcherArgs).yieldsAsync(null, launcherContainer);
dockerMock.createContainer.withArgs(buildArgs).yieldsAsync(null, buildContainer);

return executor
.start({
buildId,
container,
apiUri,
token,
annotations: {
'screwdriver.cd/dockerEnabled': 'false'
}
})
.then(() => {
const containerArgs = dockerMock.createContainer.secondCall.args[0];

assert.isFalse(containerArgs.HostConfig.Privileged);
assert.deepEqual(containerArgs.HostConfig.Binds, []);
});
});

it('supports prefixed containers', () => {
const prefix = 'beta_';
const buildImageArgs = {
Expand Down Expand Up @@ -239,8 +306,8 @@ describe('index', function () {
Memory: 2 * 1024 * 1024 * 1024,
MemoryLimit: 3 * 1024 * 1024 * 1024,
VolumesFrom: ['launcherID:rw'],
Privileged: true,
Binds: ['/var/run/docker.sock:/var/run/docker.sock']
Privileged: false,
Binds: []
}
};

Expand Down