micah

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

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

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!

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Kagamiiiii
Student &amp; New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement