[英]How to rollback database in docker container using elixir phoenix releases and the example MyApp.Release.rollback in the guides
[英]How do I run Elixir Phoenix Docker in production mode using example from Phoenix Guides?
Elixir Phoenix Guides 上給出的示例 Dockerfile 似乎已經過時和損壞。 該示例可在此處找到: https://hexdocs.pm/phoenix/releases.html#containers
我創建了一個像這樣的香草應用程序: mix phx.new hello_world
壞掉的Dockerfile:
# FROM elixir:1.9.0-alpine as build
# install build dependencies
RUN apk add --update git build-base nodejs yarn python
# prepare build dir
RUN mkdir /app
WORKDIR /app
# install hex + rebar
RUN mix local.hex --force && \
mix local.rebar --force
# set build ENV
ENV MIX_ENV=prod
# install mix dependencies
COPY mix.exs mix.lock ./
COPY config config
RUN mix deps.get
RUN mix deps.compile
# build assets
COPY assets assets
RUN cd assets && npm install && npm run deploy
RUN mix phx.digest
# build project
COPY priv priv
COPY lib lib
RUN mix compile
# build release
COPY rel rel
RUN mix release
# prepare release image
FROM alpine:3.9 AS app
RUN apk add --update bash openssl
RUN mkdir /app
WORKDIR /app
COPY --from=build /app/_build/prod/rel/my_app ./
RUN chown -R nobody: /app
USER nobody
ENV HOME=/app
我正在嘗試從 vanilla Phoenix 應用程序安裝中運行 Dockerfile 並且遇到了許多問題,包括:
# FROM elixir:1.9.0-alpine as build
# Needs to be uncommented
RUN cd assets && npm install && npm run deploy
# npm install failed, had to add nodejs-npm
COPY rel rel
# errors here, there is no rel, should I remove?
More errors later because DATABASE_URL and SECRET_KEY_BASE are not declared
我不是專家,到目前為止 Dockerfile 現在看起來像這樣:
FROM elixir:1.9.1-alpine as build
# install build dependencies
# modified: is this correct?
RUN apk add --update git build-base nodejs nodejs-npm yarn python
# prepare build dir
RUN mkdir /app
WORKDIR /app
# install hex + rebar
RUN mix local.hex --force && \
mix local.rebar --force
# set build ENV
# modified: is this correct?
ENV DATABASE_URL=${DATABASE_URL} \
SECRET_KEY_BASE=${SECRET_KEY_BASE} \
MIX_ENV=prod
# install mix dependencies
COPY mix.exs mix.lock ./
COPY config config
RUN mix deps.get
RUN mix deps.compile
# build assets
COPY assets assets
RUN cd assets && npm install && npm run deploy
# build project
COPY priv priv
COPY lib lib
RUN mix compile
# build release
# removed next line, is that correct?
# COPY rel rel
RUN mix release
# prepare release image
FROM alpine:3.9 AS app
RUN apk add --update bash openssl
RUN mkdir /app
WORKDIR /app
COPY --from=build /app/_build/prod/rel/hello_world ./
RUN chown -R nobody: /app
USER nobody
ENV HOME=/app
ENTRYPOINT ["./bin/hello_world", "start"]
我嘗試使用以下命令運行容器:
docker run -it -e DATABASE_URL='ecto://postgres:123456@localhost/hello_world_dev' -e SECRET_KEY_BASE='blargblargblarg' hello_world:latest
但我得到這個錯誤:
05:20:34.841 [error] GenServer #PID<0.1380.0> terminating
** (RuntimeError) connect raised KeyError exception: key :database not found. The exception details are hidden, as they may contain sensitive data such as database credentials. You may set :show_sensitive_data_on_connection_error to true when starting your connection if you wish to see all of the details
(elixir) lib/keyword.ex:393: Keyword.fetch!/2
(postgrex) lib/postgrex/protocol.ex:92: Postgrex.Protocol.connect/1
(db_connection) lib/db_connection/connection.ex:69: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: nil
..... repeat a lot
05:48:41.296 [info] Application hello_world exited: shutdown
這對我來說都是很新鮮的。 我已經輕松部署到 Heroku 但希望使用 Docker 部署到 AWS、GCP 等的快樂路徑...
更新 1:這是config/prod.secret.exs
文件。 我沒有修改它。 請注意它正在加載環境變量:
# In this file, we load production configuration and secrets
# from environment variables. You can also hardcode secrets,
# although such is generally not recommended and you have to
# remember to add this file to your .gitignore.
use Mix.Config
database_url =
System.get_env("DATABASE_URL") ||
raise """
environment variable DATABASE_URL is missing.
For example: ecto://USER:PASS@HOST/DATABASE
"""
config :hello_world, HelloWorld.Repo,
# ssl: true,
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
secret_key_base =
System.get_env("SECRET_KEY_BASE") ||
raise """
environment variable SECRET_KEY_BASE is missing.
You can generate one by calling: mix phx.gen.secret
"""
config :hello_world, HelloWorldWeb.Endpoint,
http: [:inet6, port: String.to_integer(System.get_env("PORT") || "4000")],
secret_key_base: secret_key_base
# ## Using releases (Elixir v1.9+)
#
# If you are doing OTP releases, you need to instruct Phoenix
# to start each relevant endpoint:
#
# config :hello_world, HelloWorldWeb.Endpoint, server: true
#
# Then you can assemble a release by calling `mix release`.
# See `mix help release` for more information.
更新 2:
我從config/prod.exs
中刪除import_config "config/prod.secret.exs"
我將config/prod.secret.exs
重命名為config/releases.exs
並在我更改的文件中use Mix.Config
import Config
和未注釋的config:hello_world, HelloWorldWeb.Endpoint, server: true
現在,當我嘗試使用端口映射和 --network="host" 運行容器時
docker run -it -e DATABASE_URL='ecto://postgres:123456@localhost/hello_world_dev' -e SECRET_KEY_BASE='blargblargblarg' -p 5432:5432 --network="host" hello_world:latest
我明白了
23:21:48.635 [error] Postgrex.Protocol (#PID<0.2615.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
23:21:48.635 [error] Postgrex.Protocol (#PID<0.2619.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
23:21:48.639 [info] Running HelloWorldWeb.Endpoint with cowboy 2.6.3 at :::4000 (http)
23:21:48.640 [info] Access HelloWorldWeb.Endpoint at http://example.com
23:21:49.938 [error] Postgrex.Protocol (#PID<0.2623.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
更新 3:我嘗試更改DATABASE_URL
但沒有成功。
# adding port
DATABASE_URL='ecto://postgres:123456@localhost:5432/hello_world_dev'
# changing hostname to 127.0.0.1
DATABASE_URL='ecto://postgres:123456@127.0.0.1/hello_world_dev'
# changing hostname to 127.0.0.1 and adding port
DATABASE_URL='ecto://postgres:123456@127.0.0.1:5432/hello_world_dev'
# changing hostname to 0.0.0.0
DATABASE_URL='ecto://postgres:123456@0.0.0.0/hello_world_dev'
# changing hostname to 0.0.0.0 and adding port
DATABASE_URL='ecto://postgres:123456@0.0.0.0:5432/hello_world_dev'
# changing ecto to postgresql
DATABASE_URL='postgresql://postgres:123456@localhost/hello_world_dev'
# changing ecto to postgresql and localhost to 127.0.0.1
DATABASE_URL='postgresql://postgres:123456@127.0.0.1/hello_world_dev'
# changing ecto to postgresql and localhost to 127.0.0.1 with port
DATABASE_URL='postgresql://postgres:123456@127.0.0.1:5432/hello_world_dev'
# changing ecto to postgresql and localhost to 0.0.0.0
DATABASE_URL='postgresql://postgres:123456@0.0.0.0/hello_world_dev'
# changing ecto to postgresql and localhost to 0.0.0.0 with port
DATABASE_URL='postgresql://postgres:123456@0.0.0.0:5432/hello_world_dev'
¯\_(ツ)_/¯
從 ENV 變量定義數據庫 url
config :hello_world, HelloWorld.Repo,
url: "${DATABASE_URL}"
然后將數據庫pool_size
與 pool_size 一起使用,並將其傳遞給容器
DATABASE_URL=ecto://postgres@db/hello_world?pool_size=10
將ENV REPLACE_OS_VARS=true
添加到您的Dockerfile
(可能僅適用於 Distillery,否則用正確的形式替換"${DATABASE_URL}"
以在運行時獲取 ENV 變量,而不是在編譯階段)。
以下是如何使用 Distillery 創建簡單構建的示例:
FROM elixir:1.9.0-alpine
RUN mix local.hex --force && \
mix local.rebar --force && \
mix archive.install --force hex phx_new 1.4.8
RUN apk add --update nodejs nodejs-npm
ENV MIX_ENV=prod
WORKDIR /srv/app
COPY ./platform/ /srv/app/
# install dependencies (production only)
RUN mix local.rebar --force
RUN mix deps.get --only prod
RUN mix compile
# RUN npm install --global webpack
RUN cd assets && npm install && ./node_modules/webpack/bin/webpack.js --mode production
RUN mix phx.digest
RUN mix distillery.release
# alpine version should be the same as build
FROM alpine:3.9
RUN apk add --update bash
ENV REPLACE_OS_VARS=true
WORKDIR /srv/app
COPY --from=0 /srv/app/_build/prod/ .
CMD rel/platform/bin/platform migrate && rel/platform/bin/platform foreground
另外,請記住,由於您在本地運行postgres
(與容器不在同一網絡上),您需要將其納入帳戶並使用docker.for.mac.localhost
作為postgres
的主機名或--net=host
docker run
和localhost
作為postgres
的主機。
看起來問題出現是因為您沒有正確設置配置。
異常:鍵:找不到數據庫
為了使用您使用環境變量注入的數據庫,您需要顯式獲取它。 根據您組織配置的方式,您應該為您的 Repo 配置一個配置。 默認情況下,repo 的配置是:
config :yourserver_api, YourServer.Repo,
username: "postgres",
password: "postgres",
database: "yourserver_api_prod",
hostname: "localhost",
pool_size: 10
如果您確定將注入例如數據庫,那么您需要將其更改為:
database: System.get_env("DATABASE_URL")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.