webentwicklung-frage-antwort-db.com.de

Wird als Host-Benutzer in einem Docker-Container ausgeführt

In meinem Team verwenden wir Docker-Container, um unsere Website-Anwendungen lokal auszuführen, während wir sie entwickeln.

Angenommen, ich arbeite an einer Flask-App bei app.py mit Abhängigkeiten in requirements.txt, würde ein Arbeitsablauf ungefähr so ​​aussehen:

# I am "robin" and I am in the docker group
$ whoami
robin
$ groups
robin docker

# Install dependencies into a docker volume
$ docker run -ti -v `pwd`:`pwd` -w `pwd` -v pydeps:/usr/local python:3-slim pip install -r requirements.txt
Collecting Flask==0.12.2 (from -r requirements.txt (line 1))
# ... etc.

# Run the app using the same docker volume
$ docker run -ti -v `pwd`:`pwd` -w `pwd` -v pydeps:/usr/local -e FLASK_APP=app.py -e FLASK_DEBUG=true -p 5000:5000 python:3-slim flask run -h 0.0.0.0
 * Serving Flask app "app"
 * Forcing debug mode on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 251-131-649

Jetzt haben wir einen lokalen Server, auf dem unsere Anwendung ausgeführt wird, und wir können Änderungen an den lokalen Dateien vornehmen, und der Server wird bei Bedarf aktualisiert.

Im obigen Beispiel wird die Anwendung als Benutzer root ausgeführt. Dies ist nur dann ein Problem, wenn die Anwendung Dateien zurück in das Arbeitsverzeichnis schreibt. Andernfalls könnten Dateien (z. B. cache.sqlite oder debug.log) in unserem Arbeitsverzeichnis von root gespeichert werden. Dies hat zu einer Reihe von Problemen für Benutzer in unserem Team geführt.

Für unsere anderen Anwendungen haben wir dies gelöst, indem Sie die Anwendung mit der Host-Benutzer UID und GID ausführen, z. für eine Django-App:

$ docker run -ti -u `id -u`:`id -g` -v `pwd`:`pwd` -w `pwd` -v pydeps:/usr/local -p 8000:8000 python:3-slim ./manage.py runserver

In diesem Fall wird die Anwendung als nicht existent Benutzer mit der ID 1000 innerhalb des Containers ausgeführt. Alle Dateien, die in das Host-Verzeichnis geschrieben werden, befinden sich jedoch ordnungsgemäß im Besitz des robin-Benutzers. Das funktioniert gut in Django.

Flask kann jedoch nicht als nicht vorhandener Benutzer ausgeführt werden (im Debug-Modus):

$ docker run -ti -u `id -u`:`id -g` -v `pwd`:`pwd` -w `pwd` -v pydeps:/usr/local -e FLASK_APP=app.py -e FLASK_DEBUG=true -p 5000:5000 python:3-slim flask run -h 0.0.0.0
 * Serving Flask app "app"
 * Forcing debug mode on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
Traceback (most recent call last):
...
  File "/usr/local/lib/python3.6/getpass.py", line 169, in getuser
    return pwd.getpwuid(os.getuid())[0]
KeyError: 'getpwuid(): uid not found: 1000'

Weiß jemand, ob es einen Weg gibt, auf den ich entweder

  • Lassen Sie Flask sich nicht um die nicht zugewiesene Benutzer-ID kümmern, oder
  • Ordnen Sie die Benutzer-ID zur Laufzeit dynamisch einem Benutzernamen zu, oder
  • Ansonsten die Docker-Anwendung als Host-Benutzer Dateien auf dem Host erstellen lassen?

Die einzige Lösung, an die ich momentan denken kann (Superhacky), besteht darin, die Berechtigungen von /etc/passwd im Docker-Image so zu ändern, dass sie global schreibbar ist. Anschließend wird der Datei zur Laufzeit eine neue Zeile hinzugefügt, um das neue UID/GID-Paar einem zuzuweisen Nutzername.

12
Robin Winslow

Sie können die passwd-Datei des Hosts freigeben: 

docker run -ti -v /etc/passwd:/etc/passwd -u `id -u`:`id -g` -v `pwd`:`pwd` -w `pwd` -v pydeps:/usr/local -p 8000:8000 python:3-slim ./manage.py runserver

Oder fügen Sie den Benutzer mithilfe von useradd und /etc als Volume zum Bild hinzu, genauso wie /usr/local:

docker run -v etcvol:/etc python..... useradd -u `id -u` $USER

(Sowohl id -u als auch $ USER werden in der Host-Shell aufgelöst, bevor der Docker den Befehl erhält.)

18
Robert

Schlagen Sie einfach dieses Problem und finden Sie eine andere Problemumgehung. 

Von getpass.py :

def getuser():
    """Get the username from the environment or password database.

    First try various environment variables, then the password
    database.  This works on Windows as long as USERNAME is set.

    """


    for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
        user = os.environ.get(name)
        if user:
            return user


    # If this fails, the exception will "explain" why
    import pwd
    return pwd.getpwuid(os.getuid())[0]

Der Aufruf von getpwuid() erfolgt nur, wenn keine der folgenden Umgebungsvariablen gesetzt ist: LOGNAME, USER, LNAME, USERNAME

Durch das Einstellen einer dieser Optionen sollte der Container gestartet werden.

$ docker run -ti -e USER=someuser ...

In meinem Fall scheint der Aufruf von getuser() von der Bibliothek werkzeug zu stammen, die versucht, einen Debugger-PIN-Code zu generieren.

1
codemonkey

Wenn Sie ein anderes Python-Paket zum Starten Ihres Containers verwenden möchten, möchten Sie vielleicht mein Python-Paket https://github.com/boon-code/docker-inside verwenden, das den Eingangspunkt überschreibt und Ihren Benutzer erstellt im Container im Fluge ...

docker-inside -v `pwd`:`pwd` -w `pwd` -v pydeps:/usr/local -e FLASK_APP=app.py -e FLASK_DEBUG=true -p 5000:5000 python:3-slim -- flask run -h 0.0.0.0

Das Überschreiben von trypoint in der Befehlszeile und das Übergeben eines Skripts, mit dem der Benutzer erstellt wird, ist möglicherweise auch für Sie in Ordnung, wenn Sie bei Docker CLI bleiben möchten.

0
boo-hoo