0

我正在尝试按照本教程来让我的(在 localhost 上运行)elixir/phoenix 应用程序在 docker 容器中运行,但我遇到了困难。

https://pspdfkit.com/blog/2018/how-to-run-your-phoenix-application-with-docker/

这是我的错误:

[info] JOIN "room:lobby" to AlbatrossWeb.RoomChannel
phoenix_1  |   Transport:  Phoenix.Transports.WebSocket (2.0.0)
phoenix_1  |   Serializer:  Phoenix.Transports.V2.WebSocketSerializer
phoenix_1  |   Parameters: %{}
phoenix_1  | inside room:lobby channel handler
phoenix_1  | [info] Replied room:lobby :ok
phoenix_1  | [error] Ranch protocol #PID<0.403.0> of listener AlbatrossWeb.Endpoint.HTTP (cowboy_protocol) terminated
phoenix_1  | ** (exit) exited in: Phoenix.Endpoint.CowboyWebSocket.resume()
phoenix_1  |     ** (EXIT) an exception was raised:
phoenix_1  |         ** (Protocol.UndefinedError) got FunctionClauseError with message "no function clause matching in Poison.Encoder.__protocol__/1" while retrieving Exception.message/1 for %Protocol.UndefinedError{description: "", protocol: Poison.Encoder, value: ["127", "127", "room:lobby", "phx_reply", %{response: %{}, status: :ok}]}
phoenix_1  |             (poison) lib/poison/encoder.ex:66: Poison.Encoder.impl_for!/1
phoenix_1  |             (poison) lib/poison/encoder.ex:69: Poison.Encoder.encode/2
phoenix_1  |             (poison) lib/poison.ex:41: Poison.encode!/2
phoenix_1  |             (phoenix) lib/phoenix/transports/v2/websocket_serializer.ex:22: Phoenix.Transports.V2.WebSocketSerializer.encode!/1
phoenix_1  |             (phoenix) lib/phoenix/transports/websocket.ex:197: Phoenix.Transports.WebSocket.encode_reply/2
phoenix_1  |             (phoenix) lib/phoenix/endpoint/cowboy_websocket.ex:77: Phoenix.Endpoint.CowboyWebSocket.websocket_handle/3
phoenix_1  |             (cowboy) /app/deps/cowboy/src/cowboy_websocket.erl:588: :cowboy_websocket.handler_call/7
phoenix_1  |             (phoenix) lib/phoenix/endpoint/cowboy_websocket.ex:49: Phoenix.Endpoint.CowboyWebSocket.resume/3
phoenix_1  |             (cowboy) /app/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
phoenix_1  | [info] JOIN "room:lobby" to AlbatrossWeb.RoomChannel
<....repeat forever....>

我不确定发生了什么。

我的房间大厅只是一个套接字通道,将 room_channel.ex 定义为:

###room_channel.ex###
defmodule AlbatrossWeb.RoomChannel do
  use Phoenix.Channel

  def join("room:lobby", _message, socket) do
    IO.puts "inside room:lobby channel handler"
    {:ok, socket}
  end

  def join("room:" <> _private_room_id, _params, _socket) do
    {:error, %{reason: "unauthorized"}}
  end

  def handle_in("updated_comments", %{"payload"=>payload}, socket) do
    IO.puts("inside updated_comments handle_in")
    broadcast! socket, "updated_comments", payload
    # ArticleController.retrieve(socket)
    {:noreply, socket}
  end
end
###room_channel.ex###

当我在没有 docker 文件的情况下运行它时,它运行良好 - 我添加的内容如下:


###run.sh###
docker-compose up --build
###run.sh###

###Dockerfile###
FROM elixir:latest

RUN apt-get update && \
  apt-get install -y postgresql-client

# Create app directory and copy the Elixir projects into it
RUN mkdir /app
COPY . /app
WORKDIR /app

# Install hex package manager
RUN mix local.hex --force

# Compile the project
RUN mix do compile

CMD ["/app/entrypoint.sh"]
###Dockerfile###

###docker-compose###
# Version of docker-compose
version: '3'

# Containers we are going to run
services:
  # Our Phoenix container
  phoenix:
    # The build parameters for this container.
    build:
      # Here we define that it should build from the current directory
      context: .
    environment:
      # Variables to connect to our Postgres server
      PGUSER: postgres
      PGPASSWORD: postgres
      PGDATABASE: db
      PGPORT: 5432
      # Hostname of our Postgres container
      PGHOST: db
    ports:
      # Mapping the port to make the Phoenix app accessible outside of the container
      - "4000:4000"
    depends_on:
      # The db container needs to be started before we start this container
      - db
  db:
    # We use the predefined Postgres image
    image: postgres:9.6
    environment:
      # Set user/password for Postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      # Set a path where Postgres should store the data
      PGDATA: /var/lib/postgresql/data/pgdata
    restart: always
    volumes:
      - pgdata:/var/lib/postgresql/data
# Define the volumes
volumes:
  pgdata:
###docker-compose###

###entrypoint.sh###
#!/bin/bash

while ! pg_isready -q -h $PGHOST -p $PGPORT -U $PGUSER
do
  echo "$(date) - waiting for database to start"
  sleep 2
done

# Create, migrate, and seed database if it doesn't exist.
if [[ -z `psql -Atqc "\\list $PGDATABASE"` ]]; then
  echo "Database $PGDATABASE does not exist. Creating..."
  createdb -E UTF8 $PGDATABASE -l en_US.UTF-8 -T template0
  echo "1"
  mix do ecto.drop, ecto.create
  echo "2"
  mix phx.gen.schema Binarys binary postnum:integer leftchild:integer rightchild:integer downvotes:integer message:string parent:string upvotes:integer
  echo "3"
  mix phx.gen.schema Comments comment postnum:integer children:map downvotes:integer message:string parent:string upvotes:integer identifier:uuid
  echo "4"
  mix ecto.migrate
  echo "5"
  mix run priv/repo/seeds.exs
  echo "Database $PGDATABASE created."
fi

exec mix phx.server
###entrypoint.sh###

我还更改了 dev.exs 文件中的配置,如下所示:

###dev.exs###
config :albatross, Albatross.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "postgres",
  hostname: "db",
  database: "db",
  # port: 5432,
  pool_size: 10
###dev.exs###

有趣的是,所有这些错误似乎都是在我的前端启动时产生的,但没有发出请求(除了连接到套接字)。如果我尝试发出 http 请求,我会得到:

phoenix_1  | [info] POST /addComment
phoenix_1  | inside addComment
phoenix_1  | [debug] Processing with AlbatrossWeb.PageController.addComment/2
phoenix_1  |   Parameters: %{"payload" => %{"message" => "sf", "parent" => "no_parent", "postnum" => 6, "requestType" => "post", "urlKEY" => "addComment"}}
phoenix_1  |   Pipelines: [:browser]
phoenix_1  | [error] Failure while translating Erlang's logger event
phoenix_1  | ** (Protocol.UndefinedError) got FunctionClauseError with message "no function clause matching in Plug.Exception.__protocol__/1" while retrieving Exception.message/1 for %Protocol.UndefinedError{description: "", protocol: Plug.Exception, value: %Protocol.UndefinedError{description: "", protocol: Plug.Exception, value: %Protocol.UndefinedError{description: "", protocol: Plug.Exception, value: %Protocol.UndefinedError{description: "", protocol: String.Chars, value: %Postgrex.Query{columns: nil, name: "", param_formats: nil, param_oids: nil, param_types: nil, ref: nil, result_formats: nil, result_oids: nil, result_types: nil, statement: ["INSERT INTO ", [34, "comment", 34], [], [32, 40, [[[[[[[[[[], [34, "children", 34], 44], [34, "downvotes", 34], 44], [34, "identifier", 34], 44], [34, "message", 34], 44], [34, "parent", 34], 44], [34, "postnum", 34], 44], [34, "upvotes", 34], 44], [34, "inserted_at", 34], 44], 34, "updated_at", 34], ") VALUES ", [], 40, [[[[[[[[[[], [36 | "1"], 44], [36 | "2"], 44], [36 | "3"], 44], [36 | "4"], 44], [36 | "5"], 44], [36 | "6"], 44], [36 | "7"], 44], [36 | "8"], 44], 36 | "9"], 41], [], " RETURNING ", [], 34, "id", 34], types: nil}}}}}
phoenix_1  |     (plug) lib/plug/exceptions.ex:4: Plug.Exception.impl_for!/1
phoenix_1  |     (plug) lib/plug/exceptions.ex:19: Plug.Exception.status/1
phoenix_1  |     (plug) lib/plug/adapters/translator.ex:79: Plug.Adapters.Translator.non_500_exception?/1
phoenix_1  |     (plug) lib/plug/adapters/translator.ex:49: Plug.Adapters.Translator.translate_ranch/5
phoenix_1  |     (logger) lib/logger/erlang_handler.ex:104: Logger.ErlangHandler.translate/6
phoenix_1  |     (logger) lib/logger/erlang_handler.ex:97: Logger.ErlangHandler.translate/5
phoenix_1  |     (logger) lib/logger/erlang_handler.ex:30: anonymous fn/3 in Logger.ErlangHandler.log/2
phoenix_1  |     (logger) lib/logger.ex:861: Logger.normalize_message/2
phoenix_1  |     (logger) lib/logger.ex:684: Logger.__do_log__/3
phoenix_1  |     (kernel) logger_backend.erl:51: :logger_backend.call_handlers/3
phoenix_1  |     (kernel) logger_backend.erl:38: :logger_backend.log_allowed/2
phoenix_1  |     (ranch) /app/deps/ranch/src/ranch_conns_sup.erl:167: :ranch_conns_sup.loop/4
phoenix_1  |     (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
phoenix_1  | 

所以你可以看到它看到了请求,并且似乎在操纵它。就是不能退货。我的 Docker 和 docker-compose 文件中都暴露了我的端口,我真的看不出还有什么问题,因为当我在 docker 容器之外运行这个应用程序时,它可以工作。

出了什么问题?

4

2 回答 2

1

我认为问题出在你的 Dockerfile 上。

您没有公开任何端口。

为了能够发布端口,您需要首先公开帖子。

尝试添加EXPOSE 4000您的 Dockerfile。

于 2018-10-15T08:59:00.457 回答
0

没有足够的声誉来回复其他答案,但我想告诉潜在的读者 EXPOSE 指令只不过是文档。在发布之前不必公开端口。

来自官方 docker 文档

EXPOSE 指令实际上并不发布端口。它充当构建映像的人和运行容器的人之间的一种文档类型,关于打算发布哪些端口。要在运行容器时实际发布端口,请使用 docker run 上的 -p 标志来发布和映射一个或多个端口,或者使用 -P 标志来发布所有暴露的端口并将它们映射到高阶端口。

于 2020-07-24T09:11:31.470 回答