Skip to content

Instantly share code, notes, and snippets.

@hkumarmk
Last active September 29, 2015 12:17
Show Gist options
  • Save hkumarmk/3c60a9b5e00820481922 to your computer and use it in GitHub Desktop.
Save hkumarmk/3c60a9b5e00820481922 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import argparse
import sys
import os
import shutil
import glob
from jinja2 import Environment, FileSystemLoader
from docker import Client
from tempfile import mkdtemp
def docker_client(url='unix://var/run/docker.sock'):
""" return docker client """
return Client(url)
def build_image(docker_client, path, tag):
""" Build docker image"""
return [ ''.join(line.values()).strip() for line in docker_client.build(path=path, rm=True, forcerm=True, tag=tag, decode=True)]
def create_container(docker_client, image, name=None, command=None, env=None, disable_network=False, shared_volumes=None, cwd=None):
""" create docker containers """
if shared_volumes:
volumes = shared_volumes.values()
binds = ['{}:{}'.format(k,v) for k,v in shared_volumes.iteritems()]
host_config=docker_client.create_host_config(binds=binds)
else:
host_config=None
container = docker_client.create_container(image=image, name=name, command=command,
environment=env, network_disabled=disable_network,
volumes=volumes, working_dir=cwd,
host_config=host_config)
return container
def start_container(docker_client, container):
""" Start docker container """
response = docker_client.start(container=container.get('Id'))
return response
def wait_container(docker_client, container):
""" Wait the container to finish execution """
rv = docker_client.wait(container=container)
return rv
def container_logs(docker_client, container):
""" Get container stdout and stderr """
return [log.strip() for log in docker_client.logs(container=container, stream=True, timestamps=True)]
def remove_container(docker_client, container, force=False):
""" Remove docker container """
return docker_client.remove_container(container=container, force=force)
def docker_build(docker_path, build_dir, build_type, source_dir='source', force_rm=False, docker_url='unix://var/run/docker.sock', flavor='ubuntu', dist='trusty'):
c = docker_client(docker_url)
print "Starting %s Package Build" % build_type
image_tag='dbuild-' + flavor + '/' + dist
response = build_image(c, docker_path, tag=image_tag )
print '\n'.join(response)
if build_type == 'source':
command = ['dpkg-buildpackage', '-S', '-nc', '-uc', '-us']
cwd = '/build/' + source_dir
elif build_type == 'binary':
command = ['bash', '-c', "dpkg-source -x /build/*.dsc /build/pkgbuild/ && cd /build/pkgbuild && /usr/lib/pbuilder/pbuilder-satisfydepends && dpkg-buildpackage"]
cwd = '/build'
else:
raise Exception('Unknown build_type %s' % build_type)
container = create_container(c, image_tag,command=command, shared_volumes={build_dir: '/build'}, cwd=cwd)
print(container)
response = start_container(c, container)
rv = wait_container(c, container)
logs = container_logs(c, container)
print '\n'.join(logs)
if rv == 0:
print 'Build successful (build type: %s), removing container %s' % (build_type, container.get('Id'))
remove_container(c, container, force=True)
return True
else:
if force_rm:
print "Build failed (build type: %s), Removing container %s" % (build_type, container.get('Id'))
remove_container(c, container, force=True)
return False
else:
print "Build failed (build type: %s), keeping container %s" % (build_type, container.get('Id'))
return False
def main(argv=sys.argv):
ap = argparse.ArgumentParser(description='Build debian packages in docker container')
ap.add_argument('--build_dir', type=str, help='package build directory')
ap.add_argument('--source_dir', type=str, default='source',
help='subdirectory of build_dir where sources kept')
ap.add_argument('--force_rm', action='store_true', default=False,
help='Remove the containers even if build failed')
ap.add_argument('--docker_url', type=str,
default='unix://var/run/docker.sock',
help='Docker url, it can be unix socket or tcp url')
ap.add_argument('--flavor', type=str, default='ubuntu',
help='Linux flavor to use for container to build')
ap.add_argument('--dist', type=str, default='trusty',
help='Linux distribution')
args = ap.parse_args()
PATH = os.path.dirname(os.path.abspath(__file__))
TMPL_ENV = Environment(
autoescape=False,
loader=FileSystemLoader(os.path.join(PATH, 'templates')),
trim_blocks=False)
docker_dir = mkdtemp()
dockerfile = os.path.join(docker_dir, 'Dockerfile')
ctxt = {'flavor': args.flavor, 'dist': args.dist,
'maintainer': 'dbuild, [email protected]', }
with open(dockerfile, 'w') as d:
dockerdata = TMPL_ENV.get_template('dockerfile.jinja').render(ctxt)
d.write(dockerdata)
script_dir = os.path.join(PATH, 'scripts/')
for f in glob.glob(os.path.join(script_dir, '*')):
if os.path.isfile(f):
shutil.copy2(f, docker_dir)
source_build_rv = docker_build(docker_dir, build_dir=args.build_dir,
build_type='source', source_dir=args.source_dir,
force_rm=args.force_rm, docker_url=args.docker_url,
flavor=args.flavor, dist=args.dist)
if source_build_rv:
binary_build_rv = docker_build(docker_dir, build_dir=args.build_dir,
build_type='binary', source_dir=args.source_dir,
force_rm=args.force_rm, docker_url=args.docker_url,
flavor=args.flavor, dist=args.dist)
shutil.rmtree(docker_dir)
return binary_build_rv
else:
shutil.rmtree(docker_dir)
return source_build_rv
if __name__ == "__main__":
sys.exit(not main(sys.argv))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment