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

Docker Compose环境下Phoenix服务无法连接PostgreSQL求助

问题描述

我配置了如下docker-compose.yml文件:

version: "3.8"

services:
  plataforma-pescarte:
    build: /home/dev/pescarte
    container_name: plataforma-pescarte
    ports:
      - 8080:8080
    depends_on:
      postgresql:
        condition: service_healthy
    env_file:
      - /home/dev/pescarte/.env
    networks:
      - pescarte-network

  postgresql:
    image: postgres
    container_name: postgresql
    environment:
      - POSTGRES_USER=peapescarte
      - POSTGRES_DB=peapescarte
      - POSTGRES_PASSWORD=<redacted>
    ports:
      - 5432:5432
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U peapescarte -h postgresql -d peapescarte"]
      interval: 5s
      timeout: 2s
      retries: 1
    networks:
      - pescarte-network

networks:
  pescarte-network:

plataforma-pescarte的Dockerfile:

ARG ELIXIR_VERSION=1.14.2
ARG OTP_VERSION=25.1.2.1
ARG DEBIAN_VERSION=buster-20230109-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

RUN apt-get update -y && apt-get install -y build-essential curl \
    && curl -fsSL https://deb.nodesource.com/setup_17.x | bash - \
    && apt-get install -y nodejs

WORKDIR /app

RUN mix local.hex --force && \
    mix local.rebar --force

ENV MIX_ENV="prod"

COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config

# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv
COPY lib lib
COPY assets assets

# compile assets
RUN npm i --prefix ./assets
RUN mix assets.deploy

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

FROM ${RUNNER_IMAGE}

RUN apt-get update -y \
  && apt-get install -y iputils-ping libstdc++6 openssl libncurses5 locales postgresql-client

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR /pescarte
RUN chown nobody /pescarte

# set runner ENV
ENV MIX_ENV="prod"

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/pescarte ./

USER nobody

CMD ["bin/server"]

.env文件内容:

SECRET_KEY_BASE="lDNl9lE0FnTNYArm0Cc7+Z18ocSn8WA2mO36cDxQC+4Ihiuzvs69Lqj9b5QYnYon"

DATABASE_URL="ecto://peapescarte:<redacted>@postgresql:5432/peapescarte"

SSL_KEY_PATH=/etc/ssl/private/ssl-cert-snakeoil.key
SSL_CERT_PATH=/etc/ssl/certs/ssl-cert-snakeoil.pem

ECTO_IPV6=true
UENF_SERVER=true

MIX_ENV=prod
PORT=8080

config/runtime.exs配置:

database_url =
    System.get_env("DATABASE_URL") ||
      raise "DATABASE_URL not available"

  if System.get_env("ECTO_IPV6") do
    config :pescarte, Pescarte.Repo, socket_options: [:inet6]
  end

  config :pescarte, Pescarte.Repo,
    # fly.io don't need
    ssl: false,
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")

构建成功,但执行docker compose up时,plataforma-pescarte服务出现如下错误:

postgresql           | PostgreSQL init process complete; ready for start up.
postgresql           |
postgresql           | 2023-06-23 16:12:06.631 UTC [1] LOG:  starting PostgreSQL 15.2 (Debian 15.2-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
postgresql           | 2023-06-23 16:12:06.632 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgresql           | 2023-06-23 16:12:06.632 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgresql           | 2023-06-23 16:12:06.640 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgresql           | 2023-06-23 16:12:06.652 UTC [64] LOG:  database system was shut down at 2023-06-23 16:12:06 UTC
postgresql           | 2023-06-23 16:12:06.662 UTC [1] LOG:  database system is ready to accept connections
plataforma-pescarte  | 16:12:11.588 [error] Postgrex.Protocol (#PID<0.137.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (postgresql:5432): non-existing domain - :nxdomain

但进入plataforma-pescarte容器执行ping postgresql或pg_isready -U peapescarte -d peapescarte -h postgresql命令时,能正常解析域名并连接PostgreSQL数据库。请问哪里配置出错了?

解决方案

问题出在IPv6配置冲突上:

  1. .env中设置了ECTO_IPV6=true,导致config/runtime.exs给Repo添加了socket_options: [:inet6],强制Ecto使用IPv6连接数据库。
  2. 虽然PostgreSQL日志显示监听了IPv6地址,但Docker默认自定义网络是禁用IPv6的,这就导致Ecto尝试用IPv6解析postgresql域名时失败,抛出:nxdomain错误。
  3. 进入容器后用ping或pg_isready能成功,是因为这些工具默认优先使用IPv4,自动 fallback 到了可用的IPv4地址。

修复方案:

  • 临时快速修复:将.env里的ECTO_IPV6=true改为ECTO_IPV6=false,让Ecto使用IPv4连接,问题即可解决。
  • 永久方案(若确实需要IPv6):在docker-compose.yml的自定义网络中启用IPv6支持,示例配置:
networks:
  pescarte-network:
    enable_ipv6: true
    ipam:
      config:
        - subnet: fd00::/80

同时需要确保Docker daemon本身已启用IPv6支持(修改/etc/docker/daemon.json后重启Docker服务)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:54:55