作为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.sqlite
或debug.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中解析)
Just hit这个问题,并找到了一个不同的解决方法。
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()
调用如果没有以下环境变量的设置仅仅是由:LOGNAME
,USER
,LNAME
,USERNAME
设置任何人都应该允许容器开始。
$ docker run -ti -e USER=someuser ...
在我的情况下,调用getuser()
似乎来自Werkzeug库试图生成一个调试器的PIN码。 OMG!
OMG!现在你说这听起来很明显!我认为共享主机的'/ etc/passwd'文件是我要去的方式。谢谢! –
我会在13小时内给你奖励它,当它让我 –
其实我想我会使用你的第二个建议'因为它更便携 - 例如,将与macOS系统一起工作。 –