简体   繁体   English

docker-compose 构建环境变量

[英]docker-compose build environment variable

TL;DR : How can I pass env variable when building the image with docker-compose and have docker run image command recognize them ? TL;DR:如何在使用docker-compose构建图像时传递 env 变量并让docker run image command识别它们?

I have this Dockerfile :我有这个 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

and this docker-compose.yml :和这个 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:

With this .env file (which is in the root folder, like docker-compose.yml and Dockerfile) :使用这个 .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

And this code in the node server startup :而节点服务器启动中的这段代码:

// 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')
}

When I run the docker-compose build command, everything is fine, but for instance If I try docker run myimage yarn run test the Error "Please set an environment" is thrown.当我运行docker-compose build命令时,一切都很好,但是例如如果我尝试docker run myimage yarn run test会抛出错误“请设置环境”。

I would expect that我希望

env_file:
  - .env

makes the env variables of this file accessible in my image but that is not the case, that's why I tried to add使这个文件的 env 变量可以在我的图像中访问,但事实并非如此,这就是我尝试添加的原因

 environment:
  - NODE_ENV=development

But still no success, I have also tried to pass my env variable as command line argument when I run the build :但仍然没有成功,我还尝试在运行 build 时将我的 env 变量作为命令行参数传递:

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

But it gives me this message :但它给了我这样的信息:

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

And I would really prefer to use the first or second methods我真的更喜欢使用第一种或第二种方法

docker version : 18.06.1-ce docker-compose version : 1.19.0 docker 版本:18.06.1-ce docker-compose 版本:1.19.0

There's a note in the docs : 文档中有一个注释:

Note: If your service specifies a build option, variables defined in environment are not automatically visible during the build. 注意:如果您的服务指定了构建选项,则在构建期间,环境中定义的变量不会自动显示。 Use the args sub-option of build to define build-time environment variables. 使用build的args子选项来定义构建时环境变量。

It's also described in here . 它也在这里描述 First (as mentioned above), you need to specify ARG in Dockerfile: 首先(如上所述),您需要在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

And then edit your docker-compose file to include the argument during build, like so: 然后编辑您的docker-compose文件以在构建期间包含参数,如下所示:

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

Or even 甚至

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

As per documentation under build args .根据build args下的文档。

You can omit the value when specifying a build argument, in which case its value at build time is the value in the environment where Compose is running.您可以在指定构建参数时省略该值,在这种情况下,它在构建时的值是 Compose 运行环境中的值。

args:
  NODE_ENV:

Additionally, it will use the .env file as documented under variable substitution .此外,它将使用变量替换下记录的.env文件。

You can set default values for environment variables using a .env file, which Compose automatically looks for.您可以使用 Compose 自动查找的 .env 文件为环境变量设置默认值。 Values set in the shell environment override those set in the .env file.在 shell 环境中设置的值会覆盖在 .env 文件中设置的值。

So you can create a .env file like below.所以你可以创建一个.env文件,如下所示。

NODE_ENV=production
BASE_URL=/foo/bar/

And then just list them in the compose file either under build.args to make them available on build , or under environment to make them available on run .然后只需在build.args下的 compose 文件中列出它们以使其在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:

This is kind of useful.这有点有用。 However, the problem that comes along with this approach is that if the variables are not set from shell or env file, the default values in the Dockerfile will be overwritten with an empty value.然而,这种方法带来的问题是,如果变量不是从 shell 或 env 文件设置的,Dockerfile 中的默认值将被空值覆盖。

If one wants to keep some sort of default, the following can be used.如果想要保留某种默认值,可以使用以下内容。

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

This is making usage of posix parameter expansion .这是使用posix 参数扩展 If the variable is not set, it will use the value after :- .如果未设置变量,它将使用:-之后的值。 So in the example above, it would default to NODE_ENV=dev and BASE_URL=http://localhost:8080 if those are not set.所以在上面的例子中,如果没有设置,它会默认为 NODE_ENV=dev 和 BASE_URL=http://localhost:8080 。 Allowing to override them with a .env file or by setting a shell variable, ie export NODE_ENV=prod .允许使用.env文件或通过设置 shell 变量覆盖它们,即export NODE_ENV=prod

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM