Na minha equipe, usamos contêineres do Docker para executar localmente os aplicativos do nosso site enquanto desenvolvemos neles.
Supondo que estou trabalhando em um aplicativo do Flask em app.py
com dependências em requirements.txt
, um fluxo de trabalho seria mais ou menos assim:
# 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
Agora, temos um servidor local executando nosso aplicativo, e podemos fazer alterações nos arquivos locais e o servidor será atualizado conforme necessário.
No exemplo acima, o aplicativo acaba sendo executado como o usuário root
. Isso não é um problema, a menos que o aplicativo grave os arquivos de volta no diretório de trabalho. Se isso acontecer, poderemos acabar com arquivos (por exemplo, algo como cache.sqlite
ou debug.log
) em nosso diretório de trabalho de propriedade de root
. Isso causou vários problemas para os usuários de nossa equipe.
Para nossos outros aplicativos, resolvemos isso executando o aplicativo com o UID e o GID do usuário do host - por exemplo, para um aplicativo do 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
Nesse caso, o aplicativo será executado como um usuário inexistente com ID 1000
dentro do contêiner, mas todos os arquivos gravados no diretório do host acabam corretamente pertencidos pelo robin
do utilizador. Isso funciona bem no Django.
No entanto, o Flask se recusa a executar como um usuário inexistente (no modo de depuração):
$ 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'
Alguém sabe se existe alguma maneira que eu possa:
- Make Flask não se preocupa com o ID de usuário não atribuído ou
- De alguma forma, atribua dinamicamente o ID do usuário a um nome de usuário em tempo de execução ou
- Caso contrário, permite que o aplicativo docker crie arquivos no host como o usuário do host?
A única solução em que posso pensar agora (super hacky) é alterar as permissões de /etc/passwd
na imagem do docker para serem globalmente graváveis e, em seguida, adicionar uma nova linha ao arquivo em tempo de execução para atribuir o novo UID / GID par para um nome de usuário.