Python flask应用程序访问群中的Docker机密

问题描述:

我想部署一个flask + gunicorn项目,我是Docker的新手.到目前为止,我有一个如下的Dockerfile.

I want to deploy a flask+gunicorn project and I am newbie to Docker. So far, I have a Dockerfile as following.

# Pull official base image
FROM python:3.7-slim-buster

# Set work directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Set environment variables
ENV REDIS_HOST [...omit here...]
ENV REDIS_PORT [...omit here...]
ENV REDIS_DB_WHITELIST [...omit here...]
ENV MYSQL_HOST [...omit here...]
ENV MYSQL_PORT [...omit here...]
ENV MYSQL_DB_DUMMY [...omit here...]

# Copy project
COPY . /usr/src/app/

# Install dependencies
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN pip install gunicorn

EXPOSE 5000

RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["sh", "entrypoint.sh"]

还有如下所示的docker-compose.yml.

And a docker-compose.yml as following.

version: "3.9"

secrets:
  FLASK_SECRET_KEY:
    external: true
  MYSQL_USER:
    external: true
  MYSQL_PASSWORD:
    external: true

services:
  web:
    image: flask-app:v0.1.0
    environment:
      FLASK_SECRET_KEY_FILE: /run/secrets/FLASK_SECRET_KEY
      MYSQL_USER_FILE: /run/secrets/MYSQL_USER
      MYSQL_PASSWORD_FILE: /run/secrets/MYSQL_PASSWORD
    ports:
      - "5000:5000"
    secrets:
      - FLASK_SECRET_KEY
      - MYSQL_USER
      - MYSQL_PASSWORD

在我搜索完之后,似乎访问docker机密的唯一方法是使用 docker stack deploy --compose-file = docker-compose.yml flask-app 命令.显然,我需要将三个敏感数据 FLASK_SECRET_KEY MYSQL_USER MYSQL_PASSWORD 存储在Docker机密中.事实证明,应用程序始终无法运行,并且我假设python脚本中的 mysql_user = os.environ ['MYSQL_USER'] 等无法访问环境变量.

After I googled through, it seems the only way of accessing docker secrets is to use docker stack deploy --compose-file=docker-compose.yml flask-app command. Obviously, I have three sensitive data FLASK_SECRET_KEY, MYSQL_USER, MYSQL_PASSWORD needed to storing in Docker secrets. It turns out that app keeps failing to run, and I assume that mysql_user = os.environ['MYSQL_USER'] etc. in python script fails to access environment variable.

我不知道通过Dockerfile或docker-compose.yml从Docker机密访问敏感数据的正确方法,如果发现错误,请纠正我.

I have no idea of right way to access sensitive data from Docker secrets, via Dockerfile or docker-compose.yml, and please correct me if I get something wrong.

我确实找到了一种使用

I did find an approach of accessing sensitive data from docker secret, using python-dotenv. Here's some snippet of my project-level config.py module.

import os
from dotenv import load_dotenv

dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
if os.path.exists(dotenv_path):
    load_dotenv(dotenv_path=dotenv_path)


def manage_sensitive(name):
    v1 = os.getenv(name)
    
    secret_fpath = f'/run/secrets/{name}'
    existence = os.path.exists(secret_fpath)
    
    if v1 is not None:
        return v1
    
    if existence:
        v2 = open(secret_fpath).read().rstrip('\n')
        return v2
    
    if all([v1 is None, not existence]):
        return KeyError(f'{name}')


class ConfigRabbitMQ:
    AMQP_USER = manage_sensitive(name='amqp_user')
    AMQP_PASSWORD = manage_sensitive(name='amqp_password')
    
    AMQP_HOST = manage_sensitive(name='amqp_host')
    AMQP_PORT = manage_sensitive(name='amqp_port')

因此,与此 config.py 模块相同的目录中有一个 .env 文件.该模块可以访问Docker密钥和 .env 文件中的敏感数据,因为通常做法是在 .dockerignore 文件中列出 .env .因此,例如, docker-compose.yml 如下.

So there's a .env file at the same directory with this config.py module. This module can access sensitive data from Docker secret and .env file, as it is a common practice to list .env in a .dockerignore file. Thus, for example, docker-compose.yml is as following.

version: "3.9"

services:
  web:
    ...
    secrets:
      - amqp_user
      - amqp_password
    ...

secrets:
  amqp_user:
    external: true
  amqp_password:
    external: true

是否有更好的建议?