I built a service orchestration with docker-compose that connects an Elixir app that uses BroadayRabbitMQ to another container that uses RabbitMQ-3-Management Docker image. The problem is, even though these services are on the same network (as in I built a docker network to support them) & set the env variables. I receive "[error] Cannot connect to a RabbitMQ broker: :unknown_host" How do I get RabbitMQ to connect to my Elixir release container?
docker-compose.yml
version: "3.8"
services:
poll_workers_app:
container_name: coder_workers_ex
build:
context: .
dockerfile: CoderWorkersProd.Dockerfile
volumes:
- .:/app
depends_on:
- db
- rabbitmq
env_file:
- config/docker.env
ports:
- '4000:4000'
tty: true
networks:
- rabbitmq_network
db:
image: 'postgres:12'
container_name: coder_workers_db
environment:
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_HOST_AUTH_METHOD: trust
restart: always
volumes:
- 'pgdata:/var/lib/postgresql/data'
ports:
- "5432:5432"
networks:
- rabbitmq_network
rabbitmq:
hostname: rabbitmq
image: rabbitmq:3-management
container_name: coder_workers_rabbitmq
env_file:
- config/docker.env
ports:
- '5672:5672'
- '15672:15672'
- '15692:15692'
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- rabbitmq_network
volumes:
pgdata:
rabbitmq-data: {}
networks:
rabbitmq_network:
external:
name: rabbitmq_network
rabbit_report_pipeline.ex
defmodule CoderWorkers.Pipelines.RabbitReportPipeline do
use Broadway
require Logger
alias CoderWorkers.Responses.RabbitResponse
alias CoderWorkers.Cache.Responses
@producer BroadwayRabbitMQ.Producer
@queue "coder.worker.rabbit_report.status"
@connection [
username: System.get_env("RABBITMQ_USERNAME"),
password: System.get_env("RABBITMQ_PASSWORD"),
host: System.get_env("RABBITMQ_HOST")
]
.env
RABBITMQ_DEFAULT_USER=guest
RABBITMQ_DEFAULT_PASS=guest
RABBITMQ_DEFAULT_VHOST=rabbitmq
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_HOST=rabbitmq
error
coder_workers_ex | 20:03:25.676 [error] Cannot connect to RabbitMQ broker: :unknown_host
coder_workers_ex | 20:03:41.300 [error] Cannot connect to RabbitMQ broker: :unknown_host
coder_workers_ex | 20:04:10.856 [error] Cannot connect to RabbitMQ broker: :unknown_host
coder_workers_ex | 20:04:39.142 [error] Cannot connect to RabbitMQ broker: :unknown_host
CodePudding user response:
I can not see how you connect from the coder_workers_ex
to the rabbit_mq
. So just in case:
You can connect inside the network by using the container name as the host, not the host name. That is only used inside the container, as you can read also here.
For instance: attaching a terminal session to coder_workers_ex
container and executing: ping rabbitmq
will not work, but ping coder_workers_rabbitmq
will.
If this does not help, then maybe show the code that connects the containers so we can try to help you better.
EDIT: as pointed out in the comments by David Maze: Connecting can be done using either: comtainer_name, hostname, or service-block-name. So while this answer gives you a correct working solution, it is not the correct answer, because this was not your problem in the first place.
CodePudding user response:
Looks like your docker setup is correct, it won't work because you have to use runtime configuration (read about config/runtime.exs
).
When you are using a attribute, in your case @connection
, it will always get evaluated at compile-time.
To avoid this, there is a rule of thumb:
If your configuration is not a compile-time configuration, always use a function to fetch the configuration.
Example:
def connection() do
[
username: System.get_env("RABBITMQ_USERNAME"),
password: System.get_env("RABBITMQ_PASSWORD"),
host: System.get_env("RABBITMQ_HOST")
]
end
This should work as-is, however it is recommended to store all your configuration inside of config files. So all you have to do is create your runtime.exs
file:
import Config
if config_env() == :prod do
config :my_app, :rabbitmq_config,
username: System.get_env("RABBITMQ_USERNAME"),
password: System.get_env("RABBITMQ_PASSWORD"),
host: System.get_env("RABBITMQ_HOST")
end
Then, you can get the configuration using Application.get_env/3 or Application.fetch_env/2, remember to fetch configurations using functions.
To make this easier, I would recommend using credo, it enforces you to use Applicaiton.compile_env/3
in situations where you are trying to call runtime configurations at compile-time.