Docker-compose环境变量

72

我正试图设置一个Postgres容器,并希望用以下方式设置Postgres登录:

POSTGRES_USER: docker
POSTGRES_PASSWORD: docker

所以我已经创建了 docker-compose.yml 如下

web:
  build: .
  ports:
    - "62576:62576"
  links:
   - redis
   - db
db:
  image: postgres
  environment:
    POSTGRES_PASSWORD: docker
    POSTGRES_USER: docker

redis:
   image: redis

我也尝试了另一种环境变量声明的语法,将db部分声明为:

db:
  image: postgres
  environment:
   - POSTGRES_PASSWORD=docker
   - POSTGRES_USER=docker

然而这两个选项似乎都不起作用,因为无论我使用哪种连接字符串尝试连接到Postgres数据库,都会出现某些问题:

postgres://postgres:postgres@db:5432/users
postgres://postgres:docker@db:5432/users
postgres://docker:docker@db:5432/users

他们都告诉我认证失败了,而不是抱怨没有用户数据库。


2
@db 意味着远程连接,但没有任何迹象表明您已在 postgresql.confpg_hba.conf 中允许它们,特别是最后一个。不在问题中直接包含身份验证错误消息是没有意义的。 - Daniel Vérité
1
我遇到了非常类似的问题。我已经在 pg_hba.conf 中进行了必要的更改以允许远程连接。问题似乎是 docker-compose 忽略了环境变量 POSTGRES_PASSWORD - jap1968
8个回答

99

我曾经因为这个问题苦苦挣扎,而且接受的答案也没有帮到我。最后,我通过移除容器解决了它:

docker-compose rm postgres

然后还有音量

docker volume rm myapp_postgres

然后当我执行了全新的docker-compose up之后,我看到CREATE ROLE已经被执行了,我猜想在最初的up中可能被忽略了。


这个问题的原因在于这里进行了详细说明,该Git存储库是用于Docker官方postgres镜像的。


3
这是否意味着环境变量只在第一次运行时被读取,在以后的所有运行中都会被忽略?如果是这样,可能最好在第一次运行后将那些变量和变量值手动删除。 - wotanii
2
是的@wotanii,看起来那就是原因。你的洞察力让我找到了这个相关问题。我会更新答案并引用它。谢谢! - davetapley
3
哇,非常感谢你 @dukedave。你的回答让我今天过得很愉快! - m.w.
2
在找到这个答案之前,我花了一天以上的时间。谢谢! - Scott Terry
2
我浪费了很多时间,只是为了用 docker-compose rm 来解决它... 这就像 Drupal 清除缓存两次一样... - Steve
显示剩余7条评论

47

如果您正在使用Docker

请检查本地数据库是否处于活动状态,因为它往往会与Docker冲突。如果是这样,您可以停用它、更改端口号或卸载它以避免冲突。


5
耶稣啊,我已经让三个工程师连续一整天地试图找出问题出在哪里。然后有人指出了这条评论。结果发现有人很久以前安装了本地的postgres测试,而我们正在尝试连接错误的postgres -_-. 停掉了Windows服务,现在完美解决了。非常感谢! - FatalCatharsis
2
非常高兴听到这个有所帮助。 - Abdelsalam Megahed
1
我浪费了一整天的时间,直到看到这个。非常感谢。但愿我能点赞两次。 - Oluwasegun Wahaab
我猜Docker日志没有显示任何登录失败的尝试应该引起警觉。我已经暴露了一个不同的端口,可以同时运行两个实例 - 谢谢! - Johnny Bueti
非常感谢您,先生。您已经帮我省去了很多麻烦。 - Nadar
显示剩余2条评论

24

你收到的认证错误会对我们帮助很大!

我使用你的参数启动了Postgres镜像:

docker run --name db -d -e POSTGRES_PASSWORD=docker -e POSTGRES_USER=docker postgres

然后我在以下位置执行:

docker exec -it db psql -U docker user
psql: FATAL:  database "user" does not exist

我收到了你所期望的错误信息,因为我使用的是信任身份验证:

docker exec -it db cat /var/lib/postgresql/data/pg_hba.conf | grep -v '^#'

local   all             all                                     trust
host    all             all             127.0.0.1/32            trust
host    all             all             ::1/128                 trust
host all all 0.0.0.0/0 md5
为了模拟您的 Web 容器,我将运行另一个 PostgreSQL 容器实例并连接数据库容器,然后再连接回数据库容器。
core@ku1 /tmp/i $ docker run --rm --name web --link db:db -it postgres psql -h db -Udocker user
Password for user docker: 
psql: FATAL:  password authentication failed for user "docker"

如果我输入错误的密码,会得到身份验证错误。但是,如果我输入正确的密码:

core@ku1 /tmp/i $ docker run --rm --name web --link db:db -it postgres psql -h db -Udocker user
Password for user docker: 
psql: FATAL:  database "user" does not exist

一切似乎都正常运行。我将所有内容都放在一个yaml文件中,并以这种方式进行了测试:

web:
  image: postgres
  command: sleep 999
  ports:
    - "62576:62576"
  links:
   - db
db:
  image: postgres
  environment:
    POSTGRES_PASSWORD: docker
    POSTGRES_USER: docker

然后使用docker-compose启动它:

core@ku1 /tmp/i $ docker-compose -f dc.yaml up
Creating i_db_1...
Creating i_web_1...
Attaching to i_db_1, i_web_1
db_1  | ok
db_1  | creating template1 database in /var/lib/postgresql/data/base/1 ... ok
db_1  | initializing pg_authid ... ok
db_1  | initializing dependencies ... ok
db_1  | creating system views ... ok
db_1  | loading system objects' descriptions ... ok
db_1  | creating collations ... ok
db_1  | creating conversions ... ok
db_1  | creating dictionaries ... ok
db_1  | setting privileges on built-in objects ... ok
db_1  | creating information schema ... ok
db_1  | loading PL/pgSQL server-side language ... ok
db_1  | vacuuming database template1 ... ok
db_1  | copying template1 to template0 ... ok
db_1  | copying template1 to postgres ... ok
db_1  | syncing data to disk ... ok
db_1  | 
db_1  | WARNING: enabling "trust" authentication for local connections
db_1  | You can change this by editing pg_hba.conf or using the option -A, or
db_1  | --auth-local and --auth-host, the next time you run initdb.
db_1  | 
db_1  | Success. You can now start the database server using:
db_1  | 
db_1  |     postgres -D /var/lib/postgresql/data
db_1  | or
db_1  |     pg_ctl -D /var/lib/postgresql/data -l logfile start
db_1  | 
db_1  | 
db_1  | PostgreSQL stand-alone backend 9.4.1
db_1  | backend> statement: CREATE DATABASE "docker" ;
db_1  | 
db_1  | backend> 
db_1  | 
db_1  | PostgreSQL stand-alone backend 9.4.1
db_1  | backend> statement: CREATE USER "docker" WITH SUPERUSER PASSWORD 'docker' ;
db_1  | 
db_1  | backend> 
db_1  | LOG:  database system was shut down at 2015-04-12 22:01:12 UTC
db_1  | LOG:  database system is ready to accept connections
db_1  | LOG:  autovacuum launcher started
^Z
[1]+  Stopped                 docker-compose -f dc.yaml up
core@ku1 /tmp/i $ bg

你可以看到用户和密码已被创建。我运行的命令是:

core@ku1 /tmp/i $ docker exec -it i_web_1 psql -Udocker -h db user
Password for user docker: 
psql: FATAL:  password authentication failed for user "docker"
core@ku1 /tmp/i $
db_1  | FATAL:  password authentication failed for user "docker"
db_1  | DETAIL:  Connection matched pg_hba.conf line 95: "host all all 0.0.0.0/0 md5"

core@ku1 /tmp/i $ docker exec -it i_web_1 psql -Udocker -h db user
Password for user docker: 
psql: FATAL:  database "user" does not exist
db_1  | FATAL:  database "user" does not exist

所以我能想到的唯一事情就是您正在尝试从您的主机连接到数据库,而不是从Web容器连接?或者您的Web容器没有使用“db”作为连接的主机?我看不出您对Web容器的定义中存在任何错误。


9
感谢你的帮助,结果发现在第一次创建镜像时出现了一些奇怪的问题,导致我看到了身份验证问题。执行 docker-compose rm,然后再执行 docker-compose up 可以解决这个问题。 - royalaid

23

我曾经遇到过同样的问题,而在我的情况下,这个问题被一个命令解决了:

docker-compose up --force-recreate

我尝试了这个选项,但之后我收到了这个错误:守护进程的错误响应:重复挂载点:/var/lib/postgresql/data。 - Burillodev

10

感谢Bryan提供的docker-compose exec containername env,我发现还需要删除卷。由于使用docker-compose volume rm volumename需要知道确切的名称,所以更简单的方法是删除全部内容:

docker-compose down --volumes

7

这对我很有帮助

docker stop $(docker ps -qa) && docker system prune -af --volumes && docker compose up

3
在我的情况下,我在Windows 10的WSL2中运行postgres:13-alpine,上述解决方案都没有奏效。

我的错误在于,我使用的docker network名称与另一个项目共享。假设我有A和B两个项目,两者结构相同:

myappfolder
  - docker-compose.yml
    - services
        - app
            - depends on db
        - db

默认情况下,docker-compose 会从 docker-compose.yml 文件所在的上级目录名中获取 network 名称。因此,项目 A 和 B 都试图连接到同一个网络:myappfolder_default
为了解决这个问题:
  1. 确保项目的网络名称是唯一的:

    a. 要么更改根文件夹的名称使其唯一

    b. 或者编辑你的 docker-compose.yml 文件以设置显式的网络名称

  2. 执行 docker-compose down -v 命令,这将重置网络中定义的所有可能的数据库 > 在继续之前,请确保进行 psql 倾倒

  3. 执行 docker-compose up 命令

更多网络文档请参考:https://docs.docker.com/compose/networking/

1
这对我有效,谢谢。 - alfonsoolavarria

1

我遇到了类似的情况。在@Greg的回答下,我执行了docker-compose up,然后它就获取了环境变量。

在此之前,我一直在使用docker-compose run,但是它没有获取环境变量,这可以通过运行docker-compose exec task env来证明。奇怪的是,docker-compose run task env显示了我期望的环境变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接