代码之家  ›  专栏  ›  技术社区  ›  Lucifer N.

Docker-如何在构建时从Docker compose传递环境变量和最佳实践?

  •  0
  • Lucifer N.  · 技术社区  · 2 年前

    我有一个正在尝试容器化的应用程序,它由一个带有PostgreSQL、elasticsearch和redis服务的Web应用程序组成。在运行应用程序之前,我的Web应用程序需要用Postgres的数据填充redis和elasticsearch服务中的数据,因此我在应用程序的dockerfile中使用了一个入口点。为了填充这些服务,我的应用程序使用docker compose网络在其自己的(特定于应用程序的)设置文件中设置的服务地址,我已将这些设置文件设置为docker compose中的环境变量 environment 将应用程序的一部分传递到容器中。

    我的 docker-compose.yml 文件如下:

    version: '3'
    services:
    
      redis:
        image: 'redis:alpine'
        expose: 
           - 6379:6379
    
     
      elasticsearch:
        image: 'docker.elastic.co/elasticsearch/elasticsearch:7.13.1'
        environment: 
          - node.name=node-1
          - cluster.initial_master_nodes=node-1
        expose:
          - "9200:9200"
    
      db:
        image: 'postgres:latest'
        build:
          context: ./docker/db
          dockerfile: Dockerfile   
        environment:
          POSTGRES_USER: myuser
          POSTGRES_HOST_AUTH_METHOD: trust
          POSTGRES_DB: mydb
     
      app:
        build: ./app
        ports:
          - '8000:8000'
        volumes: 
          - ./database:/var/lib/postgresql
    
        environment:
        - REDIS_HOST = redis
        - DB_NAME=mydbname
        - DB_USER=myusername
        - ES_URL = elasticsearch
    
        links:
          - redis
          - db 
          - elasticsearch
        depends_on:
          - redis
          - db
          - elasticsearch
    

    我的应用程序的dockerfile(相关部分)就是这样,其中 entrypoint.sh 脚本包含用于填充这些服务的命令:

    # copy project
    COPY . .
    RUN chmod +x entrypoint.sh
    
    #compile assets for testing and insert data from db into Elasticsearch and Redis
    ENTRYPOINT ["./entrypoint.sh"]
    

    然而,这些服务的地址似乎并没有作为环境变量从 docker-compose.yml 当入口点脚本运行时,应用程序容器无法访问它们,尽管在早期版本中(没有入口点脚本),它们似乎在容器启动并运行后就被传递到了容器中。我在这里有点困惑,因为据我所知,入口点脚本的运行方式就像它们处于容器的运行阶段,而不是构建阶段一样,因此它们应该可以访问来自 docker-compose.yml .

    在这个阶段传递环境变量似乎有几种选择,如果一个容器需要在最终版本之前访问内部网络上的其他容器,我不确定这里的最佳做法是什么 CMD 声明它在哪里运行和公开。

    谢谢

    1 回复  |  直到 2 年前
        1
  •  0
  •   larsks    2 年前

    这还不是一个答案,因为我在等你的一些补充信息。但是,我想强调一下您现有配置中的几个问题:

    • 不要使用 links 在您的撰写文件中;该功能已经 deprecated 已经好几年了。Docker为同一网络上的容器维护自动DNS条目,因此您始终可以按名称引用组成文件中的其他服务。

    • 看起来你混淆了 expose ports 指令。

      这个 暴露 该语句实际上是一个禁止操作(对于阅读您的撰写文件的人来说,它提供了丰富的信息,但在其他方面并不是特别有用)。

      您可以使用 港口 指令。而不是:

      expose:
        - "9200:9200"
      

      你想要:

      ports:
        - "9200:9200"
      
    • 简短的形式 depends_on 实际上也是无用的。它使一个容器依赖于另一个容器的成功启动,但它对 服务 例如,如果你 依赖 Postgres,在它真正准备好接受连接之前,您可能仍然会尝试与Postgres交互。

      有一个 long form of depends_on ,但要使其有效,您需要对容器进行健康检查。

      要么使用长格式,要么在应用程序中实现连接和重试逻辑。

    看起来您可能正在使用一些旧文档;这个 compose syntax reference 值得一读。


    其余答案待定,等待您的问题/评论的更新。。。