将env变量注入映像的构建阶段

时间:2020-01-10 22:56:31

标签: azure docker azure-devops dockerfile azure-pipelines

为基于Django的API处理CI / CD管道。我需要在构建阶段注入一个环境变量,以成功构建图像。

    构建映像时,
  • python manage.py collectstaticDockerfile中运行
  • collectstatic需要SECRET_KEY中的settings.py才能运行
  • SECRET_KEY在此阶段为空,因为它是通过os.environ['SECRET_KEY]读入的。
  • 因为它为空,所以构建失败
  • 因此,我需要将环境设置为具有该变量

我在把这些东西放在一起时遇到麻烦,所以想看看是否有人可以帮助我。

这是我到目前为止所拥有的:

Azure管道

enter image description here

azure-pipelines.yml

trigger:
  branches:
    include:
    - master

resources:
- repo: self

variables:
  # Container registry service connection established during pipeline creation
  secretKey: $(SECRET_KEY)

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build and push stage
  jobs:  
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - bash:
      env:
        SECRET_KEY: $(secretKey)
    - task: Docker@2
      displayName: Build and push api image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)-api
        dockerfile: $(dockerfilePath)/api/Dockerfile
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
    - upload: manifests
      artifact: manifests

Dockerfile

FROM python:3.7-slim
ENV PYTHONUNBUFFERED 1
WORKDIR /app
EXPOSE 5000
COPY requirements*.txt ./
RUN pip install -r requirements.txt
COPY . .
RUN python manage.py collectstatic
CMD ["gunicorn", "-b", ":5000", "--log-level", "info", "config.wsgi:application"]

构建失败日志(可能无济于事,因为我知道失败的原因... SECRET_KEY不在环境变量中)

Step 8/18 : RUN python manage.py collectstatic
 ---> Running in 1f42a5c062aa
Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 325, in execute
    settings.INSTALLED_APPS
  File "/usr/local/lib/python3.7/site-packages/django/conf/__init__.py", line 79, in __getattr__
    self._setup(name)
  File "/usr/local/lib/python3.7/site-packages/django/conf/__init__.py", line 66, in _setup
    self._wrapped = Settings(settings_module)
  File "/usr/local/lib/python3.7/site-packages/django/conf/__init__.py", line 157, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/app/config/settings.py", line 26, in <module>
    SECRET_KEY = os.environ['SECRET_KEY']
  File "/usr/local/lib/python3.7/os.py", line 679, in __getitem__
    raise KeyError(key) from None
KeyError: 'SECRET_KEY'
The command '/bin/sh -c python manage.py collectstatic' returned a non-zero code: 1
##[error]The command '/bin/sh -c python manage.py collectstatic' returned a non-zero code: 1
##[error]The process '/usr/bin/docker' failed with exit code 1

我只是不确定如何完成其​​中的环境变量。从一开始我的方法可能是完全错误的。

那我应该怎么做:

  1. 安全地声明管道中的环境变量吗?
  2. 将上述环境变量传递到构建阶段吗?

谢谢!

2 个答案:

答案 0 :(得分:5)

您的python manage.py collectstatic在docker容器中运行,其os.environ['SECRET_KEY]将尝试获取运行它的容器的环境变量。但是您在管道中设置的环境变量SECRET_KEY是用于构建代理的。

您可以尝试按照以下步骤将管道env变量传递给docker容器。

1,我在您的dockerfile ARG中添加了ENVARG SECRET; ENV SECRET_KEY $SECRET

ENV SECRET_KEY是指ARG SECRET

的值
FROM python:3.7-slim

ARG SECRET
ENV SECRET_KEY $SECRET

ENV PYTHONUNBUFFERED 1
WORKDIR /app
EXPOSE 5000
COPY requirements*.txt ./
RUN pip install -r requirements.txt
COPY . .
RUN python manage.py collectstatic
CMD ["gunicorn", "-b", ":5000", "--log-level", "info", "config.wsgi:application"]

2,我将docker buildandpush任务分离为停靠构建和停靠推入,因为buildandpush命令不能接受参数。

在docker build 任务中。我将变量secretKey传递给了 arguments 字段--build-arg SECRET=$(secretKey)。这样,当docker运行build时,ARG SECRET将被secretKey取代。它将按照上面的dockerfile中的定义传递给ENV SECRET_KEY。以便将SECRET_KEY设置为docker容器的Environment变量。

然后,您的python代码应该可以使用os.environ['SECRET_KEY]

来获取环境变量的值。
stages:
- stage: Build
  displayName: Build and push stage
  jobs:  
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: Docker@2
      displayName: Build
      inputs:
        command: build
        repository: $(imageRepository)-api
        dockerfile: $(dockerfilePath)/api/Dockerfile
        containerRegistry: $(dockerRegistryServiceConnection)

        arguments: --build-arg SECRET=$(secretKey)

        tags: |
          $(tag)

    - task: Docker@2
      displayName: Push
      inputs:
        command: push
        repository: $(imageRepository)-api
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)


- upload: manifests
  artifact: manifests

答案 1 :(得分:0)

您可以在--build-arg中使用ARG和相应的Dockerfile命令注入env变量,但这不安全。密钥将嵌入到图像中!

如果您想确保安全,则可以选择:

  1. 使用Docker构建的密钥 outside 下载所需的任何内容,然后将其复制到其中。
  2. 使用Docker的BuildKit后端(具有实验性,但比以前少了很多错误),该Docker可以安全地传递秘密。
  3. 在另一个容器中运行网络服务器,使用--network container:<thatcontainerid>运行Docker构建,现在您可以将查询发送到另一个容器以获取机密。或类似地在主机上运行网络服务器,请执行--network host

更长的文章,也提到了其他一些选择,例如通过多阶段构建进行复制:https://pythonspeed.com/articles/docker-build-secrets/

相关问题