web-dev-qa-db-ja.com

Dockerコンテナー内でホストユーザーとして実行する

私のチームでは、Dockerコンテナを使用して、Webサイトアプリケーションの開発中にローカルでWebサイトアプリケーションを実行しています。

app.pyに依存関係があるrequirements.txtのFlaskアプリで作業していると仮定すると、作業フローはおおよそ次のようになります。

# 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など)ができてしまいます。これにより、チームのユーザーに多くの問題が発生しました。

他のアプリケーションでは、HostユーザーのUIDとGIDでアプリケーションを実行することでこれを解決しました-例: Django app:

$ 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を持つnon-existentユーザーとして実行されますが、ホストディレクトリは、最終的に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アプリケーションがホストユーザーとしてホスト上にファイルを作成できるようにしますか?

私が今考えることができる唯一の解決策(超ハッキング)は、Dockerイメージ内の/etc/passwdのアクセス許可をグローバルに書き込み可能に変更し、実行時にそのファイルに新しいUID/GIDとユーザー名のペア。

14
Robin Winslow

ホストの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を使用するのと同じように、/usr/localをボリュームとして使用して、useraddでユーザーを画像に追加します。

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

id -uと$ USERの両方が、ホストシェルで、dockerがコマンドを受信する前に解決されます)

22
Robert

この問題を見つけて、別の回避策を見つけただけです。

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 デバッガーのピンコードを生成しようとしているライブラリから来ているようです。

1
codemonkey

別のPythonパッケージを使用してコンテナを起動してもよい場合は、私のPython package 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を使用したい場合は、コマンドラインでエントリポイントをオーバーライドし、ユーザーを作成するスクリプトを渡すことでも問題ありません。

0
boo-hoo