【问题标题】:docker-compose build environment variabledocker-compose 构建环境变量
【发布时间】:2019-02-25 01:15:26
【问题描述】:

TL;DR :如何在使用docker-compose 构建图像并让docker run image command 识别它们时传递环境变量?

我有这个 Dockerfile:

FROM mhart/alpine-node:10
ADD . /app
WORKDIR /app
RUN apk --no-cache add --virtual builds-deps build-base python &&\
    yarn global add nodemon &&\
    yarn &&\
    apk del builds-deps build-base python

还有这个 docker-compose.yml :

version: "3.3"
services:

  api:
    build:
      context: .
      dockerfile: Dockerfile-preprod
    image: registry.git.louis-girones.fr:4567/make-your-night/back:preprod
    environment:
      - NODE_ENV=development
    env_file:
      - .env
    volumes:
      - .:/app
    ports:
      - "${PORT_PREPROD}:${PORT_PREPROD}"
    command: sh -c "mkdir -p dist && touch ./dist/app.js && yarn run start"

  mongo:
    image: mongo:4.0
    ports:
      - "${MONGO_PREPROD}"
    command: mongod
    volumes:
      - ./data:/data/db

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:6.1.1
    volumes:
      - ./esdata:/usr/share/elasticsearch/data
    environment:
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.type=single-node
    ports:
      - "9300:9300"
      - "9200:9200"

volumes:
  esdata:

使用这个 .env 文件(位于根文件夹中,如 docker-compose.yml 和 Dockerfile):

#!/usr/bin/env bash

NODE_ENV=development
PORT=9000
SECRET_SESSION=superSecr3t
APP_NAME=Night Vision
API_VERSION=/api/v0/
DEFAULT_TZ=Europe/Paris
ASSETS_URI=http://localhost:9000/public/img/
BCRYPT_WORKFACTOR=1
ES_PORT=9200
ES_LOG_LEVEL=trace

并且这个代码在节点服务器启动中:

// Export the config object based on the NODE_ENV
// ==============================================
const config: IConfig = commonConfig

if (commonConfig.env === 'development') {
    _.merge(config, developmentConfig)
} else if (commonConfig.env === 'test') {
    _.merge(config, testConfig)
} else if (commonConfig.env === 'preproduction') {
    _.merge(config, preproductionConfig)
} else if (commonConfig.env === 'production') {
    _.merge(config, productionConfig)
} else {
    throw new Error('Please set an environment')
}

当我运行docker-compose build 命令时,一切都很好,但例如如果我尝试docker run myimage yarn run test,则会抛出“请设置环境”错误。

我希望这样

env_file:
  - .env

使这个文件的环境变量可以在我的图像中访问,但事实并非如此,这就是我尝试添加的原因

 environment:
  - NODE_ENV=development

但仍然没有成功,我还尝试在运行构建时将我的 env 变量作为命令行参数传递:

docker-compose build --build-arg NODE_ENV=development api

但它给了我这个信息:

[Warning] One or more build-args [NODE_ENV] were not consumed
Successfully built 9b14dd5abc3f

我更喜欢使用第一种或第二种方法

码头工人版本:18.06.1-ce docker-compose 版本:1.19.0

【问题讨论】:

  • 打开您的容器并输入echo $NODE_ENV 并查看结果。是development吗?
  • @alex-karshin(不确定如何在评论中标记用户的答案...)不,这是一个空行
  • 好的,尝试从第一行删除#!/usr/bin/env bash。我认为这是你的问题。
  • 实际上有人回答告诉我添加ENV NODE_ENV=development 有效但我没有时间接受它,我真的更喜欢ENV NODE_ENV=${NODE_ENV} 这样似乎不起作用的东西
  • 即使使用#!/usr/bin/env bash,echo $NODE_ENV 仍然会显示一个空行,不过感谢您的帮助

标签: docker docker-compose


【解决方案1】:

根据build args 下的文档。

您可以在指定构建参数时省略该值,在这种情况下,它在构建时的值是运行 Compose 的环境中的值。

args:
  NODE_ENV:

此外,它将使用.env 文件中记录的variable substitution

您可以使用 Compose 自动查找的 .env 文件设置环境变量的默认值。在 shell 环境中设置的值会覆盖在 .env 文件中设置的值。

所以你可以创建一个.env 文件,如下所示。

NODE_ENV=production
BASE_URL=/foo/bar/

然后只需将它们列在撰写文件中的build.args 下以使它们在build 下可用,或在environment 下使它们在run 上可用。

version: '3.9'
services:
  app:
    build:
      context: .
      # these are available on build
      args:
        NODE_ENV:
    # these are available on run
    environment:
      BASE_URL:

这很有用。但是,这种方法带来的问题是,如果变量不是从 shell 或 env 文件中设置的,Dockerfile 中的默认值将被空值覆盖。

如果想要保留某种默认值,可以使用以下内容。

version: '3.9'
services:
  app:
    build:
      context: .
      args:
        NODE_ENV: ${NODE_ENV:-dev}
    environment:
      BASE_URL: ${BASE_URL:-http://localhost:8080}

这是在使用posix parameter expansion。如果变量没有设置,它将使用:-之后的值。因此,在上面的示例中,如果未设置,则默认为 NODE_ENV=dev 和 BASE_URL=http://localhost:8080。允许使用 .env 文件或设置 shell 变量(即 export NODE_ENV=prod)覆盖它们。

【讨论】:

【解决方案2】:

有注释in the docs

注意:如果您的服务指定了构建选项,则环境中定义的变量在构建期间不会自动可见。使用 build 的 args 子选项来定义构建时环境变量。

也是described in here。首先(如上所述),您需要在Dockerfile中指定ARG

FROM mhart/alpine-node:10
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
ADD . /app
WORKDIR /app
RUN apk --no-cache add --virtual builds-deps build-base python &&\
    yarn global add nodemon &&\
    yarn &&\
    apk del builds-deps build-base python

然后编辑您的 docker-compose 文件以在构建期间包含参数,如下所示:

build:
  context: .
  dockerfile: Dockerfile-preprod
  args:
    - NODE_ENV=development

甚至

build:
  context: .
  dockerfile: Dockerfile-preprod
  args:
    - NODE_ENV=${NODE_ENV}

【讨论】:

  • 我们如何对 env 文件做同样的事情?
  • @AdharshM 不幸的是,docker-compose 不支持这个。你唯一能做的就是source .env && docker-compose ...。我知道我迟到了,但这可能会有所帮助。更多信息github.com/docker/compose/issues/5600
  • 不是撰写文件构建args 应该指定为NODE_ENV: developmentNODE_ENV: ${NODE_ENV}
  • @GregorEesmaa 它是一个 yaml 文件,你可以使用 linter 来查看两种方式都可以
  • 花了我几个小时才意识到 docker compose environment 是用于运行时
猜你喜欢
  • 2015-06-17
  • 2019-09-30
  • 1970-01-01
  • 2022-01-01
  • 2018-02-03
  • 2022-06-11
  • 2019-07-26
  • 1970-01-01
  • 2019-01-07
相关资源
最近更新 更多