def stage_deps(target, args): """Pull image dependencies into the `img` store. Arguments: target (taskboot.target.Target): Target args (argparse.Namespace): CLI arguments Returns: None """ create_cert(CA_KEY, CA_CRT, ca=True) create_cert(SRV_KEY, SRV_CRT, ca_key=CA_KEY, ca_cert=CA_CRT) img_tool = Img(cache=args.cache) # retrieve image archives from dependency tasks to /images image_path = Path(mkdtemp(prefix="image-deps-")) try: config = Configuration(Namespace(secret=None, config=None)) queue = taskcluster.Queue(config.get_taskcluster_options()) # load images into the img image store via Docker registry with Registry(): for task_id, artifact_name in load_artifacts( args.task_id, queue, "public/**.tar.zst"): img = download_artifact(queue, task_id, artifact_name, image_path) image_name = Path(artifact_name).stem check_call([ "skopeo", "copy", f"docker-archive:{img}", f"docker://localhost/mozillasecurity/{image_name}:latest", ]) img.unlink() img_tool.run( ["pull", f"localhost/mozillasecurity/{image_name}:latest"]) img_tool.run([ "tag", f"localhost/mozillasecurity/{image_name}:latest", f"{args.registry}/mozillasecurity/{image_name}:latest", ]) img_tool.run([ "tag", f"localhost/mozillasecurity/{image_name}:latest", (f"{args.registry}/mozillasecurity/" f"{image_name}:{args.git_revision}"), ]) finally: rmtree(image_path) # workaround https://github.com/genuinetools/img/issues/206 patch_dockerfile(target.check_path(args.dockerfile), img_tool.list_images())
def build_compose(target, args): """ Read a compose file and build each image described as buildable """ assert args.build_retries > 0, "Build retries must be a positive integer" build_tool = Img(cache=args.cache) # Check the dockerfile is available in target composefile = target.check_path(args.composefile) # Check compose file has version >= 3.0 compose = yaml.load(open(composefile)) version = compose.get("version") assert version is not None, "Missing version in {}".format(composefile) assert compose["version"].startswith( "3."), "Only docker compose version 3 is supported" # Check output folder output = None if args.write: output = os.path.realpath(args.write) os.makedirs(output, exist_ok=True) logger.info("Will write images in {}".format(output)) # Load services services = compose.get("services") assert isinstance(services, dict), "Missing services" # All paths are relative to the dockerfile folder root = os.path.dirname(composefile) for name, service in services.items(): build = service.get("build") if build is None: logger.info( "Skipping service {}, no build declaration".format(name)) continue if args.service and name not in args.service: msg = "Skipping service {}, building only {}".format( name, args.service) logger.info(msg) continue # Build the image logger.info("Building image for service {}".format(name)) context = os.path.realpath( os.path.join(root, build.get("context", "."))) dockerfile = os.path.realpath( os.path.join(context, build.get("dockerfile", "Dockerfile"))) # We need to replace the FROM statements by their local versions # to avoid using the remote repository first patch_dockerfile(dockerfile, build_tool.list_images()) docker_image = service.get("image", name) tags = gen_docker_images(docker_image, args.tag, args.registry) retry( lambda: build_tool.build(context, dockerfile, tags, args.build_arg ), wait_between_retries=1, retries=args.build_retries, ) # Write the produced image if output: build_tool.save(tags, os.path.join(output, "{}.tar".format(name))) logger.info("Compose file fully processed.")
def build_compose(target, args): ''' Read a compose file and build each image described as buildable ''' assert args.build_retries > 0, 'Build retries must be a positive integer' docker = Docker(cache=args.cache) # Check the dockerfile is available in target composefile = target.check_path(args.composefile) # Check compose file has version >= 3.0 compose = yaml.load(open(composefile)) version = compose.get('version') assert version is not None, 'Missing version in {}'.format(composefile) assert compose['version'].startswith('3.'), \ 'Only docker compose version 3 is supported' # Check output folder output = None if args.write: output = os.path.realpath(args.write) os.makedirs(output, exist_ok=True) logger.info('Will write images in {}'.format(output)) # Load services services = compose.get('services') assert isinstance(services, dict), 'Missing services' # All paths are relative to the dockerfile folder root = os.path.dirname(composefile) for name, service in services.items(): build = service.get('build') if build is None: logger.info( 'Skipping service {}, no build declaration'.format(name)) continue if args.service and name not in args.service: msg = 'Skipping service {}, building only {}'.format( name, args.service) logger.info(msg) continue # Build the image logger.info('Building image for service {}'.format(name)) context = os.path.realpath( os.path.join(root, build.get('context', '.'))) dockerfile = os.path.realpath( os.path.join(context, build.get('dockerfile', 'Dockerfile'))) # We need to replace the FROM statements by their local versions # to avoid using the remote repository first patch_dockerfile(dockerfile, docker.list_images()) docker_image = service.get('image', name) tags = gen_docker_images(docker_image, args.tag, args.registry) retry( lambda: docker.build(context, dockerfile, tags, args.build_arg), wait_between_retries=1, retries=args.build_retries, ) # Write the produced image if output: for tag in tags: docker.save(tag, os.path.join(output, '{}.tar'.format(name))) logger.info('Compose file fully processed.')
def patch(content, images): dockerfile = tmpdir.join(str(uuid.uuid4())) dockerfile.write(content) patch_dockerfile(str(dockerfile), images) return dockerfile.read()