You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Elixir API无法连接MongoDB容器问题求助

问题:Docker部署Elixir API无法连接MongoDB容器

我开发了一个基于Elixir的API,包含Users、Products、Orders模块,使用MongoDB 4.4。本地运行正常,但部署到Docker后始终无法连接另一个容器中的MongoDB,最终连接失败报错。我已经通过MongoDB Compass成功连接该MongoDB容器,推测是配置问题,但尝试了MongoDB容器IP、127.0.0.1、0.0.0.0、localhost等多种地址配置均无效。

错误日志

users_service-elixir_app-1  | 12:06:41.705 [error] Mongo.Protocol (#PID<0.566.0>) failed to connect: ** (Mongo.Error) localhost:27017 tcp connect: connection refused - :econnrefused
users_service-elixir_app-1  |
users_service-elixir_app-1  | 12:06:41.723 [notice] Application api_test exited: exited in: ApiTest.Application.start(:normal, [])
users_service-elixir_app-1  |     ** (EXIT) an exception was raised:
users_service-elixir_app-1  |         ** (MatchError) no match of right hand side value: {:error, :econnrefused}
users_service-elixir_app-1  |             (api_test 0.1.0) lib/services/publisher.ex:2: Api.Service.Publisher.start/2
users_service-elixir_app-1  |             (kernel 9.0.1) application_master.erl:293: :application_master.start_it_old/4
users_service-elixir_app-1  | 12:06:41.722 [error] CRASH REPORT Process <0.456.0> with 0 neighbours exited with reason: no match of right hand value {error,econnrefused} in 'Elixir.Api.Service.Publisher':start/2 line 2 in application_master:init/4 line 142
users_service-elixir_app-1  | 12:06:41.723 [info] Application api_test exited with reason: no match of right hand value {error,econnrefused} in 'Elixir.Api.Service.Publisher':start/2 line 2
users_service-elixir_app-1  | Kernel pid terminated (application_controller) ({application_start_failure,api_test,{bad_return,{{'Elixir.ApiTest.Application',start,[normal,[]]},{'EXIT',{{badmatch,{error,econnrefused}},[{'Elixir.Api.Service.Publisher',start,2,[{file,"lib/services/publisher.ex"},{line,2}]},{application_master,start_it_old,4,[{file,"application_master.erl"},{line,293}]}]}}}}})
users_service-elixir_app-1  |
users_service-elixir_app-1  | Crash dump is being written to: erl_crash.dump...done
users_service-elixir_app-1 exited with code 1

相关配置文件

Dockerfile

FROM elixir:1.14

# Set environment variables
ENV MIX_ENV=prod TERM=xterm

# Create app directory and copy project files
WORKDIR /app
COPY . /app

# Install hex package manager and rebar
RUN mix local.hex --force && mix local.rebar --force

# Install dependencies and compile the project
RUN mix deps.get && mix deps.compile && mix compile

# Expose the desired port (3000)
EXPOSE 3000

# Start the server
CMD ["mix", "run", "--no-halt"]

docker-compose.yml

version: '3'
services:
  elixir_app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:     # Docker need to expose ports for you to access your app.
      - 3000:3000
    depends_on:
      - mongodb
      - rabbitmq

  mongodb:
    image: mongo:4.4
    container_name: mongodb
    restart: always
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=example
    ports:
      - 27017:27017

  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    environment:
      - RABBITMQ_DEFAULT_USER=guest
      - RABBITMQ_DEFAULT_PASS=guest
    ports:
      - 5672:5672
      - 15672:15672

config.exs

use Mix.Config

import_config "#{config_env()}.exs"

# config :api_test,
# api_host: "localhost",
# api_port: 3000,
# api_scheme: "http",
# app_secret_key: "secret",
# jwt_validity: 3600,
# db_host: "localhost",
# db_port: 27017,
# db_db: "ski-online-shop",
# db_tables: [
# "users"
# ],
#
# routing_keys: %{
#     # User Events
#     "user_login" => "api.login.auth-login.events",
#     "user_logout" => "api.login.auth-logout.events",
#     "user_register" => "api.login.auth-register.events",
#     # Order Events
#     "order_added" => "api.order.add.events",
#     "pay_order" => "api.order.pay.events",
#     # Invoice Events
#     "invoice_added" => "api.invoice.add.events"
# },
# event_url: "guest:guest@localhost",
# event_exchange: "my_api",
# event_queue: "auth_service"

dev.exs 和 prod.exs(内容一致)

use Mix.Config
config :users_service, port:3000
config :users_service, database: "ski-online-shop"
config :users_service, pool_size: 2
config :users_service, :c, username: "user", password: "secret"

config :users_service, :db_config,
  name: :mongo,
  url: "mongodb://mongodb:27017/ski-online-shop"

config :amqp,
  connections: [
    myconn: [url: "guest:guest@localhost"]
  ],
  channels: [
    mychan: [connection: :myconn]
  ]

解决方案

1. 修复MongoDB认证不匹配问题

你的MongoDB容器配置了root账号和example密码,但Elixir配置中使用的是user和secret,账号密码不匹配会直接导致连接失败。修改dev.exs和prod.exs中的数据库配置,添加正确的认证信息:

config :users_service, :db_config,
  name: :mongo,
  url: "mongodb://root:example@mongodb:27017/ski-online-shop?authSource=admin"

2. 对齐配置模块与应用名称

错误日志显示应用是api_test,但你的配置都是针对users_service的,这说明应用实际读取的配置项和你定义的不匹配。检查Mongo连接代码,确保读取的配置键与配置文件一致:

  • 如果连接代码是Application.get_env(:api_test, :db_config),则将配置改为config :api_test, :db_config, ...

3. 确保MongoDB服务就绪后再启动Elixir应用

depends_on仅保证容器启动顺序,不保证MongoDB服务完全可用。添加健康检查确保服务就绪:
修改docker-compose.yml中的mongodb服务:

mongodb:
  image: mongo:4.4
  container_name: mongodb
  restart: always
  environment:
    - MONGO_INITDB_ROOT_USERNAME=root
    - MONGO_INITDB_ROOT_PASSWORD=example
  ports:
    - 27017:27017
  healthcheck:
    test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')", "--username", "root", "--password", "example", "--authenticationDatabase", "admin"]
    interval: 5s
    timeout: 5s
    retries: 5

修改elixir_app服务的依赖条件:

elixir_app:
  build:
    context: .
    dockerfile: Dockerfile
  ports:
    - 3000:3000
  depends_on:
    mongodb:
      condition: service_healthy
    rabbitmq:
      condition: service_started

4. 修复RabbitMQ连接地址

RabbitMQ配置中使用localhost无法在容器内访问,改为服务名rabbitmq:

config :amqp,
  connections: [
    myconn: [url: "amqp://guest:guest@rabbitmq:5672"]
  ],
  channels: [
    mychan: [connection: :myconn]
  ]

内容的提问来源于stack exchange,提问作者Alexandru-Dan Pop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:47:01