作为Docker容器中的主机用户运行

问题描述:

在我们的团队中,我们使用Docker容器在本地运行我们的网站应用程序,同时对其进行开发。作为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.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中工作正常。

然而,瓶拒绝为不存在的用户身份运行(在调试模式):

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

有谁知道,如果有任何办法,我既可以:

  • 使瓶不担心未分配的用户标识,或者
  • 不知何故在运行时将用户标识动态分配给用户名,或者
  • 否则允许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 

或者,用户与useradd添加到图像,使用/etc音量,以同样的方式使用/usr/local

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

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

+0

OMG!现在你说这听起来很明显!我认为共享主机的'/ etc/passwd'文件是我要去的方式。谢谢! –

+0

我会在13小时内给你奖励它,当它让我 –

+0

其实我想我会使用你的第二个建议'因为它更便携 - 例如,将与macOS系统一起工作。 –

Just hit这个问题,并找到了一个不同的解决方法。

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库试图生成一个调试器的PIN码。 OMG!