簡體   English   中英

在Docker容器中作為主機用戶運行

[英]Running as a host user within a Docker container

在我的團隊中,我們使用Docker容器來本地運行我們的網站應用程序,同時我們對它們進行開發。

假設我工作的燒瓶中的應用程序在app.py與依賴requirements.txt ,工作流程看起來大致是這樣的:

# 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

現在我們有一個運行我們的應用程序的本地服務器,我們可以更改本地文件,服務器將根據需要刷新。

在上面的示例中,應用程序最終以root用戶身份運行。 除非應用程序將文件寫回工作目錄,否則這不是問題。 如果確實如此,那么我們最終可能會在root擁有的工作目錄中cache.sqlite文件(例如cache.sqlitedebug.log )。 這給我們團隊中的用戶帶來了許多問題。

對於我們的其他應用程序,我們通過使用主機用戶的 UID和GID運行應用程序來解決這個問題 - 例如對於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

在這種情況下,應用程序將作為容器內ID為1000不存在用戶運行,但寫入主機目錄的任何文件最終都由robin用戶正確擁有。 這在Django中運行良好。

但是,Flask拒絕以不存在的用戶身份運行(在調試模式下):

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

有誰知道我有沒有辦法:

  • 讓Flask不用擔心未分配的用戶ID,或者
  • 以某種方式在運行時動態地將用戶ID分配給用戶名,或
  • 否則,允許docker應用程序在主機上創建文件作為主機用戶?

我現在能想到的唯一解決方案(超級hacky)是將docker鏡像中/etc/passwd的權限更改為全局可寫,然后在運行時向該文件添加一個新行以分配新的UID / GID配對用戶名。

您可以共享主機的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

或者,使用/etc作為卷將用戶添加到帶有useradd的映像,就像使用/usr/local

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

(在docker收到命令之前, id -u和$ USER都在主機shell中解析)

剛剛遇到這個問題,發現了一個不同的解決方法。

來自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]

只有在未設置以下環境變量時才會調用getpwuid()LOGNAMEUSERLNAMEUSERNAME

設置其中任何一個都應該允許容器啟動。

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

在我的例子中,對getuser()的調用似乎來自Werkzeug庫,試圖生成調試器代碼。

如果你可以使用另一個Python包來啟動容器,也許你想使用我的Python包https://github.com/boon-code/docker-inside覆蓋入口點並在容器中創建你的用戶蒼蠅......

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

如果您想堅持使用Docker CLI,那么在命令行上覆蓋入口點並傳遞創建用戶的腳本也可能適合您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM