简体   繁体   English

如何使用 docker-compose 环境变量填充配置文件

[英]How to use docker-compose environment variables to populate config file

I'm new to docker-compose.我是 docker-compose 的新手。
I'm trying to understand how can I pass environment variables via docker-compose to populate missing variables values in a config file during Dockerfile 's build stage, so in the run phase, I will run the service- rabbitmq with its configuration filled with the env variables values.我试图了解如何通过 docker-compose 传递环境变量,以便在Dockerfile的构建阶段填充配置文件中缺少的变量值,因此在运行阶段,我将运行服务rabbitmq填充其配置变量值。

In docker-compose yml file I have an env_file: and also environment: , question how can I pass them forward to populate the config file.在 docker-compose yml 文件中,我有一个env_file:environment: ,询问如何将它们转发以填充配置文件。

Any help, an idea would be greatly appreciated with a simple example of course.当然,如果有任何帮助,一个简单的例子将不胜感激。

Example rabbitmq config file (with env variable which need to be filled with its value for $SSL_PORT):示例 rabbitmq 配置文件(环境变量需要用 $SSL_PORT 的值填充):

[{rabbit,
  [
    {loopback_users, []},
    {ssl_listeners, [$SSL_PORT]},
    {ssl_options, [{cacertfile,"/etc/rabbitmq/ca/cacert.pem"},
                   {certfile,"/etc/rabbitmq/server/cert.pem"},
                   {keyfile,"/etc/rabbitmq/server/key.pem"},
                   {verify,verify_none},
                   {fail_if_no_peer_cert,false}]}
  ]}
].

The problem can be divided in 2 parts: 该问题可分为2部分:

  1. Inject the configuration values inside the container 将配置值注入容器中
  2. Let the target software use such configuration values 让目标软件使用此类配置值

The first problem is solved via the use of environment variables: as you stated you can either instruct docker to use env files ( --env-file file.env ) or specify single environment variables ( --env VARIABLE=value ) and docker will make them available inside the container. 第一个问题是通过使用环境变量解决的:如您所述,您可以指示--env-file file.env使用env文件( --env-file file.env )或指定单个环境变量( --env VARIABLE=value ),而--env VARIABLE=value将使它们在容器内可用。

The second problem has different solution based on the configuration framework used. 第二个问题根据所使用的配置框架有不同的解决方案。

For instance if you are using something like Typesafe config or Spring you can just put a reference to the environment variable inside the configuration itself and the configuration framework will automatically expand it. 例如,如果您使用的是Typesafe configSpring ,则可以在配置本身内部放置对环境变量的引用,配置框架将自动对其进行扩展。

If instead you are configuring a third-party software which doesn't support environment variable expansion you will need to do some preprocessing before the target software gets executed. 相反,如果要配置的第三方软件不支持环境变量扩展,则需要在执行目标软件之前进行一些预处理。

This is usually done by creating a docker image with a custom entrypoint . 这通常是通过创建具有自定义入口点的docker映像来完成的。 This entrypoint is responsible of modifying the configuration of the target software expannding the known environment variables and then starting the software. 该入口点负责修改目标软件的配置,使其使用已知的环境变量,然后启动该软件。

An example of such an entrypoint script could be: 这样的入口点脚本的示例可以是:

#!/bin/sh

sed -i "s/\$SSL_PORT/$SSL_PORT/g" /etc/software.conf

exec $@

Modifying a configuration file in this way could be dangerous and error prone so take care when writing such scripts. 以这种方式修改配置文件可能很危险且容易出错,因此在编写此类脚本时要格外小心。

Update : 更新

If all you want to do is to perform some pre-processing before the original entrypoint start you can follow this simple pattern: Let's say the original entrypoint is called docker-entrypoint.sh , all you need to do is to to create docker-entrypoint-pre.sh with this content: 如果您要做的只是在原始入口点开始之前执行一些预处理,则可以遵循以下简单模式:假设原始入口点名为docker-entrypoint.sh ,您要做的就是创建docker-entrypoint-pre.sh具有以下内容:

#!/bin/bash

# Perfom all the needed preprocessing here...

# Invoke the original entrypoint passing the command and arguments
exec /docker-entrypoint.sh $@ 

If you build a docker image using your new entrypoint and start a container with: 如果您使用新的入口点构建docker映像并使用以下命令启动容器:

docker run --rm test-image echo "This is a test"

What will happen is that docker-entrypoint-pre.sh will be called with arguments echo and This is a test . 将会发生的是,将使用参数echo调用docker-entrypoint-pre.shThis is a test After the preprocessing is done the original entrypoint docker-entrypoint.sh will be called with the same arguments thus maintaining the behaviour of the original image. 预处理完成后,将使用相同的参数调用原始入口点docker-entrypoint.sh ,从而保持原始映像的行为。

Update2: In order to add your new entrypoint you have to create a new Docker image inheriting from the original. Update2:为了添加新的入口点,您必须创建一个从原始继承的新Docker映像。 Lets say that the original image is rabbit:latest , you would need to create a Dockerfile with the following content: 假设原始图像是rabbit:latest ,则需要创建一个包含以下内容的Dockerfile

FROM rabbit:latest

COPY docker-entrypoint-pre.sh /docker-entrypoint-pre.sh

ENTRYPOINT ["/docker-entrypoint-pre.sh"]

And then build your image with docker build -t myrabbit:latest . 然后使用docker build -t myrabbit:latest .构建映像docker build -t myrabbit:latest . from the directory containing the Dockerfile and the docker-entrypoint-pre.sh . 从包含Dockerfiledocker-entrypoint-pre.sh的目录中。

At this point you have a new image myrabbit:latest with your preprocessing logic. 至此,您的预处理逻辑有了一个新映像myrabbit:latest

Assuming that your config file(s) are using the variable $SSL_PORT inside the container, and you want to pass environment variables from the host machine to be used on build, this can be done in your docker-compose.yml . 假设您的配置文件正在容器使用变量$SSL_PORT ,并且您想要从主机传递环境变量以用于构建,则可以在docker-compose.yml完成此操作。 YAML supports the use of environment variables, therefore, you can use environment: followed by an array of variables you wish to pass to the container during runtime. YAML支持使用环境变量,因此,您可以使用environment:然后是要在运行时传递给容器的变量数组。

For example: 例如:

version: '3'
services:
  your-app:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - "SSL_PORT=${PORT_VARIABLE_FROM_HOST}"

To trouble shoot and make sure that your variables are in fact assigned inside your container run: 要排除故障并确保变量实际上是在容器运行中分配的,请执行以下操作:

docker exec -it <container_name_or_id> printenv

This should list all of the environment variables inside your container 这应该列出容器内的所有环境变量

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

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