Тьюториал docker-compose из python

Есть ли возможность запустить из python docker-compose, без запуска дополнительного процесса?


Ответы (1 шт):

Автор решения: hedgehogues

В тестах CLI docker-compose можно найти TopLevelCommand, который и является классом для запуска docker-compose.

Немного детальнее. Создадим несколько функций, который мы получили из вышеуказанного репозитория.

from compose.cli.command import get_project
from compose.cli.utils import get_version_info
from compose.cli.main import TopLevelCommand, setup_logging, setup_console_handler, console_handler, \
    set_no_color_if_clicolor, setup_parallel_logger, perform_command
from compose.cli import errors
from compose.cli.docopt_command import DocoptDispatcher
import functools


setup_logging()
dispatcher = DocoptDispatcher(
    TopLevelCommand,
    {'options_first': True, 'version': get_version_info('compose')})

options, handler, command_options = dispatcher.parse(sys.argv[1:])
setup_console_handler(console_handler,
                      options.get('--verbose'),
                      set_no_color_if_clicolor(options.get('--no-ansi')),
                      options.get("--log-level"))
setup_parallel_logger(set_no_color_if_clicolor(options.get('--no-ansi')))
if options.get('--no-ansi'):
    command_options['--no-color'] = True
cmd = functools.partial(perform_command, options, handler, command_options)
cmd()

Далее, можно сжать код до следующего:

from compose.cli.command import get_project
from compose.cli.utils import get_version_info
from compose.cli.main import TopLevelCommand
from compose.cli import errors
from compose.cli.docopt_command import DocoptDispatcher
import functools

def perform_command(options, handler, command_options):
    project_dir = '.'

    project = get_project(project_dir, options.get('--file'))
    command = TopLevelCommand(project, options=options)
    with errors.handle_connection_errors(project.client):
        handler(command, command_options)


def run(src_path=None):
    if src_path is None:
        src_path = './'
    dispatcher = DocoptDispatcher(
        TopLevelCommand,
        {'options_first': True, 'version': get_version_info('compose')},
    )

    cli_command = ['-f', 'docker-compose.yml', 'up', '-d']

    options, handler, command_options = dispatcher.parse(cli_command)
    command = functools.partial(perform_command, options, handler, command_options)
    command()

Этот кусок кода запускает docker-compose из файла, основываясь на cli интерфейсе.

Теперь, если заглянуть внутрь TopLevelCommand, в частности, внутрь up, то легко увидеть, что код сводится к следующему:

from compose.cli.command import get_project
from compose.cli.docopt_command import DocoptDispatcher

def run(src_path=None):
    if src_path is None:
        src_path = './'
    dispatcher = DocoptDispatcher(
        TopLevelCommand,
        {'options_first': True, 'version': get_version_info('compose')},
    )

    cli_command = ['-f', f'{src_path}docker-compose.yml', 'up', '-d']

    options, handler, command_options = dispatcher.parse(cli_command)
    project_dir = '.'
    project = get_project(project_dir, options.get('--file')).up()
    print(project)

И, затем, к следующему:

from compose.cli.command import get_project

def run(file_path, project_dir):
    servies = get_project(project_dir, [file_path]).up()
    return servies

где, в project хранится список запущенных сервисов.

Таким образом, если Вам требуется сократить число команд и вызывать docker-compose на уровне языка, следует выполнить команду, как написано в первом блоке, а затем проследить, какие конструкции языка используются.

→ Ссылка