#python #linux #docker #dockerfile
#python #linux #docker #dockerfile
Вопрос:
Я создал образ docker, используя Dockerfile, который выполняет следующее:
FROM my-base-python-image
WORKDIR /opt/data/projects/project/
RUN mkdir files
RUN rm -rf /etc/yum.repos.d/*.repo
COPY rss-centos-7-config.repo /etc/yum.repos.d/
COPY files/ files/
RUN python -m venv /opt/venv amp;amp; . /opt/venv/activate
RUN yum install -y unzip
WORKDIR files/
RUN unzip file.zip amp;amp; rm -rf file.zip amp;amp; . /opt/venv/bin/activate amp;amp; python -m pip install *
WORKDIR /opt/data/projects/project/
Это создает образ, который позволяет мне запускать пользовательскую команду. Например, в терминале вот команда commmand, которую я запускаю после активации моего проекта venv:
python -m pathA.ModuleB -a inputfile_a.json -b inputfile_b.json -c
Аргументы a amp; b — это пользовательские теги для идентификации входных файлов. -c вызывает блок кода.
Итак, чтобы успешно запустить созданный образ, я запускаю контейнер и сопоставляю локальные файлы с входными файлами:
docker run --rm -it -v /local/inputfile_a.json:/opt/data/projects/project/inputfile_a.json -v /local/inputfile_b.json:/opt/data/projects/project/inputfile_b.json image-name:latest bash -c 'source /opt/venv/bin/activate amp;amp; python -m pathA.ModuleB -a inputfile_a.json -b inputfile_b.json -c'
Помимо сокращения путей к файлам, могу ли я что-нибудь сделать, чтобы сократить docker run
команду? Я думаю, что добавление CMD и / или ENTRYPOINT в Dockerfile помогло бы, но я не могу понять, как это сделать, поскольку я получаю ошибки.
Комментарии:
1. Как насчет использования переменных среды? Или настройка скрипта через стандартный интерфейс?
2. как насчет использования
docker-compose
? это вариант?3. Сопоставьте
/opt/data/projects/project/
/local
вместо этого, чтобы получить все файлы за один раз (и, возможно, использовать$PWD
, если он находится в текущем каталоге). Затем установите точку входа, чтобы вам не нужныbash
source
были части и .4. Создание виртуальной среды внутри контейнера — это подход с поясом и подтяжками. Вы можете значительно упростить контейнер, установив все для всей системы.
Ответ №1:
Есть несколько вещей, которые вы можете сделать, чтобы улучшить это.
Самое простое — запустить приложение вне Docker. Вы упоминаете, что у вас есть рабочая виртуальная среда Python. Целью разработки Docker является то, что программы в контейнерах обычно не могут обращаться к файлам на хосте, поэтому, если ваше приложение предназначено для чтения и записи файлов хоста, Docker может не подойти.
Ваши пути к файлам внутри контейнера довольно длинные, и это увеличивает ваши -v
параметры монтирования. Вам не нужен /opt/data/projects/project
префикс; очень типично просто использовать короткие пути, такие как /app
или /data
.
Вы также устанавливаете свое приложение в виртуальную среду Python, но внутри образа Docker, который обеспечивает собственную изоляцию. Как вы видите в своей docker run
команде и в других местах, механизм активации виртуальной среды в Docker немного запутан. Это также не обязательно; просто пропустите настройку виртуальной среды вообще. (Вы также можете запускать напрямую /opt/venv/bin/python
, и он знает, что он «принадлежит» виртуальной среде, без ее явной активации.)
Наконец, в вашем setup.py
файле вы можете использовать setuptools
entry_points
объявление для предоставления скрипта, который запускает ваш именованный модуль.
Это может уменьшить ваш Dockerfile до более или менее
FROM my-base-python-image
# OS-level setup
RUN rm -rf /etc/yum.repos.d/*.repo
COPY rss-centos-7-config.repo /etc/yum.repos.d/
RUN yum install -y unzip
# Copy the application in
WORKDIR /app/files
COPY files/ ./
RUN unzip file.zip
amp;amp; rm file.zip
amp;amp; pip install *
# Typical runtime metadata
WORKDIR /app
CMD main-script --help
И затем, когда вы ее запустите, вы можете:
docker run --rm -it
-v /local:/data # just map the entire directory
image-name:latest
main-script -a /data/inputfile_a.json -b /data/inputfile_b.json -c
Вы также можете рассмотреть docker run -w /data
возможность изменения текущего каталога, что добавит аргумент уровня Docker, но немного сократит командную строку скрипта.