Ich arbeite im DevOps-Unfeld und schreibe mir oft kleine Helfer in Python, die mir wiederkehrende Aufgaben abnehmen, bei der Automatisierung unterstützen oder einfach nur Daten aggregieren und hübsch aufbereiten. So entstand zum Beispiel das Tool aws-taskser, über das ich Aufgaben in der AWS-Cloud von der Kommandozeile aus durchführen kann. Diese Pakete möchte ich nicht jedesmal wenn ich sie benötige auschecken, bauen und dann erst nutzen können. Also habe ich eine einfacherer Möglichkeit gesucht und bin dabei auf den pypiserver gestoßen. Es handelt sich hier um einen Server, der kompatibel zu den Python-Tools pip und easy_install ist und Pakete für diese Tools bereitstellt (Python Package Index Server). Das öffentliche Pendant dazu ist der Dienst pypi.org.

Installation

Es gibt verschiedene Optionen, wie man diesen Server installiert, ich habe mich für die Docker-Variante entschieden. Auf Dockerhub wird ein Image bereitgestellt, dass man mittels docker-compose schnell eingerichtet bekommt:

---
version: "3.3"

services:
    pypiserver:
        image: pypiserver/pypiserver:v1.3.2
        restart: unless-stopped
        container_name: pypiserver
        ports:
            - "8080:8080"
        volumes:
            - /srv/pip/data/packages:/data/packages:rw
            - /srv/pip/data/conf/htpasswd:/data/.htpasswd:ro
        command: -P /data/.htpasswd -a update,download -v /data/packages

Über den command-Parameter gebe ich die Startparameter für den PyPi-Server mit. Im Detail bedeuten diese:

  • Authentifizierung: Nach dem Parameter -P folgt die Angabe einer htpasswd-Datei, die Benutzername und Kennwort enthält. Es handelt sich hier um eine apache htpasswd-Datei.
  • Restriktionen: Man muss angeben, für welche Operationen die Authentifizierung benötigt wird (Parameter -a). Es gibt die Operation list, update und download. In unserem Fall wird ein Benutzername und Kennwort für den Upload und Download von Paketen benötigt. Die Liste mit allen Paketen kann öffentlich eingesehen werden.
  • Ausgabe: Der Parameter -v (verbose) sorgt für etwas mehr Informationsausgabe.
  • Speicherort: Als letztes gibt man den Speicherort der Pakete an (/data/packages).

Über die Volumes sorge ich dafür, das die Pakete und die htpasswd-Datei persistent abgelegt werden. Wenn man die Pakete persistent ablegt, muss man darauf achten, dass der Ordner und die Dateien darin der User-ID 9898 gehören. Unter dieser User-ID läuft der PyPi-Server. Man erhält andernfalls einen 500er-Fehler und der Server loggt, dass er keine Berechtigung hat die Dateien abzulegen.

Erstellen von Paketen

Das Bauen von Paketen ist bei python.org sehr gut beschrieben. Wenn man seine setup.py-Datei fertig gestellt hat, dann kann man das Paket und das Wheel bauen:

python3 setup.py sdist bdist_wheel

In dem Ordner dist findet man dann die installierbaren Pakete.

Upload der Pakete

Die so erstellten Pakete kann man nun hochladen mittels setuptools oder twine. Ich persönlich verwende twine:

twine upload --skip-existing --repository-url https://ppi.example.com/ dist/*

Installation der Pakete

Will man nun eines seiner Python-Pakete benutzen, so installiert man dieses mit einem Einzeiler:

pip install --index-url https://ppi.example.com/simple/ my-package

Je nach Einstellung wird man dann nach Benutzername und Kennwort gefragt und das Paket wird installiert.

Voilá, fertig ist unser eigener, kleiner Python Package Index Server.

Vorheriger Beitrag