[英]Copy a file from host to a running docker container from within the container?
[英]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.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中運行良好。
但是,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'
有誰知道我有沒有辦法:
我現在能想到的唯一解決方案(超級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()
: LOGNAME
, USER
, LNAME
, USERNAME
設置其中任何一個都應該允許容器啟動。
$ 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.