forked from phoenixframework/phoenix
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add phx.gen.release task for release/docker based deployments (phoeni…
…xframework#4609) * Add phx.gen.release task for release and docker based deployments
- Loading branch information
1 parent
940664c
commit 380a281
Showing
14 changed files
with
479 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
defmodule Mix.Tasks.Phx.Gen.Release do | ||
@shortdoc "Generates release files and optional Dockerfile for release-based deployments" | ||
|
||
@moduledoc """ | ||
Generates release files and optional Dockerfile for release-based deployments. | ||
The following release files are created: | ||
* `lib/app_name/release.exs` - A release module containing tasks for running | ||
migrations inside a release | ||
* `rel/overlays/bin/migrate` - A migrate script for conveniently invoking | ||
the release system migrations | ||
* `rel/overlays/bin/server` - A server script for conveniently invoking | ||
the release system with environment variables to start the phoenix web server | ||
Note, the `rel/overlays` directory is copied into the release build by default when | ||
running `mix release`. | ||
When the `--docker` flag is passed, the following docker files are generated: | ||
* `Dockerfile` - The Dockerfile for use in any standard docker deployment | ||
* `.dockerignore` - A docker ignore file with standard elixir defaults | ||
For extended release configuration, the `mix release.init`task can be used | ||
in addition to this task. See the `Mix.Release` docs for more details. | ||
""" | ||
|
||
use Mix.Task | ||
|
||
@doc false | ||
def run(args) do | ||
docker? = "--docker" in args | ||
ecto? = "--ecto" in args || Code.ensure_loaded?(Ecto) | ||
|
||
if Mix.Project.umbrella?() do | ||
Mix.raise(""" | ||
mix phx.gen.release is not supported in umbrella applications. | ||
Run this task in your web application instead. | ||
""") | ||
end | ||
|
||
app = Mix.Phoenix.otp_app() | ||
app_namespace = Mix.Phoenix.base() | ||
|
||
binding = [ | ||
app_namespace: app_namespace, | ||
otp_app: app, | ||
elixir_vsn: System.version(), | ||
otp_vsn: otp_vsn() | ||
] | ||
|
||
Mix.Phoenix.copy_from(paths(), "priv/templates/phx.gen.release", binding, [ | ||
{:eex, "rel/server.sh.eex", "rel/overlays/bin/server"}, | ||
{:eex, "rel/server.bat.eex", "rel/overlays/bin/server.bat"} | ||
]) | ||
|
||
if ecto? do | ||
Mix.Phoenix.copy_from(paths(), "priv/templates/phx.gen.release", binding, [ | ||
{:eex, "rel/migrate.sh.eex", "rel/overlays/bin/migrate"}, | ||
{:eex, "rel/migrate.bat.eex", "rel/overlays/bin/migrate.bat"}, | ||
{:eex, "release.ex", Mix.Phoenix.context_lib_path(app, "release.ex")} | ||
]) | ||
end | ||
|
||
if docker? do | ||
Mix.Phoenix.copy_from(paths(), "priv/templates/phx.gen.release", binding, [ | ||
{:eex, "Dockerfile.eex", "Dockerfile"}, | ||
{:eex, "dockerignore.eex", ".dockerignore"} | ||
]) | ||
end | ||
|
||
File.chmod!("rel/overlays/bin/server", 0o755) | ||
File.chmod!("rel/overlays/bin/server.bat", 0o755) | ||
if ecto? do | ||
File.chmod!("rel/overlays/bin/migrate", 0o755) | ||
File.chmod!("rel/overlays/bin/migrate.bat", 0o755) | ||
end | ||
|
||
Mix.shell().info(""" | ||
Your application is ready to be deployed in a release! | ||
# To start your system | ||
_build/dev/rel/#{app}/bin/#{app} start | ||
# To start your system with the Phoenix server running | ||
_build/dev/rel/#{app}/bin/server | ||
#{ecto? && ecto_instructions(app)} | ||
Once the release is running: | ||
# To connect to it remotely | ||
_build/dev/rel/#{app}/bin/#{app} remote | ||
# To stop it gracefully (you may also send SIGINT/SIGTERM) | ||
_build/dev/rel/#{app}/bin/#{app} stop | ||
To list all commands: | ||
_build/dev/rel/#{app}/bin/#{app} | ||
""") | ||
|
||
ecto? && | ||
post_install_instructions("config/runtime.exs", ~r/ECTO_IPV6/, """ | ||
[warn] Conditional IPV6 support missing from runtime configuration. | ||
Add the following to your config/runtime.exs: | ||
maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: [] | ||
config :#{app}, #{app_namespace}.Repo, | ||
..., | ||
socket_options: maybe_ipv6 | ||
""") | ||
|
||
post_install_instructions("config/runtime.exs", ~r/PHX_SERVER/, """ | ||
[warn] Conditional server startup is missing from runtime configuration. | ||
Add the following to your config/runtime.exs: | ||
server? = System.get_env("PHX_SERVER") != nil | ||
config :#{app}, #{app_namespace}.Endpoint, | ||
..., | ||
server: server? | ||
""") | ||
|
||
post_install_instructions("config/runtime.exs", ~r/PHX_HOST/, """ | ||
[warn] Environment based URL export is missing from runtime configuration. | ||
Add the following to your config/runtime.exs: | ||
host = System.get_env("PHX_HOST") || "example.com" | ||
config :#{app}, #{app_namespace}.Endpoint, | ||
..., | ||
url: [host: host, port: 443] | ||
""") | ||
end | ||
|
||
defp ecto_instructions(app) do | ||
""" | ||
# To run migrations | ||
_build/dev/rel/#{app}/bin/migrate | ||
""" | ||
end | ||
|
||
defp paths do | ||
[".", :phoenix] | ||
end | ||
|
||
defp post_install_instructions(path, matching, msg) do | ||
case File.read(path) do | ||
{:ok, content} -> | ||
unless content =~ matching, do: Mix.shell().info(msg) | ||
|
||
{:error, _} -> | ||
Mix.shell().info(msg) | ||
end | ||
end | ||
|
||
def otp_vsn do | ||
major = to_string(:erlang.system_info(:otp_release)) | ||
path = Path.join([:code.root_dir(), "releases", major, "OTP_VERSION"]) | ||
|
||
case File.read(path) do | ||
{:ok, content} -> | ||
String.trim(content) | ||
|
||
{:error, _} -> | ||
IO.warn("unable to read OTP minor version at #{path}. Falling back to #{major}.0") | ||
"#{major}.0" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian instead of | ||
# Alpine to avoid DNS resolution issues in production. | ||
# | ||
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu | ||
# https://hub.docker.com/_/ubuntu?tab=tags | ||
# | ||
# | ||
# This file is based on these images: | ||
# | ||
# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image | ||
# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20210902-slim - for the release image | ||
# - https://pkgs.org/ - resource for finding needed packages | ||
# - Ex: hexpm/elixir:<%= elixir_vsn %>-erlang-<%= otp_vsn %>-debian-bullseye-20210902-slim | ||
# | ||
ARG BUILDER_IMAGE="hexpm/elixir:<%= elixir_vsn %>-erlang-<%= otp_vsn %>-debian-bullseye-20210902-slim" | ||
ARG RUNNER_IMAGE="debian:bullseye-20210902-slim" | ||
|
||
FROM ${BUILDER_IMAGE} as builder | ||
|
||
# install build dependencies | ||
RUN apt-get update -y && apt-get install -y build-essential git \ | ||
&& apt-get clean && rm -f /var/lib/apt/lists/*_* | ||
|
||
# prepare build dir | ||
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 ./ | ||
RUN mix deps.get --only $MIX_ENV | ||
RUN mkdir config | ||
|
||
# copy compile-time config files before we compile dependencies | ||
# to ensure any relevant config change will trigger the dependencies | ||
# to be re-compiled. | ||
COPY config/config.exs config/${MIX_ENV}.exs config/ | ||
RUN mix deps.compile | ||
|
||
COPY priv priv | ||
|
||
# note: if your project uses a tool like https://purgecss.com/, | ||
# which customizes asset compilation based on what it finds in | ||
# your Elixir templates, you will need to move the asset compilation | ||
# step down so that `lib` is available. | ||
COPY assets assets | ||
|
||
# compile assets | ||
RUN mix assets.deploy | ||
|
||
# Compile the release | ||
COPY lib lib | ||
|
||
RUN mix compile | ||
|
||
# Changes to config/runtime.exs don't require recompiling the code | ||
COPY config/runtime.exs config/ | ||
|
||
COPY rel rel | ||
RUN mix release | ||
|
||
# start a new build stage so that the final image will only contain | ||
# the compiled release and other runtime necessities | ||
FROM ${RUNNER_IMAGE} | ||
|
||
RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales \ | ||
&& apt-get clean && rm -f /var/lib/apt/lists/*_* | ||
|
||
# Set the locale | ||
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen | ||
|
||
ENV LANG en_US.UTF-8 | ||
ENV LANGUAGE en_US:en | ||
ENV LC_ALL en_US.UTF-8 | ||
|
||
WORKDIR "/app" | ||
RUN chown nobody /app | ||
|
||
# Only copy the final release from the build stage | ||
COPY --from=builder --chown=nobody:root /app/_build/prod/rel/<%= otp_app %> ./ | ||
|
||
USER nobody | ||
|
||
CMD /app/bin/server |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
.dockerignore | ||
# there are valid reasons to keep the .git, namely so that you can get the | ||
# current commit hash | ||
#.git | ||
.log | ||
tmp | ||
|
||
# Mix artifacts | ||
_build | ||
deps | ||
*.ez | ||
releases | ||
|
||
# Generate on crash by the VM | ||
erl_crash.dump | ||
|
||
# Static artifacts | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
call "%~dp0\<%= otp_app %>" eval <%= app_namespace %>.Release.migrate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
cd -P -- "$(dirname -- "$0")" | ||
exec ./<%= otp_app %> eval <%= app_namespace %>.Release.migrate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
set PHX_SERVER=true | ||
call "%~dp0\<%= otp_app %>" start |
Oops, something went wrong.