2017-08-23 65 views
6

W moim zespole używamy kontenerów Docker do lokalnego uruchamiania naszych aplikacji internetowych, podczas gdy pracujemy nad nimi.Uruchamianie jako użytkownik hosta w kontenerze Docker

Zakładając pracuję nad app kolbie w app.py z zależnościami w requirements.txt, przepływ pracy będzie wyglądać mniej więcej tak:

# 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 

Teraz mamy lokalnego serwera z uruchomionym naszej aplikacji, a my możemy zrobić zmiany w plikach lokalnych, a serwer odświeży się w razie potrzeby.

W powyższym przykładzie aplikacja kończy pracę jako użytkownik root. Nie stanowi to problemu, chyba że aplikacja zapisze pliki z powrotem do katalogu roboczego. Jeśli tak, to możemy skończyć z plikami (np. Takimi jak cache.sqlite lub debug.log) w naszym katalogu roboczym należącym do root. To spowodowało wiele problemów dla użytkowników w naszym zespole.

W przypadku innych naszych aplikacji rozwiązaliśmy ten problem, uruchamiając aplikację z użytkownikiem hosta: UID i GID - np. dla aplikacji Django:

$ 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 

W tym przypadku aplikacja zostanie uruchomiona jako nieistniejącego użytkownika o ID 1000 wewnątrz pojemnika, ale wszystkie pliki zapisywane w katalogu hosta kończy się prawidłowo posiadaniu przez robin użytkownika. Działa to dobrze w Django.

Jednak Kolba odmawia pracy jako nieistniejącego użytkownika (w trybie debugowania):

$ 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' 

Czy ktoś wie, czy jest jakiś sposób, że mogę albo:

  • Bądź Flask nie martwić się o nieprzypisany identyfikator użytkownika lub w jakiś sposób dynamicznie przypisać identyfikator użytkownika do nazwy użytkownika w czasie wykonywania, lub
  • W przeciwnym razie zezwolić aplikacji dokujania na utworzenie pliku s na hoście jako użytkownik hosta?

Jedynym rozwiązaniem można myślę teraz (Super hacky) ma się zmienić uprawnienia /etc/passwd w obrazie Döcker być zapisywany w skali globalnej, a następnie dodać nową linię do tego pliku w czasie wykonywania przypisać nowy Para UID/GID do nazwy użytkownika.

Odpowiedz

5

Można udostępniać gospodarza plik passwd:

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 

też dodać użytkownika do obrazu z useradd korzystając /etc jako objętość, w taki sam sposób korzystania /usr/local:

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

(Oba numery: id -u i $ USER są rozwiązywane w powłoce hosta, zanim doker odbierze komendę)

+0

OMG! Teraz mówisz, że to brzmi tak oczywiste! Myślę, że udostępnianie pliku hosta '/ etc/passwd' jest sposobem, w jaki pójdę. Dzięki! –

+0

Przyznam ci nagrodę za 13 godzin, kiedy pozwoli mi –

+0

Właściwie, myślę, że użyję twojej drugiej sugestii, ponieważ jest bardziej przenośna - np. będzie działać z systemami MacOS. –

0

Po prostu trafienie ten problem i znalazł inne obejście.

Od 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] 

Wezwanie do getpwuid() jest wykonany tylko wtedy, gdy żaden z następujących zmiennych środowiskowych są: LOGNAME, USER, LNAME, USERNAME

Ustawianie każdy z nich powinien umożliwić kontener zacząć.

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

W moim przypadku, wezwanie do getuser() wydaje się pochodzić z biblioteki Werkzeug próbuje wygenerować kod pin debugger.