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
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).
Also Liked
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
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
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.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









