micah
Postgrex error (nxdomain) when resolving rootless docker-compose database domain
I’m attempting to setup a rootless docker-compose deployment of an Phoenix app using Podman 4. Unfortunately, when starting the Phoenix App, Ecto throws an error, unable to resolve the database’s domain name (db in the example below)
[error] Postgrex.Protocol (#PID<0.1965.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): non-existing domain - :nxdomain
While troubleshooting I’ve overwritten the phoenix app’s container start command with the following:
command: [“eval”, “IO.inspect :gen_tcp.connect(‘db’, 5432, [packet: :raw, mode: :binary, active: false], 3000)”]
Which yields {:ok, #Port<0.6>} , Indicating to me this is some sort of issue with how Postgrex is utilizing gen_tcp.
I also tried using inet_res directly:
command: [“eval”, “IO.inspect :inet_res.resolve(‘db’, :in, :a)”]
Which seems to successfully resolve the IP:
{:ok,
{:dns_rec, {:dns_header, 1, true, :query, false, false, true, false, false, 0},
[{:dns_query, 'db', :a, :in, false}],
[{:dns_rr, 'db', :a, :in, 0, 86400, {10, 89, 0, 35}, :undefined, [], false}],
[], []}}
When I try to use other valid domains besides db and its alias’s, including localhost, I get connection errors. That makes sense because there is no Postgres instance listening there, but it seems to pass the name resolution step just fine.
The final piece that I’ve noticed on my local machine is that :inet_res.resolve does not resolve domains specified in the host file (/etc/hosts), but gen_tcp.connect seems to. Though the hosts file is not how domain names are set with docker-compose / podman.
Here’s my Repo config (the commented out parts have been tried but haven’t changed the error)
config :phoenix_app, PhoenixApp.Repo,
# ssl: true,
# socket_options: [:inet6],
url: "ecto://user:pass@db/phoenix_app",
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
Have I simply misconfigured something? Is this a bug in Postgrex? What suggestions do you have for debugging this error?
Most Liked
hst337
By the way, since docker released rootless support, I do not use podman, because it is still buggy and podman-compose is still in a buggy alpha state
micah
Of course. Here is my docker-compose file:
version: "3"
services:
app:
image: localhost/phoenix_app_${INSTANCE_NAME}:${phoenix_app_INSTANCE_VERSION}
# image: docker.io/hexpm/elixir:1.14.0-erlang-25.1-alpine-3.16.2
ports:
- "8083:8083"
depends_on:
db:
condition: service_healthy
environment:
- HOSTNAME=localhost
- DATABASE_URL=ecto://user:pass@db/phoenix_app
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
- PORT=8083
networks:
mynetwork:
aliases:
- api.local
# command: ["eval", "IO.inspect :inet_res.resolve('db', :in, :a)"]
# command: ["eval", "IO.inspect :gen_tcp.connect('db', 5432, [packet: :raw, mode: :binary, active: false], 3000)"]
db:
image: postgres:13-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=phoenix_app
networks:
mynetwork:
aliases:
- db.local
healthcheck:
test: [ "CMD", "pg_isready", "-q", "-d", "phoenix_app", "-U", "user" ]
timeout: 45s
interval: 10s
retries: 10
server:
image: caddy:2-alpine
ports:
- ${PORT}:80
- ${SSL_PORT}:443
volumes:
- caddy_data:/data
- caddy_config:/config
# - ./Caddyfile:/etc/caddy/Caddyfile
volumes:
caddy_data:
caddy_config:
networks:
mynetwork:
driver: bridge
And my Containerfile if that is at all interesting:
ARG ELIXIR_VERSION=1.14.0
ARG OTP_VERSION=25.1
ARG ALPINE_VERSION=3.16.2
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-alpine-${ALPINE_VERSION}"
ARG RUNNER_IMAGE="alpine:${ALPINE_VERSION}"
FROM ${BUILDER_IMAGE} as build
ARG MIX_ENV="prod"
# install build dependencies
RUN apk add --no-cache build-base git python3 curl
# prepare build dir
WORKDIR /app
# install hex + rebar
RUN mix local.hex --force && \
mix local.rebar --force
# set build ENV
ARG MIX_ENV
ENV MIX_ENV="${MIX_ENV}"
ARG FORCE_SSL
ENV FORCE_SSL="${FORCE_SSL}"
# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config
# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/$MIX_ENV.exs config/
RUN mix deps.compile
COPY priv priv
# note: if your project uses a tool like https://purgecss.com/,
# which customizes asset compilation based on what it finds in
# your Elixir templates, you will need to move the asset compilation
# step down so that `lib` is available.
COPY assets assets
RUN mix assets.deploy
# compile and build the release
COPY lib lib
RUN mix compile
# changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/
# uncomment COPY if rel/ exists
# COPY rel rel
RUN mix release
# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE} AS app
RUN apk add --no-cache libstdc++ libgcc openssl ncurses-libs ffmpeg
ARG USER
ENV USER="userman"
# Podman bug where MIX_ENV doesn't defined
ARG MIX_ENV="prod"
ENV MIX_ENV="${MIX_ENV}"
WORKDIR "/home/${USER}/app"
# Creates an unprivileged user to be used exclusively to run the Phoenix app
RUN \
addgroup \
-g 1000 \
-S "${USER}" \
&& adduser \
-s /bin/sh \
-u 1000 \
-G "${USER}" \
-h "/home/${USER}" \
-D "${USER}" \
&& su "${USER}"
# Everything from this line onwards will run in the context of the unprivileged user.
USER "${USER}"
COPY --from=build --chown="${USER}":"${USER}" /app/_build/"${MIX_ENV}"/rel/phoenix_app ./
ENTRYPOINT ["bin/phoenix_app"]
# Usage:
# * build: sudo docker image build -t elixir/my_app .
# * shell: sudo docker container run --rm -it --entrypoint "" -p 127.0.0.1:4000:4000 elixir/my_app sh
# * run: sudo docker container run --rm -it -p 127.0.0.1:4000:4000 --name my_app elixir/my_app
# * exec: sudo docker container exec -it my_app sh
# * logs: sudo docker container logs --follow --tail 100 my_app
CMD ["start"]
I’m really very stumped with this one, so any suggestions are appreciated!
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








