Запуск Anaconda проекта с применением технологии Docker

Описание проблемы

Имеется проект на Python с применением Anaconda, осуществляющий длительные расчеты.

Имеется несколько мощных вычислительных станций, на которых этот проект должен запускаться с разными параметрами. Результат вычислений должен быть сохранен для дальнейшей обработки.

В код проекта регулярно вносятся изменения, необходимо иметь возможность запуска определенной версии проекта с целью анализа результатов.

Необходимо также иметь возможность быстрой настройки окружения у всех участников проекта и на вычилительных станциях.

Anaconda и Docker

Для быстрого создания и развертывания среды для запуска проекта предлагается использовать технологию Docker. Использование Docker позволит максимально упростить процесс подготовки окружения.

Все преимущества использования Anaconda в связке с Docker приведены в блоге Anaconda.

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

Использование готового образа

Готовые образы можно скачать в Docker Hub.

Для начала работы c Anaconda необходимо определиться с версией. На момент написания статьи в Docker Hub предложено 4 варианта:

continuumio/anaconda (based on Python 2.7)

continuumio/anaconda3 (based on Python 3.5)

continuumio/miniconda (based on Python 2.7)

continuumio/miniconda3 (based on Python 3.5)

Для установки anaconda и anaconda3 требуется скачать порядка 600 MB, установленный образ занимает в системе порядка 2,5 GB.

Образ miniconda3 занимает в системе 454 MB, объем скачанных данных варьируется в пределах 120-150 MB.

Для того, чтобы скачать и распаковать образ необходимо ввести команду

docker pull continuumio/miniconda3

После этого можно запустить контейнер командой:

docker run -i -t continuumio/miniconda3 /bin/bash

Стоит заметить, что при таком запуске контейнер после завершения работы сохранит все данные, полученные в процессе развертывания и работы. Для того, чтобы контейнер удалился сразу после завершения необходимо добавить ключ --rm после команды run.

При запуске будет произведен поиск образа continuumio/miniconda3 в системе. Если он уже был ранее скачан, то будет создан контейнер из этого образа и в нем будет запущен /bin/bash. Если образ не был найден, то предварительно будет скачан соответствующий образ из Docker Hub, Подробнее про технологии работы Docker можно почитать в официальной документации

С целью получения более глубокого понимания особенностей системы Anaconda, а также с целью экономии свободного пространства и трафика, предлагается создать свой образ на основе continuumio/miniconda3.

Создание своего образа

Для создания своего образа необходимо выбрать базовый образ и подготовить Dockerfile. Этот файл содержит инструкции, которые необходимо выполнить на базовом образе. Описание формата Dockerfile приведено в официальной документации Docker. Также следует ознакомиться с Best practices по написанию Dockerfile. На русском языке перевод основных инструкций Dockerfile приведен, например, в статье Погружаемся в Docker: Dockerfile и коммуникация между контейнерами.

Для наследования образа от continuumio/miniconda3 используется инструкция FROM.

FROM continuumio/miniconda3:4.3.14

Рекомендуется явно указывать версии образов, пакетов, библиотек и пр., чтобы избежать проблем совместимости.

Инструкция RUN позволяет произвольную команду. Процесс сборки образа происходит так. Разворачивается родительский образ во временный контейнер, в нем выполняется команда, переданная с помощью инструкции RUN. Состояние временного контейнера сохраняется в образ, временный контейнер удаляется. Таким образом, добавляется новый “слой” в образ. Для более полного понимания того, организован механизм “слоев” в Docker можно ознакомиться с статьей Образы и контейнеры Docker в картинках.

Инструкция WORKDIR хранит путь до рабочего каталога проекта.

Инструкция COPY позволяет копировать данные из локального каталога в образ. Более функциональный аналог ADD позволяет добавлять в образ файлы, скачанные с интернета, а также умеет распаковывать архивы.

Инструкция CMD описывает команду, которая будет запущена после старта контейнера. Существует также инструкция ENTRYPOINT, которая делает то же самое, с одним исключением. Команда, которая передается в CMD может быть изменена пользователем при запуске образа, ENTRYPOINT – нет. Для достижения большей гибкости будем пользоваться инструкцией CMD.

Инструкция VOLUME предоставляет возможность подключения к контейнеру каталогов основной системы. Это может использоваться, например, для подключения постоянных данных, которые нельзя включить в образ. В нашем случае VOLUME используются для подключения каталогов с входными и выходными данными. Существует большое количество опций работы Volume, подробнее с ними можно ознакомиться в официальной документации Docker.

В результате получился приведенный ниже Dockerfile. Его необходимо разместить в каталоге проекта.

FROM continuumio/miniconda3:4.3.14

RUN conda install -y numpy scipy scikit-learn pandas && \

    # install apt
    apt-get update && \
    apt-get install -y cmake build-essential gcc g++ git wget && \
    
    # install lightgbm
    git clone --recursive https://github.com/Microsoft/LightGBM && \
    cd LightGBM/python-package && python setup.py install && \
    
    # clean
    apt-get autoremove -y && apt-get clean && \
    conda clean -i -l -t -y && \
    rm -rf /usr/local/src/*

WORKDIR /opt/project/

COPY . /opt/project/

RUN mkdir -p /data/input \
    mkdir -p /data/output \ 

VOLUME /data/input
VOLUME /data/output

CMD ["/opt/conda/bin/python", "/opt/project/main.py"]

Сборка и запуск образа

Для сборки образа необходимо перейти в каталог, содержащий Dockerfile и выполнить команду:

docker build -t conda .

Здесь conda – имя образа. Оно может быть любым, однако, желательно, чтобы оно отражало содержимое.

Запуск контейнера осуществляется командой

docker run --rm conda

Параметр --rm может быть удален, если необходимо, чтобы данные остались после завершения работы контейнера.

Следующая команда запускает процесс вычислений.

docker run --rm -v /home/user/data/input:/data/input -w /home/user/data/output:/data/output conda

Здесь /home/user/data/input и /home/user/data/output – локальные каталоги, которые будут примонтированы к Docker для хранения входных и выходных данных соответственно. Ключ -v обозначает монтирование в режиме только чтения, ключ -w позволяет производить запись в примонтированный каталог.

Запускать процесс вычислений вовсе не обязательно. Можно, например, запустить bash в требуемой среде и, например, поэкспериментировать с ipython. Однако, для правильного запуска серверных приложений, слушающих порты, необходимо прописать порты в Dockerfile, а для запуска графических приложений, возможно, потребуется нетривиальная настройка X-сервера. Эти вопросы не будут рассмотрены в данной статье.

docker run --rm -v /home/user/data/input:/data/input -w /home/user/data/output:/data/output -it conda /bin/bash

Результаты

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