PJUllrich
Use Fly.io internal DNS for resolving Database_URL
I am trying to use fly.io to deploy a simple Phoenix + Ecto app, but have problems connecting Ecto to the provisioned Postgres instance.
I created a postgres instance with flyctl postgres create and attached it to the application with flyctl postgres attach --postgres-app my-app-postgres. This adds a DATABASE_URL environment variable to the application context, which I read out in my releases.exs. I checked and my application receives the correct DATABASE_URL. Unfortunately, Postgresx cannot connect to the database and fails with the error:
Postgrex.Protocol (#PID<0.2945.0>) failed to connect: ** (DBConnection.ConnectionError)
tcp connect (my-app-postgres.internal:5432): non-existing domain - :nxdomain
The problem seems to be Fly’s own DNS resolver, which should resolve the my-app-postgres.internal part in the DATABASE_URL to an IP address. I saw that the LiveView-Counter example project uses a custom DNS Strategy to resolve the APP_NAME.internal URLs. I wondered whether I can set a similar strategy for Ecto to use.
My assumption is that Ecto tries to resolve the my-app-postgres.internal URl with a public DNS instead of the Fly.io internal DNS, which is responsible for the .internal-URLs in the internal network of Fly.
My question is therefore: Do you know how I could configure Phoenix or Ecto to use the internal DNS for the .internal-URLs?
I saw a similar question, where the network_mode in the docker-compose.yml was used to let Phoenix discover other services through the host network, but with Fly.io, one can only use a Dockerfile and not a docker-compose.yml file to create the application. So, I wouldn’t know how to set the network_mode inside the Dockerfile.
Edit: I set the private_network=true flag in my fly.toml file, but it didn’t help:
app = "my-app"
kill_signal = "SIGINT"
kill_timeout = 5
[experimental]
private_network=true
[[services]]
internal_port = 4000
protocol = "tcp"
[services.concurrency]
hard_limit = 25
soft_limit = 20
[[services.ports]]
handlers = ["http"]
port = "80"
[[services.ports]]
handlers = ["tls", "http"]
port = "443"
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
port = "4000"
restart_limit = 6
timeout = "2s"
Marked As Solved
mrkurt
Ecto doesn’t speak IPv6 by default in Phoenix. Will you try adding this to your Ecto repo config?
socket_options: [:inet6]
We need better docs for Elixir apps.
Also Liked
mrkurt
No problem! I just submitted a PR to make this work magically with new Phoenix apps: Enable IPv6 for Ecto by mrkurt · Pull Request #4289 · phoenixframework/phoenix · GitHub
PJUllrich
PJUllrich
Yes, that did the trick. Thank you very much!
mrkurt
Oh wow that’s amazing.
Thanks again for your help!






