在Docker Compose V3中使应用容器能够访问CouchDB容器

92次阅读
没有评论

问题描述

在尝试通过容器连接到CouchDB时遇到问题,他的应用无法看到CouchDB。然而,如果使用外部地址 123.456.789.123:12345 (server_ip:external_port),它可以工作,但他需要通过内部端口 5986 在网络上进行连接。

以下是他的Docker-Compose配置文件:

version: '3'
services:
  couchdb:
    image: couchdb:latest
    restart: always
    volumes:
      - couchdb-data-volume:/usr/local/var/lib/couchdb
    env_file: .env.docker
    ports:
      - "12345:5986"
    networks:
      app-net:
        aliases:
          - couchdb
  app:
    build: .
    image: app
    restart: always
    depends_on:
      - couchdb
    env_file: .env.docker
    networks:
      app-net:
        driver: bridge
volumes:
  couchdb-data-volume:

他还提供了一个环境变量文件 .env.docker,内容如下:

NODE_ENV=production
COUCHDB_SERVER=http://user:pass@couchdb:5986
COUCHDB_USER=user
COUCHDB_PASSWORD=pass

他尝试使用 links 替代网络,但问题依然存在:

links:
  - couchdb

他寻求解决方法。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

最佳解决方案

问题出在您没有将 app 服务注册到 app-net 网络上。要让容器能够相互连接,它们必须共享一个网络,并使用镜像名称作为域名。Docker 提供了网络内部的 DNS 服务。

您需要做以下更改来修复这个问题:

app 服务中,添加 container_name: app 来设置容器名称。

同时,将 app 服务注册到 app-net 网络中,将 networks: 部分调整如下:

version: '3'
services:
  couchdb:
    # ... 其他配置 ...
    networks:
      app-net:
        aliases:
          - couchdb
  app:
    build: .
    image: app
    container_name: app
    restart: always
    depends_on:
      - couchdb
    env_file: .env.docker
    networks:
      - app-net
volumes:
  couchdb-data-volume:
networks:
  app-net:

app 服务中,现在可以使用 http://couchdb:5986 来访问 couchdb 服务。您可以使用以下命令在 app 服务内部测试这一点:docker exec -it app bash,这取决于 container_name 的设置。

备选解决方案

另一种方法是使用脚本或工具来控制容器的启动顺序。您可以使用 docker run 命令手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。以下是一个简单的 Bash 脚本示例,可以在容器 A 启动后启动容器 B:

#!/bin/bash
# 启动容器 A
docker run -d --name container_a your_image_a
# 等待容器 A 完全启动
while ! docker exec container_a echo "Container A is ready"; do
  sleep 1
done
# 启动容器 B
docker run -d --name container_b your_image_b

在这个示例中,我们首先使用 docker run 命令启动容器 A,并将其命名为 container_a。然后,使用一个循环来等待容器 A 完全启动(这里是通过在容器内运行 echo 命令来测试)。一旦容器 A 就绪,我们再使用 docker run 命令启动容器 B,并将其命名为 container_b

以上是两种解决方案,您可以根据您的需求选择其中之一来解决您的问题。

正文完