Hello everyone,
I am learning Phoenix/Elixir and I am trying to dockerize my app so that I can deploy to AWS, but I keep getting all kinds of errors.
I am getting this error:
Recreating myapp_web_1_f59b1c3a118c ... done
Attaching to myapp_web_1_f59b1c3a118c
web_1_f59b1c3a118c | "ecto://postgres:alejandro1@localhost/appexo_prod"
web_1_f59b1c3a118c | 18:45:11.435 [error] Postgrex.Protocol (#PID<0.2424.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
...
web_1_f59b1c3a118c | 18:45:11.438 [error] Postgrex.Protocol (#PID<0.2417.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
web_1_f59b1c3a118c | 18:45:11.443 [info] Running MyappWeb.Endpoint with cowboy 2.6.3 at :::4000 (http)
web_1_f59b1c3a118c | 18:45:11.443 [info] Access MyappWeb.Endpoint at http://localhost:4000
^CGracefully stopping... (press Ctrl+C again to force)
Stopping myapp_web_1_f59b1c3a118c ...
Killing myapp_web_1_f59b1c3a118c ... done
The Endpoint is wrong and connection is refused.
Here is my prod.exs
use Mix.Config
config :myapp, MyappWeb.Endpoint,
http: [:inet6, port: System.get_env("PORT") || 4000],
url: [host: "localhost", port: System.get_env("PORT")],
cache_static_manifest: "priv/static/cache_manifest.json",
secret_key_base: System.get_env("SECRET_KEY_BASE"),
server: true,
root: "."
# Do not print debug messages in production
config :logger, level: :info
# Configure your database
config :myapp, Myapp.Repo,
adapter: Ecto.Adapters.Postgres,
# hostname: System.get_env("DATABASE_HOST"),
# username: System.get_env("DATABASE_USER"),
# password: System.get_env("DATABASE_PASS"),
# database: System.get_env("DATABASE_NAME"),
url: System.get_env("DATABASE_URL"),
pool_size: 10
# import_config "prod.secret.exs"
My docker-compose.yml
version: '3.5'
services:
web:
image: "myapp:latest"
ports:
- "80:4000" # In our .env file above, we chose port 4000
env_file:
- config/docker.env
My config/config.exs
use Mix.Config
config :myapp,
ecto_repos: [Myapp.Repo]
# Configures the endpoint
config :myapp, MyappWeb.Endpoint,
url: [host: "localhost"],
secret_key_base: "RXyklAFqTajbz7dePdeEHa/sLLbMORcUeY/GshZsKnXJIZ7eSTnKQq22DRoCkTO/",
render_errors: [view: AppexoWeb.ErrorView, accepts: ~w(json)],
pubsub: [name: Appexo.PubSub, adapter: Phoenix.PubSub.PG2]
.........
import_config "#{Mix.env()}.exs"
My Dockerfile:
# The version of Alpine to use for the final image
# This should match the version of Alpine that the `elixir:1.7.2-alpine` image uses
ARG ALPINE_VERSION=3.9
FROM elixir:1.8.2-alpine AS builder
# The following are build arguments used to change variable parts of the image.
# The name of your application/release (required)
ARG APP_NAME=myapp
# Database Url
ARG DATABASE_URL=ecto://postgres:xxxxxxxxxx@localhost/my_db
# The version of the application we are building (required)
ARG APP_VSN=0.1.0
# The environment to build with
ARG MIX_ENV=prod
# Set this to true if this release is not a Phoenix app
ARG SKIP_PHOENIX=false
# If you are using an umbrella project, you can change this
# argument to the directory the Phoenix app is in so that the assets
# can be built
ARG PHOENIX_SUBDIR=.
ENV SKIP_PHOENIX=${SKIP_PHOENIX} \
APP_NAME=${APP_NAME} \
APP_VSN=${APP_VSN} \
MIX_ENV=${MIX_ENV} \
DATABASE_URL=${DATABASE_URL}
# By convention, /opt is typically used for applications
WORKDIR /opt/app
# This step installs all the build tools we'll need
RUN apk update && \
apk upgrade --no-cache && \
apk add --no-cache \
nodejs \
yarn \
git \
build-base && \
mix local.rebar --force && \
mix local.hex --force
# This copies our app source code into the build container
COPY . .
RUN mix do deps.get, deps.compile, compile
# This step builds assets for the Phoenix app (if there is one)
# If you aren't building a Phoenix app, pass `--build-arg SKIP_PHOENIX=true`
# This is mostly here for demonstration purposes
RUN if [ ! "$SKIP_PHOENIX" = "true" ]; then \
cd ${PHOENIX_SUBDIR}/assets && \
yarn install && \
yarn deploy && \
cd - && \
mix phx.digest; \
fi
RUN \
mkdir -p /opt/built && \
mix distillery.release --verbose && \
cp _build/${MIX_ENV}/rel/${APP_NAME}/releases/${APP_VSN}/${APP_NAME}.tar.gz /opt/built && \
cd /opt/built && \
tar -xzf ${APP_NAME}.tar.gz && \
rm ${APP_NAME}.tar.gz
# From this line onwards, we're in a new image, which will be the image used in production
FROM alpine:${ALPINE_VERSION}
# The name of your application/release (required)
ARG APP_NAME=myapp
# Database Url
ARG DATABASE_URL=ecto://postgres:xxxxxxx@localhost/mydb
RUN apk update && \
apk add --no-cache \
bash \
openssl-dev
ENV REPLACE_OS_VARS=true \
APP_NAME=${APP_NAME} \
DATABASE_URL=${DATABASE_URL}
WORKDIR /opt/app
COPY --from=builder /opt/built .
CMD trap 'exit' INT; DATABASE_URL=${DATABASE_URL} /opt/app/bin/${APP_NAME} foreground
My repo.ex
defmodule Myapp.Repo do
use Ecto.Repo,
otp_app: :myapp,
adapter: Ecto.Adapters.Postgres
def init(_type, config) do
database_url = System.get_env("DATABASE_URL")
IO.inspect(database_url)
if database_url == nil do
{:ok, config}
else
{:ok, Keyword.put(config, :url, database_url)}
end
end
end
rel/config.exs
...
environment :prod do
set include_erts: true
set include_src: false
set cookie: :"..................."
# set vm_args: "rel/vm.args"
end
release :myapp do
set version: current_version(:appexo)
set applications: [
:runtime_tools
]
set config_providers: [
{Distillery.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/etc/config.exs"]}
]
set overlays: [
{:copy, "rel/config/config.exs", "etc/config.exs"}
]
end
And my rel/config/config.exs
use Mix.Config
config :myapp, Myapp.Repo,
# username: System.get_env("DATABASE_USER"),
# password: System.get_env("DATABASE_PASS"),
# database: System.get_env("DATABASE_NAME"),
# hostname: System.get_env("DATABASE_HOST"),
url: System.get_env("DATABASE_URL"),
pool_size: 10
port = String.to_integer(System.get_env("PORT") || "8080")
config :appexo, Appexo.Endpoint,
http: [port: port],
url: [host: "localhost", port: port],
root: ".",
secret_key_base: System.get_env("SECRET_KEY_BASE")
Also docker.env
HOSTNAME=localhost
SECRET_KEY_BASE="u1QXlca4XEZKb1o3HL/aUlznI1qstCNAQ6yme/lFbFIs0Iqiq/annZ+Ty8JyUCDc"
DATABASE_HOST=db
DATABASE_USER=postgres
DATABASE_PASS=xxxxxxx
DATABASE_NAME=my_db
DATABASE_URL=ecto://postgres:xxxxxxx@localhost/my_db
PORT=4000
LANG=en_US.UTF-8
REPLACE_OS_VARS=true
I have tried a lot of things… What am I doing wrong??