Предварительно замечу, что возможными решениями проблемы являются следующие варианты:

  • настройка прокси репозитория PyPI в изолированном сегменте сети;

  • сборка всего python-проекта в docker image;

  • сборка всего python-проекта в один бинарный пакет.

Как подметил sshikov в комментариях:

Широко известный Nexus в бесплатной версии умеет работать прокси репозиторием PyPI. При этом вокруг него можно строить решение, которое будет контролировать безопасность устанавливаемых модулей.

Для сборки бинарных пакетов предлагаю ознакомиться со статьей Компиляция Python.

Но если все указанные выше варианты вам не подходят, то данная статья вам будет полезна.

Статья простая и нацелена на новичков, олдов прошу не возмущаться)

Задача

Необходимо выполнить деплой python-проекта со всеми его зависимостями из локального Git (Bitbucket) на сервер в изолированном сегменте сети.

Проблема заключается в том, что на сервере для python-проекта невозможно подтянуть зависимости простой командой «pip install», так как доступа к каталогам пакетов типа PyPI просто нет - решение этой проблемы и описано в данной статье.

Вводные данные по серверу:

  • нет доступа в глобальный интернет;

  • нет доступа к Python Package Index и другим индексам;

  • есть доступ к локальному RHEL-репозиторию;

  • есть доступ к локальному Git;

  • Python и Git уже установлены на сервере.

В нашем распоряжении:

  • vm на Linux или Windows в открытом сегменте сети с доступом в интернет

  • ну и собственно сам сервер в изолированном сегменте

* данные между сервером и vm передавать можно

Файл requirements.txt

Если в вашем Python-проекте нет файла requirements, то его необходимо будет создать.

Файл requirements.txt представляет собой текстовый файл, используемый в Python-проектах для указания списка зависимостей и их версий.

Каждая строка в этом файле представляет одну зависимость и имеет формат имя_пакета==версия, где имя_пакета — это название библиотеки или пакета Python, а версия — это желаемая версия этой зависимости.

Этот файл часто используется с инструментами управления пакетами, такими как pip, для автоматической установки и управления зависимостями проекта.

Файл requirements.txt в демонстрационном проекте:

netrnd-parser==1.0.428
pydantic[dotenv]
typer
requests
typing_extensions==4.5.0
urllib3==1.26.16
wheel==0.40.0

Клонирование проекта на offline-сервер

Отключим проверку SSL Сертификатов в git (опционально):

git config --global http.sslVerify false

Выполним клонирование git-репозитория проекта в домашний каталог сервера:

git clone https://company.ru/scm/nec/prefix_check.git
Cloning into 'prefix_check'...
Username: ********
Password: ********

После успешного клонирования в домашнем каталоге должна появиться директория с проектом:

ls -l
drwxrwxr-x. 5 smirnov-nk smirnov-nk 181 Jul 25 17:06 prefix_check

Подготовка архива с wheel-пакетами согласно requirements на online VM

Вариант с Linux VM

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

Выполним клонирование репозитория:

git config --global http.sslVerify false
git clone https://company.ru/scm/nec/prefix_check.git

Создадим папку и, с помощью pip, скачаем туда все зависимости проекта согласно файлу requirements:

mkdir dwl
cd dwl
pip3.10 download -r ~/prefix_check/requirements.txt
описание опций

-r, --requirement <file>: Install from the given requirements file. This option can be used multiple times.

Соберем архим:

tar -czvf dwl.tar.gz ./*

Вариант с Windows VM

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

Выполним клонирование репозитория:

git config --global http.sslVerify false
git clone https://stash.sigma.sbrf.ru/scm/nec/prefix_check.git

Создадим папку и, с помощью pip, скачаем туда все зависимости проекта согласно файлу requirements:

mkdir dwl
cd dwl
pip download -r ..\prefix_check\requirements.txt

Перечеркнутые пакеты предназначены для установки в Windows - их необходимо в ручном режиме заменить на пакеты для Linux:

C:\work\OUVP\dwl>dir
Volume in drive C is OSDisk
Volume Serial Number is 1ED5-1624

Directory of C:\work\OUVP\dwl

07/27/2023 03:51 PM <DIR> .
07/27/2023 03:51 PM <DIR> ..
07/27/2023 03:51 PM 158,334 certifi-2023.7.22-py3-none-any.whl
07/27/2023 03:51 PM 96,919 charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl
07/27/2023 03:51 PM 97,909 click-8.1.6-py3-none-any.whl
07/27/2023 03:51 PM 25,335 colorama-0.4.6-py2.py3-none-any.whl
07/27/2023 03:51 PM 840,896 future-0.18.3.tar.gz
07/27/2023 03:51 PM 61,538 idna-3.4-py3-none-any.whl
07/27/2023 03:51 PM 1,896,631 netaddr-0.8.0-py2.py3-none-any.whl
07/27/2023 03:51 PM 395,526 netrnd_parser-1.0.428-py3-none-any.whl
07/27/2023 03:51 PM 197,477 orjson-3.8.0-cp310-none-win_amd64.whl
07/27/2023 03:51 PM 2,119,253 pydantic-1.9.0-cp310-cp310-win_amd64.whl
07/27/2023 03:51 PM 19,482 python_dotenv-1.0.0-py3-none-any.whl
07/27/2023 03:51 PM 62,574 requests-2.31.0-py3-none-any.whl
07/27/2023 03:51 PM 11,053 six-1.16.0-py2.py3-none-any.whl
07/27/2023 03:51 PM 44,712 textfsm-1.1.2-py2.py3-none-any.whl
07/27/2023 03:51 PM 45,861 typer-0.9.0-py3-none-any.whl
07/27/2023 03:51 PM 27,736 typing_extensions-4.5.0-py3-none-any.whl
07/27/2023 03:51 PM 143,106 urllib3-1.26.16-py2.py3-none-any.whl
07/27/2023 03:51 PM 64,545 wheel-0.40.0-py3-none-any.whl
18 File(s) 6,308,887 bytes
2 Dir(s) 20,226,334,720 bytes free

Необходимо скачать .whl файлы с сайта PyPI.

Результаты замены пакетов:

C:\work\OUVP\dwl>dir
Volume in drive C is OSDisk
Volume Serial Number is 1ED5-1624

Directory of C:\work\OUVP\dwl

07/27/2023 04:12 PM <DIR> .
07/27/2023 04:12 PM <DIR> ..
07/27/2023 03:51 PM 158,334 certifi-2023.7.22-py3-none-any.whl
07/27/2023 04:10 PM 201,819 charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
07/27/2023 03:51 PM 97,909 click-8.1.6-py3-none-any.whl
07/27/2023 03:51 PM 25,335 colorama-0.4.6-py2.py3-none-any.whl
07/27/2023 03:51 PM 840,896 future-0.18.3.tar.gz
07/27/2023 03:51 PM 61,538 idna-3.4-py3-none-any.whl
07/27/2023 03:51 PM 1,896,631 netaddr-0.8.0-py2.py3-none-any.whl
07/27/2023 03:51 PM 395,526 netrnd_parser-1.0.428-py3-none-any.whl
07/27/2023 04:10 PM 270,377 orjson-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
07/27/2023 04:11 PM 12,263,905 pydantic-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
07/27/2023 03:51 PM 19,482 python_dotenv-1.0.0-py3-none-any.whl
07/27/2023 03:51 PM 62,574 requests-2.31.0-py3-none-any.whl
07/27/2023 03:51 PM 11,053 six-1.16.0-py2.py3-none-any.whl
07/27/2023 03:51 PM 44,712 textfsm-1.1.2-py2.py3-none-any.whl
07/27/2023 03:51 PM 45,861 typer-0.9.0-py3-none-any.whl
07/27/2023 03:51 PM 27,736 typing_extensions-4.5.0-py3-none-any.whl
07/27/2023 03:51 PM 143,106 urllib3-1.26.16-py2.py3-none-any.whl
07/27/2023 03:51 PM 64,545 wheel-0.40.0-py3-none-any.whl
18 File(s) 16,631,339 bytes
2 Dir(s) 20,188,315,648 bytes free

Далее необходимо собрать архив.

Перенос архива на offline-сервер и установка зависимостей python-проекта

Распакуем перенесенный архив:

tar -xvf dwl.tar.gz ИЛИ unzip dwl.zip

Выполним установку зависимостей проекта согласно файлу requirements:

pip3.10 install -r ~/prefix_check/requirements.txt --no-index --find-links=~/dwl
описание опций

-r, --requirement <file>: Install from the given requirements file. This option can be used multiple times.

--no-index: Ignore package index (only looking at --find-links URLs instead).

-f, --find-links <url>: If a URL or path to an html file, then parse for links to archives such as sdist (.tar.gz) or wheel (.whl) files. If a local path or file:// URL that’s a directory, then look for archives in the directory listing. Links to VCS project URLs are not supported.

Все готово, теперь можно запускать проект в работу.

Другой вариант решения задачи для Linux VM c помощью виртуального окружения предложил в комментариях DaneSoul:

Можно использовать встроенную в Python функцию виртуального окружения:

На локальной машине создаем виртуальное окружение для проекта и устанавливаем пакеты в директорию .venv:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Копируем .venv в директорию проекта на сервер, активируем там виртуальную среду, которая подключит модули и работаем.

Тут главное, под такой же системой локально устанавливать, чтобы пути совпали.

Или можно на сервере создать пустое виртуальное окружение с папкой, в ней будет ссылка на корректный серверный python:

python3 -m venv .venv

И уже сами модули с локального окружения скопировать туда.

Также спасибо kt97679, iig, hssergey за полезные комментарии.

Комментарии (41)


  1. Boggard
    18.12.2023 15:32

    Все готово, теперь можно запускать проект в работу.

    и тут начинается самое "веселое", потому что в статье ни слова про права доступа...


    1. justnikobird Автор
      18.12.2023 15:32

      Хорошее уточнение, да, действительно, этот момент опущен. Фокус сделал именно на том, как выполнить базовый деплой проекта и установить зависимости без прямого доступа в интернет.


    1. select26
      18.12.2023 15:32

      нет доступа в глобальный интернет;

      Значит должен быть бастион или outbound proxy с контролем (full log with SSL offload или whitelist)

      pc или vm c доступом в интернет

      Если прокси нет - поднимите сами на этой VM и всё.
      Это штатный enterprise подход и нет необходимости приседать каждый раз - достаточно указать системный прокси.
      Обычно ставят Palo Alto, ну или squid по бедности. Плюс SEIM.


  1. saboteur_kiev
    18.12.2023 15:32

    В чем суть статьи? Не понял ни смысла ни инструкции.
    Как файлы перенести с сервера на сервер при помощи git?
    ну такое...


    1. justnikobird Автор
      18.12.2023 15:32

      Необходимо выполнить деплой python-проекта со всеми его зависимостями из локального Git (Bitbucket) на сервер в изолированном сегменте сети.

      Основная проблема заключается в том, что для python-проекта невозможно подтянуть зависимости простой командой «pip install», так как доступа к каталогам пакетов типа PyPI просто нет - решение этой проблемы и описано в данной статье.


      1. sshikov
        18.12.2023 15:32

        Решение этой проблемы известно уже много лет - допустим, широко известный Nexus (который вообще из мира Java) в бесплатной версии умеет работать прокси репозиторием pypi уже лет 10 наверное. При этом вокруг него можно строить решение, которое будет контролировать безопасность устанавливаемых модулей.

        Я уверен, что в питон мире есть и другие решения для подъема проксирующего сервера подобного назначения. Просто вы их не там ищете. Неужели вы думаете, что вы первый, кто оказался в изолированном сегменте без интернета? Да все банки так уже лет 20 живут.


        1. justnikobird Автор
          18.12.2023 15:32

          Да, я согласен с вами
          Указал с стате ваш комментарий
          Статья нацелена не новичков, прошу сильно не возмущаться))


          1. sshikov
            18.12.2023 15:32

            Не, так новичкам так может быть даже проще. Поставить тот же нексус - ну это может пол дня. Зато потом это будет полноценное решение. Я не возмущаюсь, а скорее удивляюсь, что не попробовали поискать готовое решение, которое несомненно есть.

            Ну кстати. решение с докером тоже может быть вариантом. Причем опять же, как вариант проксирующего docker registry, который будет стоять между сегментами, а собирать образы вы будете с доступом в интернет. Самое смешное, что тот же нексус это снова умеет. И да, вариант с репозиторием RPM тоже есть.


            1. justnikobird Автор
              18.12.2023 15:32

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

              Я указал в статье ваш комментарий, поэтому если человеку это извращенство будет нужно, то он будет читать дальше


              1. sshikov
                18.12.2023 15:32

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

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


                1. justnikobird Автор
                  18.12.2023 15:32

                  так я это и описал, или есть еще более удобный вариант?


                  1. sshikov
                    18.12.2023 15:32

                    Не, сорри. Я скорее про то, что точно такой же вариант уже в комментариях предложили :) Ну то есть, он таки напрашивается как один из.


                  1. iig
                    18.12.2023 15:32

                    еще более удобный вариант?

                    Ну, не знаю.. Завернули в docker image там где есть интернет, развернули там где нужно.. Или это слишком просто? ;)

                    ЗЫ а, у вас docker запрещен ;) PyPy разрешен, а docker нет. нуок ;)


                    1. justnikobird Автор
                      18.12.2023 15:32

                      Да, с docker было бы удобнее

                      Это действие одно из хороших решений

                      Укажу ваш комментарий в статье


                    1. atshaman
                      18.12.2023 15:32

                      Ну, в большинстве случаев сейчас это правда лучший вариант - но если приложение какой-нибудь "клей" выполняющий кучу подергушек системных утилит или там кастомного IPC-взаимодействия с чем-то - докер может быть и не лучшим вариантом. Впрочем, это прям постараться надо в наше время )


  1. Tujh
    18.12.2023 15:32

    Не плохо, но как это обновлять?

    Действительно хорошим вариантом было бы описание проксирующего PyPi сервера (если такой существует) доступного в изолированном участке.


    1. justnikobird Автор
      18.12.2023 15:32

      В контексте моей задачи, обновлять все руками, так как сервак в сегменте без интернета)
      Извращенство конечно, но уж как есть)


      1. Tujh
        18.12.2023 15:32

        Да уж, плюс в карму за старания.


  1. hssergey
    18.12.2023 15:32

    Раз можно переносить данные между своим сервером и этим изолированным, то собрать docker-контейнер со всеми зависимостями, сделать docker save, скопировать файл на изолированный сервер, сделать там docker load, пользоваться. При необходимости обновления процесс повторить.

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


    1. justnikobird Автор
      18.12.2023 15:32

      Docker запрещен в компании)))

      А так согласен


      1. hssergey
        18.12.2023 15:32

        Ну я вижу вы любите трудности преодолевать...


      1. atshaman
        18.12.2023 15:32

        Ну используйте podman - примерно во всем лучше )))


      1. Alesh
        18.12.2023 15:32

        Интересно, из каких соображений может быть запрещено использование докера)


        1. Tujh
          18.12.2023 15:32

          Первое же, что приходит в голову - можно легко подмонтировать корень файловой системы с root доступом. Дальше - множество других вариантов, так как у Docker огромные проблемы с безопастностью из-за использования централизованного сервиса с правами системы. Как правильно подметили, что бы их (проблемы с безопастностью) решить был придуман podman.


          1. Alesh
            18.12.2023 15:32

            То есть, просто "защита от дурака"?)


  1. ana_meow
    18.12.2023 15:32

    неплохо, но как это обновлять?


    1. justnikobird Автор
      18.12.2023 15:32

      В контексте моей задачи, обновлять все руками, так как сервак в сегменте без интернета)


  1. kt97679
    18.12.2023 15:32

    В случае с линуксом почему вы не соберете все в бинарный пакет и не установите уже его?


    1. justnikobird Автор
      18.12.2023 15:32

      Да, тоже одно из возможных решений
      Указал ваш комментарий в статье

      Спасибо


  1. Andy_U
    18.12.2023 15:32

    Не понял, а почему предварительно не скачать с pypi все требуемые whl-файлы и потом установить тем же pip'ом?


    1. justnikobird Автор
      18.12.2023 15:32

      В принципе это и описано в статье, только более развернуто
      Мы скачиваем все зависимости на online-машине, собираем архив, переносим архив на offline-сервер и устанавливаем через pip


  1. DaneSoul
    18.12.2023 15:32

    А не проще использовать встроенную в Python виртуализацию установки пакетов?

    На локальной машине устанавливаем пакеты в папку:

    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt

    Копируем папку .venv на сервер, активируем там виртуальную среду, которая подключит модули из папки и работаем.


    1. justnikobird Автор
      18.12.2023 15:32

      Да, тоже хороший вариант

      Добавлю в статейку

      Спасибо


    1. dsoastro
      18.12.2023 15:32

      не очень хорошая идея:

      file venv/bin/python

      ---
      venv/bin/python: symbolic link to /usr/bin/python3


      1. DaneSoul
        18.12.2023 15:32

        Так суть такой виртуализации - локальная установка пакетов для python, сам он в системе должен быть уже установлен, на него путь и укажет.
        Тут главное, под такой же системой локально устанавливать, чтобы пути совпали, если из под windows, то сюрпризы с путями могут быть, хотя их можно и вручную потом подправить наверное.
        А если на сервере исходно и python нет, то задача вообще совершенно другая, тогда и предложенный автором метод не поможет.


        1. dsoastro
          18.12.2023 15:32

          есть подозрение что при копировании на другой сервер ссылка потеряется


          1. DaneSoul
            18.12.2023 15:32

            Можно на сервере создать пустое вирт.окружение с папкой, в ней будет ссылка на корректный серверный python:

            python3 -m venv .venv

            А уже сами модули скопировать с локального окружения туда в таком случае.


            1. Andy_U
              18.12.2023 15:32

              А можно еще прочитать документацию к virtualenv.


            1. dsoastro
              18.12.2023 15:32

              проблема еще в том, что внутри файлов в папке venv имеются ссылки в текстовом виде на абсолютный путь. Например,

              cd venv/

              grep venv bin/activate

              ---
              VIRTUAL_ENV='/home/user/venv'


            1. justnikobird Автор
              18.12.2023 15:32

              Александр, вы это тестили или это теория?


              1. DaneSoul
                18.12.2023 15:32

                Не тестил.