gmc

gmc

Run migrations on Docker Production

I managed to deploy my Phoenix App on an external virtual server using Docker. The only thing missing is the call of “migrate” to run the migrations before the server starts.

I started using the official Phoenix Dockerfile and added a docker-compose.yml with an additional Postgres container. The server starts without migrations because of the “CMD [”/app/bin/server"]" statement and the end of the Dockerfile.

I tried to add “RUN /app/bin/migrate” just before, but then I get an error that the environment variable DATABASE_URL is missing. But actually it’s set in the docker-compose.yml file for the Phoenix container. It’s obviously set correctly as the server starts with no issues.

What is the correct way to run the migrations?

Btw. I would also like to run seeds.ex, but I guess I have to add this in the release.ex module.

Marked As Solved

stefanchrobot

stefanchrobot

I’m using Elixir releases with a Dockerfile similar to the one in the Phoenix guides. Here’s the last line:

CMD ["sh", "-c", "bin/app eval MyApp.Release.migrate && bin/app start"]

If the migrations fail, the app is not started and the whole deployment fails (which is what I want).

13
Post #9

Also Liked

RodolfoSilva

RodolfoSilva

In addition, I would recommend to put the exec command before start the app.

CMD ["sh", "-c", "bin/app eval MyApp.Release.migrate && exec bin/app start"]

Without this You’ll not be able to use Ctrl+C to kill the process when you start the app with docker run.

In my case I’ve create a new shell file in my release folder called migrate_and_server with this:

#!/bin/sh
cd -P -- "$(dirname -- "$0")"
./app eval MyApp.Release.migrate && PHX_SERVER=true exec ./app start

Or you can just use this way:

#!/bin/sh
cd -P -- "$(dirname -- "$0")"
./app eval MyApp.Release.migrate && exec ./server
sergio

sergio

Would be Googler’s heres for Phoenix 1.7.0 and above.

I ran mix phx.gen.release --docker and it generated the Dockerfile for me.

It also generated a migrate and server file.

in rel/overlays/bin/server...

#!/bin/sh
cd -P -- "$(dirname -- "$0")"
PHX_SERVER=true exec ./my_app start

in rel/overlays/bin/migrate...

#!/bin/sh
cd -P -- "$(dirname -- "$0")"
exec ./my_app eval MyApp.Release.migrate

At the end of the generated Dockerfile all I needed to do was:

# BAD: 
CMD ["/app/bin/server"]

# GOOD:
CMD ["sh", "-c", "/app/bin/migrate && /app/bin/server"]

Now if my migrations don’t run the server doesn’t start which is what I want. Hope this helps.

woylie

woylie

Note that if you do it like this, sh will receive the SIGTERM signal when the docker container is shut down, but it will not pass it to the application, which means after a grace period, a SIGKILL signal is issued and all children will be terminated abruptly. Your application will not be able to shut down gracefully.

It’s better to define a separate entrypoint.sh that runs both commands, or add another overlay as mentioned that runs the migrations before it starts the server.

Where Next?

Popular in Questions Top

myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement