Commit 3d8b3588 authored by Michał Kępień's avatar Michał Kępień

Add an executor for Docker on Windows Server 2016

parent 4e69dde3
Pipeline #54697 passed with stage
in 8 seconds
# GitLab Runner Custom Executor for Docker on Windows Server 2016
## Overview
This Python script allows GitLab CI jobs to be run inside Docker
containers on Windows Server 2016, which is [not supported][1] by the
native Docker executor included in GitLab Runner.
## Prerequisites
- [GitLab Runner][2]
- [Docker][3]
- [Python 3.6+][4]
## Installation
- Register a new GitLab CI runner using `gitlab-runner.exe register`,
specifying `custom` as the executor to use.
- Adjust the relevant section of GitLab Runner's `config.toml` so
that the executor gets invoked properly:
shell = "powershell"
config_exec = "C:\\path\\to\\python\\python.exe"
config_args = [ "C:\\path\\to\\windows-docker\\", "config" ]
prepare_exec = "C:\\path\\to\\python\\python.exe"
prepare_args = [ "C:\\path\\to\\windows-docker\\", "prepare" ]
run_exec = "C:\\path\\to\\python\\python.exe"
run_args = [ "C:\\path\\to\\windows-docker\\", "run" ]
cleanup_exec = "C:\\path\\to\\python\\python.exe"
cleanup_args = [ "C:\\path\\to\\windows-docker\\", "cleanup" ]
## Limitations
- Docker images are *not* automatically pulled or updated to the latest
available version during job setup. `docker pull` needs to be either
run manually or from the Windows Task Scheduler.
import json
import os
import subprocess
import sys
DOCKER_PATH = 'C:\\Program Files\\Docker\\docker.exe'
def fatal_error(message):
print(message, file=sys.stderr)
def docker_command(cmd):
try:[DOCKER_PATH] + cmd, check=True)
except subprocess.CalledProcessError:
def do_config(*_):
config = {
'builds_dir': 'C:\\builds',
'cache_dir': 'C:\\cache',
'builds_dir_is_shared': False,
def do_prepare(container_name, _):
'--name', container_name,
def do_run(container_name, args):
valid_stages = [
script_src = args[0]
stage = args[1]
if stage not in valid_stages:
fatal_error(f'Unsupported run stage "{stage}"')
script_dst_path = f'C:\\{stage}.ps1'
script_dst = f'{container_name}:{script_dst_path}'
docker_command(['cp', script_src, script_dst])
docker_command(['exec', container_name, 'powershell.exe', script_dst_path])
def do_cleanup(container_name, _):
docker_command(['stop', container_name])
def main():
actions = {
'config': do_config,
'prepare': do_prepare,
'run': do_run,
'cleanup': do_cleanup,
valid_actions = '|'.join(actions.keys())
action = actions[sys.argv[1]]
except (IndexError, KeyError):
fatal_error(f'Usage: {sys.argv[0]} {valid_actions} [args...]')
container_name = 'gitlab-runner-' + os.environ['CUSTOM_ENV_CI_JOB_ID']
action(container_name, sys.argv[2:])
if __name__ == '__main__':
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment