我可以得到Docker提供的工作示例,并且几乎每个博客都只是它的一个变体:只需在构建输出中打印出秘密值。
酷…但我需要得到它进入我的应用程序,正在寻找它,未能建立,因为它不存在。我不太清楚,我自己也搞不清楚。
项目结构:
project-root/
api/
docker/
Dockerfile
mysecret.txt
src/
...
manage.py
这是Dockerfile
(最后三行可能最相关):
# syntax=docker/dockerfile:1
FROM python:3.8-slim as python-base
ENV PYTHONUNBUFFERED=1
PYTHONDONTWRITEBYTECODE=1
PIP_NO_CACHE_DIR=off
PIP_DISABLE_PIP_VERSION_CHECK=on
PIP_DEFAULT_TIMEOUT=100
POETRY_HOME="/opt/poetry"
POETRY_VIRTUALENVS_IN_PROJECT=true
POETRY_NO_INTERACTION=1
PYSETUP_PATH="/opt/pysetup"
VENV_PATH="/opt/pysetup/.venv"
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
FROM python-base as builder-base
RUN apt-get update
&& apt-get install --no-install-recommends -y
curl
build-essential
ENV POETRY_VERSION=1.1.8
RUN curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
WORKDIR $PYSETUP_PATH
COPY ./poetry.lock ./pyproject.toml ./
RUN poetry install --no-dev
FROM python-base as development
ENV FASTAPI_ENV=development
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
COPY ./docker/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
WORKDIR $PYSETUP_PATH
RUN poetry install
WORKDIR /app
COPY . .
EXPOSE 5000
ENTRYPOINT /docker-entrypoint.sh $0 $@
CMD ["python", "src/manage.py", "runserver", "0.0.0.0:5000"]
FROM development AS test
RUN --mount=type=secret,id=mysecret export MYSECRET=$(cat /run/secrets/mysecret)
RUN coverage run --omit='src/manage.py,src/config/*,*/.venv/*,*/*__init__.py,*/tests.py,*/admin.py' src/manage.py test src && coverage report
命令如下:
$ docker build -f docker/Dockerfile --no-cache --secret id=mysecret,src=docker/mysecret.txt --target=test --progress=plain .
应用程序本身正在寻找:
SECRET_KEY = os.environ['MYSECRET']
SECRET_KEY = os.environ['mysecret']
但是它总是在Dockerfile
的最后一步失败,说它找不到必要的环境变量,MYSECRET
或mysecret
,来运行应用程序。
我已经尝试了很多事情来解决这个问题,并找出如何适当地将秘密进入应用程序:
- 添加
export MYSECRET
步骤,希望将其添加为env var:printenv
在docker run -it <image> bash
中没有显示。 - 查找
docker run -it <image> bash
中不存在的/run/secrets/mysecret
的值(因为它不应该存在)
似乎当它到达RUN coverage ...
时,该值不再可用。
那么我需要做什么才能让docker build --secret
与我的Dockerfile
正常工作呢?
简短回答
你能试着把2RUN coverage
和RUN --mount ...
结合起来吗?
我想大概是这样的:
RUN --mount=type=secret,id=mysecret
export MYSECRET=$(cat /run/secrets/mysecret)
&& coverage run --omit='src/manage.py,src/config/*,*/.venv/*,*/*__init__.py,*/tests.py,*/admin.py' src/manage.py test src
&& coverage report
细节此--secret
标志仅在一个docker层中存在。
最终构建的映像将没有秘密文件
文档:
https://docs.docker.com/develop/develop-images/build_enhancements/new-docker-build-secret-information
博客介绍:
https://pythonspeed.com/articles/docker-buildkit/
每个RUN
创建一个中间层。
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
所以,根据我的理解,
RUN --mount=type=secret,id=mysecret export MYSECRET=$(cat /run/secrets/mysecret)
在最终图像和最后一个RUN
中都不存在。
编辑1
RUN是由/bin/sh
而不是/bin/bash
执行的,所以你必须实例化MYSECRET
并分两步导出它:
/bin/sh -c[你的RUN指令]
RUN --mount=type=secret,id=mysecret
MYSECRET=$(cat /run/secrets/mysecret)
&& export MYSECRET
&& coverage run --omit='src/manage.py,src/config/*,*/.venv/*,*/*__init__.py,*/tests.py,*/admin.py' src/manage.py test src
&& coverage report
下面是我的工作示例:
- test.py
print MYSECRET value
import os print(os.environ["MYSECRET"])
- mysecret.txt
包含MYSECRET值
Hello
- Dockerfile
基于python:3.9 image
FROM python:3.9 COPY test.py /tmp/test.py RUN --mount=type=secret,id=mysecret MYSECRET=$(cat /run/secrets/mysecret) && export MYSECRET && python /tmp/test.py
- 构建输出
... #7 [3/3] RUN --mount=type=secret,id=mysecret MYSECRET=$(cat /run/secrets/mysecret) && export MYSECRET && python /tmp/test.py #7 sha256:f0134fcb389100e7094a47f437f8630e67da83447daaf617756c1d8432163bae #7 0.374 Hello #7 DONE 0.4s ...