Source code for batools.docker

# Released under the MIT License. See LICENSE for details.
#
"""General functionality related to docker builds."""

import subprocess
import os

DOCKER_DIR = os.path.abspath('config/docker')
SERVICE_NAME = {0: 'bombsquad_gui', 1: 'bombsquad_server'}


def _docker_compose(
    image_name: str,
    service_name: str,
    dockercompose_file: str,
    *,
    cmake_build_type: str | None = None,
    platform: str | None = None,
    headless_build: bool | str | None = None,
    version: str | None = None,
    build_number: str | None = None,
) -> None:

    build_cmd = [
        'docker',
        'compose',
        '-f',
        dockercompose_file,
        'build',
        service_name,
    ]

    env = os.environ.copy()
    env['BS_IMAGE_NAME'] = image_name
    if version is not None:
        env['BS_VERSION'] = version
    if build_number is not None:
        env['BS_BUILD_NUMBER'] = build_number
    if cmake_build_type is not None:
        env['BS_CMAKE_BUILD_TYPE'] = cmake_build_type
    if headless_build is not None:
        env['BS_HEADLESS_BUILD'] = '1' if headless_build else '0'
    if platform is not None:
        env['PLATFORM'] = platform

    subprocess.run(build_cmd, check=True, env=env)


[docs] def docker_compose( platform: str | None = 'linux/amd64', headless_build: bool | str | None = None, build_type: str | None = None, ) -> None: """Compose docker image. platform == 'linux/arm64' or platform == 'linux/amd64'""" from batools import version version_num, build_num = version.get_current_version() if headless_build is None: headless_build = True if build_type is None: build_type = 'Release' image_name = get_docker_image_name( headless_build=headless_build, build_type=build_type ) compose_file = os.path.join(DOCKER_DIR, 'docker-compose.yml') print( '\n' + f'Building docker image \n\t{image_name} ' + f'\n\tversion {version_num}:{build_num}' ) service_name = SERVICE_NAME[1] if headless_build else SERVICE_NAME[0] _docker_compose( image_name, service_name, compose_file, platform=platform, headless_build=headless_build, cmake_build_type=build_type, version=version_num, build_number=str(build_num), )
[docs] def get_docker_image_name(headless_build: bool | str, build_type: str) -> str: """Get name of docker images in predefined format.""" name = 'bombsquad' if headless_build: name += '_server' else: name += '_gui' if 'release' in build_type.lower(): name += '_release' else: name += '_debug' return name
[docs] def docker_save_images() -> None: """Saves bombsquad images loaded into docker.""" output = subprocess.run( ['docker', 'images'], capture_output=True, text=True, check=True ) save_cmd = ['docker', 'save', '-o'] # we expect this directory is already present from Makefile build_save_dir = 'build/docker/' img_name = get_docker_image_name(headless_build=True, build_type='Release') if img_name in output.stdout: subprocess.run( save_cmd + [build_save_dir + img_name + '_docker.tar', img_name], check=True, ) img_name = get_docker_image_name(headless_build=True, build_type='Debug') if img_name in output.stdout: subprocess.run( save_cmd + [build_save_dir + img_name + '_docker.tar', img_name], check=True, ) img_name = get_docker_image_name(headless_build=False, build_type='Release') if img_name in output.stdout: subprocess.run( save_cmd + [build_save_dir + img_name + '_docker.tar', img_name], check=True, ) img_name = get_docker_image_name(headless_build=False, build_type='Debug') if img_name in output.stdout: subprocess.run( save_cmd + [build_save_dir + img_name + '_docker.tar', img_name], check=True, )
[docs] def docker_remove_images() -> None: """Remove the bombsquad images loaded in docker.""" output = subprocess.run( ['docker', 'images'], capture_output=True, text=True, check=True ) remove_cmd = [ 'docker', 'rmi', ] img_name = get_docker_image_name(headless_build=True, build_type='Release') if img_name in output.stdout: subprocess.run(remove_cmd + [img_name], check=True) img_name = get_docker_image_name(headless_build=True, build_type='Debug') if img_name in output.stdout: subprocess.run(remove_cmd + [img_name], check=True) img_name = get_docker_image_name(headless_build=False, build_type='Release') if img_name in output.stdout: subprocess.run(remove_cmd + [img_name], check=True) img_name = get_docker_image_name(headless_build=False, build_type='Debug') if img_name in output.stdout: subprocess.run(remove_cmd + [img_name], check=True)
# Unused, using docker compose instead def _docker_build( image_name: str, dockerfile_dir: str, *, cmake_build_type: str | None = None, labels: dict[str, str] | None = None, platform: str | None = None, headless_build: bool | str | None = None, ) -> None: build_cmd = [ 'docker', 'buildx', 'build', '--tag', image_name, '--file', dockerfile_dir, '--load', '.', ] if cmake_build_type is not None: build_cmd = build_cmd + [ '--build-arg', f'cmake_build_type={cmake_build_type}', ] if headless_build is not None: if headless_build: headless_build = '1' else: headless_build = '0' build_cmd = build_cmd + [ '--build-arg', f'headless_build={headless_build}', ] if platform is not None: build_cmd = build_cmd + [ '--platform', platform, ] if labels is not None: build_cmd = build_cmd + [ f'--label={i}={labels[i]}' for i in labels.keys() ] subprocess.run(build_cmd, check=True) # Unused, using docker compose instead
[docs] def docker_build( platform: str | None = 'linux/amd64', headless_build: bool | str | None = None, build_type: str | None = None, ) -> None: """Build docker image. platform == 'linux/arm64' or platform == 'linux/amd64'""" from batools import version version_num, build_num = version.get_current_version() if headless_build is None: headless_build = True if build_type is None: build_type = 'Release' image_name = get_docker_image_name( headless_build=headless_build, build_type=build_type ) config_file = 'config/docker/Dockerfile' print( f'Building docker image {image_name} ' + f'version {version_num}:{build_num}' ) _docker_build( image_name, config_file, labels={ 'bombsquad_version': version_num, 'bombsquad_build': str(build_num), }, platform=platform, headless_build=headless_build, cmake_build_type=build_type, )
# Docs-generation hack; import some stuff that we likely only forward-declared # in our actual source code so that docs tools can find it. from typing import (Coroutine, Any, Literal, Callable, Generator, Awaitable, Sequence, Self) import asyncio from concurrent.futures import Future from pathlib import Path from enum import Enum