Hi guys! I decided to update OTP/Elixir version of my project. I have to switch from Alpine to Debian, because dart_sass has some problems with Alpine and the package I used for solving it is not working anymore. I managed to do the update almost smoothly however I really cannot make the application connect to the database. I’m getting an nxdomain
error. I must miss something and I really can’t spot it. I would really appreciate if someone could take a look and help me finding where the mistake is.
[error] Postgrex.Protocol (#PID<0.3695.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (postgres:5432): non-existing domain - :nxdomain
Docker compose
version: "3.8"
networks:
default:
driver: host
services:
postgres:
image: postgres:15
ports:
- '5432:5432'
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
expose:
- '5432'
restart: always
networks:
- default
elixir:
build:
context: .
dockerfile: Dockerfile
depends_on:
- postgres
environment:
MIX_ENV: ${MIX_ENV}
DATABASE_URL: ${DATABASE_URL}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
AWS_S3_ACCESS_KEY_ID: ${AWS_S3_ACCESS_KEY_ID}
AWS_S3_SECRET_ACCESS_KEY: ${AWS_S3_SECRET_ACCESS_KEY}
SENDGRID_API_KEY: ${SENDGRID_API_KEY}
PORT: ${PORT}
ports:
- '4000:4000'
expose:
- '4000'
networks:
- default
env file
AUTOMATIC_LOGOUT_TIME="99999999999"
CLOSING_TABS_LOGOUT_TIME="99999"
AWS_S3_ACCESS_KEY_ID="some_key"
AWS_S3_SECRET_ACCESS_KEY="some_key"
AWS_S3_BUCKET="some_bucket"
MIX_ENV="dev"
FILE_UPLOAD_ENV="dev"
NODE_ENV="production"
HOST="localhost:4000"
SENDGRID_API_KEY="development_sengrid_api_key"
PORT="4000"
SECRET_KEY_BASE="some_key"
DATABASE_URL="postgres://postgres:postgres@postgres:5432/sample_dev"
POSTGRES_PASSWORD="postgres"
POSTGRES_USER="postgres"
POSTGRES_DB="sample_dev"
DATABASE_SSL="FALSE"
Dockerfile
ARG ELIXIR_VERSION=1.15.2
ARG ERLANG_VERSION=26.0.2
ARG DEBIAN_VERSION=20230612
ARG LINUX_VERSION=debian-bullseye-${DEBIAN_VERSION}-slim
#########################
# Stage: deps-assets #
#########################
FROM hexpm/elixir:${ELIXIR_VERSION}-erlang-${ERLANG_VERSION}-${LINUX_VERSION} as deps-assets
RUN apt-get autoremove -y
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*
RUN apt update
RUN apt-get install -f
RUN apt-get install ca-certificates --assume-yes
RUN apt-get install nodejs --assume-yes
RUN apt-get install npm --assume-yes
RUN apt-get install git --assume-yes
RUN apt-get install gcc --assume-yes
RUN apt-get install build-essential --assume-yes
ENV MIX_ENV=prod \
MIX_HOME=/opt/mix \
HEX_HOME=/opt/hex
WORKDIR /app
COPY . .
RUN mix local.rebar --force \
&& mix local.hex --if-missing --force \
&& mix do deps.get --only $MIX_ENV
WORKDIR /app/apps/sample_web/assets
RUN npm install
#########################
# Stage: release #
#########################
FROM hexpm/elixir:${ELIXIR_VERSION}-erlang-${ERLANG_VERSION}-${LINUX_VERSION} as release
RUN apt-get autoremove -y
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*
RUN apt update
RUN apt-get install -f
RUN apt-get install git --assume-yes
RUN apt-get install gcc --assume-yes
RUN apt-get install build-essential --assume-yes
ENV MIX_ENV=prod \
MIX_HOME=/opt/mix \
HEX_HOME=/opt/hex
WORKDIR /app
COPY . .
COPY --from=deps-assets /app/apps/sample_web/assets/ /app/apps/sample_web/assets/
COPY --from=deps-assets /app/apps/sample_web/priv/static/ /app/apps/sample_web/priv/static/
COPY --from=deps-assets /app/deps/ /app/deps/
COPY --from=deps-assets /app/apps/sample_web/assets/static/images/ /app/apps/sample_web/priv/static/images/
COPY --from=deps-assets /app/apps/sample_web/assets/fonts/ /app/apps/sample_web/priv/static/fonts
RUN mix local.rebar --force \
&& mix local.hex --if-missing --force \
&& mix do deps.get --only $MIX_ENV, deps.compile, assets.deploy
RUN mix release \
&& rm -rf /app/deps
#########################
# Stage: production #
#########################
FROM debian:bullseye-${DEBIAN_VERSION}-slim as production
RUN apt-get autoremove -y
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*
RUN apt update
RUN apt-get install -f
RUN apt-get install openssl
RUN apt-get install gcc --assume-yes
RUN apt-get install build-essential --assume-yes
COPY --from=release /app/_build/prod/rel/sample_umbrella ./
RUN chmod +x /bin/*
CMD ["bin/sample_umbrella", "start"]
EXPOSE 4000
Runtime config:
import Config
defmodule Config.Helper do
def get_env(env, default) when is_number(default) do
value = System.get_env(env)
if value do
String.to_integer(value)
else
default
end
end
def get_env(env, default) do
value = System.get_env(env) || default
"#{value}"
end
end
if System.get_env("MIX_ENV") in ["dev", "prod", nil] do
config :sample, Sample.Repo,
ssl: System.get_env("DATABASE_SSL") == "TRUE",
url: System.get_env("DATABASE_URL"),
socket_options: [:inet6],
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
stacktrace: System.get_env("MIX_ENV") == "dev",
timeout: 30_000,
show_sensitive_data_on_connection_error: System.get_env("MIX_ENV") == "dev"
end
if System.get_env("MIX_ENV") == "test" do
# Configure your database
config :sample, Sample.Repo,
username: "postgres",
password: "postgres",
database: "sample_test",
hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox
end
if System.get_env("MIX_ENV") in ["dev", nil] do
config :sample_web, SampleWeb.Endpoint,
check_origin: ["//#{System.get_env("HOST") || "//our_application_address"}"],
http: [:inet6, port: System.get_env("PORT")],
secret_key_base: System.get_env("SECRET_KEY_BASE"),
server: true,
root: ".",
live_view: [signing_salt: System.get_env("LIVE_VIEW_SALT") || "Nbe6JYiR"],
watchers: [
sass: {
DartSass,
:install_and_run,
[:default, ~w(--embed-source-map --source-map-urls=absolute --watch --quiet)]
},
admin_sass: {
DartSass,
:install_and_run,
[:admin, ~w(--embed-source-map --source-map-urls=absolute --watch --quiet)]
},
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
]
end
if System.get_env("MIX_ENV") == "prod" do
config :sample_web, SampleWeb.Endpoint,
check_origin: ["//#{System.get_env("HOST") || "our_application_address"}"],
http: [:inet6, port: System.get_env("PORT")],
url: [scheme: "https", host: System.get_env("HOST"), port: 443],
force_ssl: [rewrite_on: [:x_forwarded_proto], hsts: true],
cache_static_manifest: "priv/static/cache_manifest.json",
secret_key_base: System.get_env("SECRET_KEY_BASE"),
server: true,
root: ".",
live_view: [signing_salt: System.get_env("LIVE_VIEW_SALT") || "Nbe6JYiR"]
end
config :ex_aws,
access_key_id: System.fetch_env!("AWS_S3_ACCESS_KEY_ID"),
secret_access_key: System.fetch_env!("AWS_S3_SECRET_ACCESS_KEY")
config :sample_web, SampleWeb.Guardian,
secret_key:
System.get_env("GUARDIAN_SECRET_KEY") ||
"sample_key"
config :sample, Sample.Mailer, api_key: System.fetch_env!("SENDGRID_API_KEY")
I use just plain
docker compose build
and
docker compose up
for launching it. The database service is up and running first, with a prompt: “ready to accept connections”.