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