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

Docker环境下Ecto连接MySQL失败问题求助

Phoenix应用Docker化后无法连接MySQL的问题排查与解决

问题描述

Phoenix应用Docker化后,执行docker compose up时无法连接MySQL数据库,尝试将DB_HOST设为0.0.0.0或localhost均无效,报错连接拒绝。

错误信息

server-1    | 11:23:07.417 [error] GenServer #PID<0.272.0> terminating
server-1    | ** (DBConnection.ConnectionError) (0.0.0.0:3306) connection refused - :econnrefused
server-1    |     (db_connection 2.4.3) lib/db_connection/connection.ex:100: DBConnection.Connection.connect/2
server-1    |     (connection 1.1.0) lib/connection.ex:622: Connection.enter_connect/5
server-1    |     (stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
server-1    | Last message: nil
server-1    | State: MyXQL.Connection
server-1    |
server-1    | 11:23:07.430 [error] GenServer #PID<0.278.0> terminating
server-1    | ** (DBConnection.ConnectionError) (0.0.0.0:3306) connection refused - :econnrefused
server-1    |     (db_connection 2.4.3) lib/db_connection/connection.ex:100: DBConnection.Connection.connect/2
server-1    |     (connection 1.1.0) lib/connection.ex:622: Connection.enter_connect/5
server-1    |     (stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
server-1    | Last message: nil
server-1    | State: MyXQL.Connection
server-1    | ** (Mix) The database for App.Repo couldn't be created: %RuntimeError{message: "killed"}
server-1 exited with code 1

核心问题分析

  1. 数据库连接地址错误:Docker Compose默认网络中,容器间通过服务名互相访问。0.0.0.0是服务监听地址而非连接地址,localhost在容器内指向自身,无法访问MySQL容器。
  2. 数据库就绪判断不足:depends_on: condition: service_started仅确保MySQL容器启动,但MySQL服务需要时间完成初始化,此时应用尝试连接会失败。

解决方案

1. 修正DB_HOST配置与健康检查

修改docker-compose.yml,将DB_HOST改为MySQL服务名database,并为数据库添加健康检查,确保服务就绪后再启动应用:

version: '3.8'

services:
  server:
    image: server
    environment:
      DB_HOST: database
      DB_DATABASE: dev
      DB_PORT: 3306
      DB_USER: dev
      DB_PASSWORD: dev
    ports:
      - "4000:4000"
    restart: on-failure
    depends_on:
      database:
        condition: service_healthy
  database:
    image: mysql:latest
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: dev
      MYSQL_PASSWORD: dev
      MYSQL_DATABASE: dev
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "dev", "-pdev"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  mysql_data:

2. 增强应用启动前的数据库等待逻辑

修改entry.sh,添加循环检测确保MySQL服务就绪后再执行数据库初始化:

# Exit on failure
set -e

# 等待MySQL服务就绪
until mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1"; do
  echo "等待MySQL数据库启动..."
  sleep 2
done

mix ecto.create
mix ecto.migrate
mix run priv/repo/seeds.exs

exec mix phx.server

同时更新Dockerfile,安装mysql-client以支持mysql命令:

FROM elixir:latest

EXPOSE 4000

# 安装mysql-client
RUN apt-get update && apt-get install -y mysql-client && rm -rf /var/lib/apt/lists/*

RUN mkdir /server
COPY . /server
WORKDIR /server

RUN mix local.rebar --force
RUN mix local.hex --force
RUN mix deps.get

RUN mix do compile

CMD [ "sh", "/server/entry.sh" ]

3. 确认数据库用户权限(可选)

若仍有连接问题,可确认dev用户允许从Docker网络连接。默认通过MYSQL_USER创建的用户权限为%(允许所有主机),若需手动授权,可进入MySQL容器执行:

GRANT ALL PRIVILEGES ON dev.* TO 'dev'@'%';
FLUSH PRIVILEGES;

验证步骤

  1. 清理旧容器与数据卷:docker compose down -v
  2. 重新构建server镜像:docker compose build server
  3. 启动服务:docker compose up

此时应用应能正常连接MySQL并完成数据库初始化。

内容的提问来源于stack exchange,提问作者Basil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:55:25