【问题标题】:Remove sensitive information from environment variables in postgres docker container从 postgres docker 容器中的环境变量中删除敏感信息
【发布时间】:2020-01-19 02:11:58
【问题描述】:

我想制作一个 postgres 数据库映像,但不想公开使用 docker-compose.yml 文件生成时存储为环境变量的密码和用户名。基本上,我不希望任何人执行到容器中并找出变量。

一种方法是使用 docker-secrets,但我不想使用 docker swarm,因为我的容器将在单个主机上运行。

我的 docker-compose 文件 -

    version: "3"
    services:
       db:
         image: postgres:10.0-alpine
      environment:
         POSTGRES_USER: 'user'
         POSTGRES_PASSWORD: 'pass'
         POSTGRES_DB: 'db'

我尝试过的事情 -

1) 在entrypoint-entrypoint.sh末尾取消设置环境变量

        for f in /docker-entrypoint-initdb.d/*; do
            case "$f" in
            *.sh)     echo "$0: running $f"; . "$f" ;;
            *.sql)    echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;;
            *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;;
            *)        echo "$0: ignoring $f" ;;
            esac
            echo
        done
        unset POSTGRES_USER

但什么也没发生。 :(

2) docker-entrypoint-initdb.d 中的 init.sql,在不使用 env 的情况下创建 db、user 和 pass。 我分享了卷,因为 -

```
   volumes:
       - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
```

并且,在我的主机上,在 docker-entrypoint-initdb.d 中,我将 init.sql 保存为 -

CREATE DATABASE docker_db;CREATE USER docker_user with encrypted password 'pass';GRANT ALL PRIVILEGES ON DATABASE docker_db TO docker_user;

我移动到正在运行的容器中,并且该文件在那里,但是没有创建文件中提到的用户或数据库。

过去两天我一直坚持这一点,非常感谢任何帮助。

【问题讨论】:

  • 如果您在 docker-compose 中设置 ENV,它将包含 ENV,只需尝试运行 docker exec -it db bash -c "printenv" ,而未设置的工作正常。
  • @Adiii ,除了在环境中指定之外,还有其他方法可以创建数据库和用户吗?请阅读我的整个问题。

标签: postgresql docker docker-compose dockerfile docker-swarm


【解决方案1】:

使用不带值的 args 在您的 Dockerfile 中构建图像:

ARG PASSWORD 

并使用

构建它
export PASSWORD="MYPASS" && docker build ...

这样ARG在运行container时不存在

这是一个完整的例子:

dockerfile:

FROM postgres:10.0-alpine

ARG my_user
ARG my_pass

Compose:

version: "3"
services:
       db:
         build:
           context: .
           args:
            - my_user
            - my_pass       
         environment:
           - POSTGRES_USER=${my_user}
           - POSTGRES_PASSWORD=${my_pass}
           - POSTGRES_DB=db

运行它:

export my_user=test && export my_pass=test1cd && docker-compose up -d --build

现在如果你登录到container 并尝试echo $my_pass 你会得到一个空字符串

结果:

docker exec -ti 3b631d907153 bash

bash-4.3# psql -U test db
psql (10.0)
Type "help" for help.

db=#

【讨论】:

  • 警告:未设置 my_user 变量。默认为空字符串。警告:未设置 my_pass 变量。默认为空字符串。错误:Compose 文件 './docker-compose.yml' 无效,因为:services.db.environment 包含 {"POSTGRES_USER": ""},这是一个无效类型,它应该是一个字符串 @LinPy
  • 我只是将您的代码复制粘贴到 Dockerfile 中,编写文件并使用您的命令运行。
  • 容器运行良好(环境变量更新为空字符串),但用户不是在 postgres 中创建的。 @LinPy
  • 尝试使用您在导出时使用的用户名/密码连接到数据库,它应该可以工作,docker exec -it db psql -U USER db
  • psql: FATAL: role "test" does not exist docker exec -it container_id psql -U test @LinPy 我使用了相同的用户并通过了你回答中提到的。
【解决方案2】:

更新

在 Compose 中使用 docker 机密之前,请考虑这个 SO question 和那个 github answer


您可以使用docker secrets in Compose

docker postgresql docs相关部分所述:

作为通过环境传递敏感信息的替代方法 变量,_FILE 可以附加到之前列出的一些 环境变量,导致初始化脚本加载 这些变量的值来自容器中存在的文件。在 特别是,这可用于从 Docker 机密中加载密码 存储在/run/secrets/<secret_name> 文件中。

因此您的撰写文件可以读取:

version: "3"
services:
  db:
    image: postgres:10.0-alpine
  environment:
    POSTGRES_USER_FILE: /run/secrets/user
    POSTGRES_PASSWORD_FILE: /run/secrets/pass
    POSTGRES_DB_FILE: /run/secrets/db
  secrets:
    - user
    - pass
    - db

secrets:
  user:
    file: user.txt
  pass:
    file: pass.txt
  db: 
    file: db.txt

【讨论】:

    【解决方案3】:

    对于任何其他环境变量,您可以查看@LinPy 的答案。它巧妙地使用 Docker Image 构建时变量来覆盖这些值。但至少,我无法在这种情况下受益,可能是因为这些是 postgres 的一些“特殊”变量并且无法覆盖它们(欢迎在评论部分进行任何解释)。

    所以,现在来解决问题 -

    问题 - 不希望 postgres 的用户名/密码作为环境变量可见。

    解决方案 - 不要指定它们是 compose 的环境变量部分。

    相反,使用脚本创建用户/数据库。 Postgres 的镜像运行一个入门级脚本,该脚本依次在 docker-entrypoint-initdb.d 目录中查找任何 .sh/.sql 文件并运行它。

    例子,

    目录结构-

    -docker-compose.yml
    -docker-entrypoint-initdb.d
      -init.sql
    

    我的 docker-compose 文件 -

    version: "3"
    
    services:
        db:
          image: postgres:10.0-alpine
          ports:
            - 8765:5432
          volumes:
            - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    

    init.sql 文件

    CREATE DATABASE docker_db;CREATE USER docker_user with encrypted password 'pass';GRANT ALL PRIVILEGES ON DATABASE docker_db TO docker_user;
    
    docker-compose up
    docker exec -it container-id bash
    psql -U docker_user docker_db
    psql (10.0)
    Type "help" for help.
    
    docker_db=>
    
    

    现在,从您的主机中删除 init.sql,因为它是共享卷,它也会从您的容器中删除。

    【讨论】:

      【解决方案4】:

      我不希望任何人执行到容器中并找出变量。

      这不现实,我不会担心。

      这里的根本问题是 Docker 没有任何访问控制特别是有人可以运行 docker 命令。 如果你可以运行任何docker 命令,那么你就可以不受限制地访问主机。例如,你可以

      docker run --rm -it -v /:/host busybox vi /host/etc/sudoers
      docker exec -it myapp_db env
      docker inspect myapp_dbadmin
      docker exec -it myapp_app cat ./db_config.yml
      docker run --rm -it -v /:/host busybox cat /host/$PWD/db_config.yml
      

      这里最简单的做法是根本不让任何您不信任的用户访问系统。 (如果您在云环境中,两个一半大小的云实例通常与一个更大的实例具有相同的成本,因此以这种方式划分用户可能很简单。)

      理论上,您可以通过确保docker 访问受到限制(例如,在sudo 后面)、仅在文件中传递凭据并确保相应的主机文件也具有适当的文件权限来限制事情,以便他们可以'不被阅读。这通常涉及将此配置移出docker-compose.yml 文件。这不是“常规”的 Docker 配置,但它确实解决了环境变量并不那么安全的问题。

      【讨论】:

        【解决方案5】:

        你已经在 DockerHub 的 Postgres 页面上描述了这种方式。

        “Docker 秘密

        作为通过环境变量传递敏感信息的替代方法,_FILE 可能会附加到一些先前列出的环境变量中,从而导致初始化脚本从容器中存在的文件中加载这些变量的值。特别是,这可用于从存储在 /run/secrets/ 文件中的 Docker 机密中加载密码。例如:

        $ docker run --name some-postgres -e POSTGRES_PASSWORD_FILE=/run/secrets/postgres-passwd -d postgres
        

        目前,这仅支持 POSTGRES_INITDB_ARGS、POSTGRES_PASSWORD、POSTGRES_USER 和 POSTGRES_DB。"

        检查服务时可以看到什么:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-08-12
          • 2016-03-07
          • 1970-01-01
          • 2016-05-30
          • 1970-01-01
          • 2015-11-20
          • 1970-01-01
          相关资源
          最近更新 更多