如何在不推送 .env 文件的情况下使用环境变量构建 docker-image

How to build docker-image with environment variables while not pushing .env-file

我是 Dev-Ops 的新手,发现自己有点困惑。 我有一个启动服务器的节点项目。该服务器的一个端点应该写入数据库。在我的本地机器上,我使用本地数据库测试此行为。 我创建了一个 .env.prod 文件和一个 .env.dev 文件来确定我是使用本地数据库还是我的服务器数据库(运行 在我的服务器上)。我还在博客文章中读到我永远不应该将我的 .env 文件推送到远程存储库。

然后我创建了一个 Dockerfile 来构建和发布我的应用程序。

在我的远程 Gitlab-Repository 上,我创建了一个 .gitlab-ci.yml,它应该在每次有新的 master 提交时从 Dockerfile 构建 docker-image。

但现在我面临的问题是,当我想构建 docker-image 时,我需要 .env.prod 文件,但我永远不应该推送此文件,因此 GitLab 无法访问它。

这种描述方式是合适的解决方案还是我做错了什么(我是否遗漏了 Dev-ops 中的一些核心概念)?

这是我的 Dockerfile

FROM node:12.7-alpine AS build

WORKDIR /usr/graphql-server
COPY package.json /usr/graphql-server/

RUN npm install
COPY ./ /usr/graphql-server

RUN npm run build
COPY ./ /usr/graphql-server

EXPOSE 4000

CMD ["npm", "run", "start:prod"]

npm run start:prod 这样做:

tsc && cross-env NODE_ENV=prod node dist/index.js

这就是我确定要使用哪种配置的方式 (index.ts):

function getConfig(): void {
  let path;
  if (process.env.NODE_ENV === 'prod') {
    path = `${__dirname}/../src/.env.prod`;
  } else {
    path = `${__dirname}/../src/.env.dev`;
  }
  dotenv.config({ path });
}

最后,感谢@AndreasJägle,我想出了一个完全不同的解决方案来解决我最初想到的问题。 我不需要 .env-file 并且不再将描述的 getConfig() 方法用于此解决方案。同样也不需要在 Gitlab 中存储 environment-variables。

首先,我现在通过在节点命令末尾传递环境变量来启动我的节点进程,例如 node dist/index.js variable1。 这个环境变量可以在运行时读取:const baseUrl = process.argv[2]。 baseUrl-variable 可以用来向这个特定的 url 发送请求。

其次,因为我正在使用 docker 构建我的项目,所以我必须将 environment-variables 的值注入到我的 docker-image 中。为此,我像这样修改了我的 docker 文件。

FROM node:12.7-alpine AS build

ENV BASE_URL=localhost
    
...

CMD ["sh", "-c", "node dist/index.js $BASE_URL"]

(注意 localhost 是 BASE_URL 环境变量的默认值,将被覆盖)

最后,我在服务器上的 docker-compose 文件中使用了之前构建的映像,并像这样设置了环境变量。

version: "3"

    services:
      test-service:
        image: my-image:latest
        container_name: 'my-container'
        environment:
          - BASE_URL=mydomain.com