Python flask应用程序在swarm中访问docker机密
我想部署一个flask+gunicorn项目,我是Docker的新手。到目前为止,我有一个Dockerfile如下Python flask应用程序在swarm中访问docker机密,python,docker-compose,dockerfile,docker-swarm,Python,Docker Compose,Dockerfile,Docker Swarm,我想部署一个flask+gunicorn项目,我是Docker的新手。到目前为止,我有一个Dockerfile如下 # 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 RE
# 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"]
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
version: "3.9"
services:
web:
...
secrets:
- amqp_user
- amqp_password
...
secrets:
amqp_user:
external: true
amqp_password:
external: true
和docker-compose.yml,如下所示
# 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"]
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
version: "3.9"
services:
web:
...
secrets:
- amqp_user
- amqp_password
...
secrets:
amqp_user:
external: true
amqp_password:
external: true
在我通过谷歌搜索之后,似乎访问docker机密的唯一方法是使用docker stack deploy--compose file=docker-compose.yml flask app
命令。显然,我有三个敏感的数据密钥,MYSQL用户,MYSQL密码需要存储在Docker secrets中。事实证明,应用程序一直无法运行,我假设python脚本中的mysql\u user=os.environ['mysql\u user']
等无法访问环境变量
我不知道通过Dockerfile或Docker-compose.yml从Docker secrets访问敏感数据的正确方法,如果我出错,请纠正我。您使用了简短的语法来声明服务上的机密。默认情况下,此类机密将装入容器内的/run/secrets/{secretname} 长语法甚至允许指定目标位置(尽管v3 compose引用声称它只装载到/run/secrets/): 创建一个秘密:
echo "mysecret" | docker secret create mysecret -
注意:这个秘密可能是在docker-compose.yml中创建的,同时还带有一个文件引用。为了简单起见,我选择在我的示例中手动创建它
在群堆中消耗秘密:
version: '3.8'
services:
testsecret:
image: ubuntu
deploy:
replicas: 1
tty: true
secrets:
- source: mysecret
target: /path/in/container/mysecret
mode: 0444
secrets:
mysecret:
external: true
然后读取应用程序中的文件/path/in/container/mysecret以获取其内容
请记住,秘密总是以只读方式装载的。增加的安全性是,秘密在swarm节点之间加密分配,并加密存储在raft日志中(~=集群状态)。一旦秘密装入容器中,它将是tempfs上的未加密文件。另一个优点是细节不作为环境变量公开,因此不太可能被意外泄漏
docker compose似乎与v3.x版的compose文件规范存在定义上的差距,该规范允许在docker compose部署中使用机密。但是:许多低级功能届时将不可用
几天后,v3 compose file reference页面似乎被破坏了:从页眉和页脚看,整个描述都丢失了…您使用了简短的语法来声明服务上的秘密。默认情况下,此类机密将装入容器内的/run/secrets/{secretname} 长语法甚至允许指定目标位置(尽管v3 compose引用声称它只装载到/run/secrets/): 创建一个秘密:
echo "mysecret" | docker secret create mysecret -
注意:这个秘密可能是在docker-compose.yml中创建的,同时还带有一个文件引用。为了简单起见,我选择在我的示例中手动创建它
在群堆中消耗秘密:
version: '3.8'
services:
testsecret:
image: ubuntu
deploy:
replicas: 1
tty: true
secrets:
- source: mysecret
target: /path/in/container/mysecret
mode: 0444
secrets:
mysecret:
external: true
然后读取应用程序中的文件/path/in/container/mysecret以获取其内容
请记住,秘密总是以只读方式装载的。增加的安全性是,秘密在swarm节点之间加密分配,并加密存储在raft日志中(~=集群状态)。一旦秘密装入容器中,它将是tempfs上的未加密文件。另一个优点是细节不作为环境变量公开,因此不太可能被意外泄漏
docker compose似乎与v3.x版的compose文件规范存在定义上的差距,该规范允许在docker compose部署中使用机密。但是:许多低级功能届时将不可用
几天后,v3 compose file reference页面似乎被破坏了:从页眉和页脚可见,整个描述都丢失了…我确实找到了一种从docker secret访问敏感数据的方法,使用。下面是我的项目级
config.py
模块的一些片段
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 secret和.env
文件中的敏感数据,因为通常在.dockrignore
文件中列出.env
。因此,例如,docker compose.yml
如下所示
# 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"]
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
version: "3.9"
services:
web:
...
secrets:
- amqp_user
- amqp_password
...
secrets:
amqp_user:
external: true
amqp_password:
external: true
对于更好的做法有什么建议吗?我确实找到了一种使用docker secret访问敏感数据的方法。下面是我的项目级
config.py
模块的一些片段
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 secret和.env
文件中的敏感数据,因为通常在.dockrignore
文件中列出.env
。因此,例如,docker compose.yml
如下所示
# 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"]
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
version: "3.9"
services:
web:
...
secrets:
- amqp_user
- amqp_password
...
secrets:
amqp_user:
external: true
amqp_password:
external: true
有什么更好的建议吗?对不起,我的答复可能过期了。正如您所看到的,我确实找到了Docker secret,并选择从其默认路径访问它。我仍然不确定这是否是一个好的做法。如果对此有任何建议,我将不胜感激。对不起,我的回复可能过期了。正如您所看到的,我确实找到了Docker secret,并选择从其默认路径访问它。我仍然不确定这是否是一个好的做法。如果对此有任何建议,我将不胜感激。