Три приема работы с Docker из программы на Python (перевод)

На написание этой истории меня вдохновили собственные тщетные попытки написать на питоне докероподобный демон для управления контейнерами.

Прием № 1: Docker для Python

pip install docker

С Docker можно работать и в командной строке, но из программы на Python через API это делать гораздо удобнее. Там можно получить список контейнеров, пробежаться по их атрибутам и делать достаточно мощные и интересные вещи, в том числе и с использованием приемов работы, о которых я говорю ниже.

import docker
client = docker.from_env()
# запуск контейнера
client.containers.run("ubuntu", "echo hello world")
client.containers.list()
container = client.containers.get('45e6d2de7c54')
pid = container.attrs['State']['Pid']

Прием № 2: пространства имен для Python

pip install nsenter

За эту вещь надо благодарить парней из Zalando. Nsenter — обвязка для C API, позволяющая работать на уровне пространства имен ядра (kernel namespace). В Docker каждый контейнер выполняется в его собственном пространстве имен. Таким образом он отделяется и защищается от влияния других контейнеров на хосте, изолируется от них. Более подробную информацию можно получить, прочитав их замечательную статью.

Nsenter очень прост в использовании. Допустим, вы запускаете новый nginx-контейнер командной docker run -d nginx и получаете его ID = 277906bc266c.

С помощью приведенного ниже кода можно получить ID процесса интересующего контейнера. При наличии этого идентификатора появляется возможность выполнить команду в пространстве имен контейнера, прогуляться по файловой системе или даже что-нибудь поломать.

import subprocess
import sys
from nsenter import Namespace
mypid = sys.argv[1]
with Namespace(mypid, 'net'):
# вывести сетевые интерфейсы так, как они видны из пространства имен процесса mypid:
subprocess.check_output(['ip', 'a'])

Зачем все это? Чтобы отладить пару багов в выполняющемся внутри контейнера коде, вам наверняка периодически приходится переключаться между сессиями bash (мне? никогда!). Эту командную оболочку совсем не зря назвали Bash (англ. bash — сильный удар). Зачем лупить молотком, если можно взять звуковую отвертку (sonic screwdriver)?

Прием № 3: cgroups для Python

pip install cgroups

Docker использует контрольные группы, чтобы ограничить процессы, не давая им захватить все доступные на хосте ресурсы. Пакет cgroups позволяет создавать, выводить список, а также манипулировать существующими на хосте группами cgroups. Например, ограничения на использование CPU контейнеру по умолчанию не установлены, поэтому с помощью Python можно динамически управлять ресурсами хоста. В следующем примере новый процесс после запуска перемещается в cgroup. То же самое можно проделать и с существующим процессом, запущенным Докером.

from cgroups import Cgroup
from cgroups.user import create_user_cgroups
import os
import subprocess
try:
# Устанавливаем для пользователя директории cgroup
user = os.getlogin()
create_user_cgroups(user)
    # Создаем cgroup и устанавливаем лимиты на cpu и память
cg = Cgroup(name)
cg.set_cpu_limit(50) # TODO : получать эти значения из опций командной строки
cg.set_memory_limit(500)
    # Создадим функцию добавления процесса в cgroup
def in_cgroup():
try:
pid = os.getpid()
cg = Cgroup(name)
for env in env_vars:
log.info('Setting ENV %s' % env)
os.putenv(*env.split('=', 1))
            # add process to cgroup
cg.add(pid)
            os.chroot(layer_dir)
if working_dir != '':
log.info("Setting working directory to %s" % working_dir)
os.chdir(working_dir)
except Exception as e:
traceback.print_exc()
log.error("Failed to preexecute function")
log.error(e)
cmd = start_cmd
log.info('Running "%s"' % cmd)
process = subprocess.Popen(cmd, preexec_fn=in_cgroup, shell=True)
process.wait()
print(process.stdout)
log.error(process.stderr)
except Exception as e:
traceback.print_exc()
log.error(e)

На этом пока все. Если вам будут нужны реальные примеры использования описанных здесь пакетов, посмотрите мою реализацию Docker Daemon на GitHub: https://github.com/tonybaloney/mocker.

Ссылка на оригинал: https://hackernoon.com/3-tricks-for-mastering-docker-with-python-99876412348d#.h9jo83b4z (Anthony Shaw)

Like what you read? Give Igor Olemskoi a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.