Last active
September 5, 2025 05:27
-
Star
(210)
You must be signed in to star a gist -
Fork
(43)
You must be signed in to fork a gist
-
-
Save jswny/83e03537830b0d997924e8f1965d88bc to your computer and use it in GitHub Desktop.
Revisions
-
jswny revised this gist
Jul 12, 2018 . 1 changed file with 1 addition and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -68,7 +68,6 @@ end In order to be able to run migrations and seed the database from the release generated by Distillery, we will need to make a few modifications as generally outlined by the [Running Migrations](https://hexdocs.pm/distillery/running-migrations.html) guide. This section assumes that you have database seeding operations defined in the normal location under `priv/repo/`. If you don't have these, your database will just be migrated and no seeding will be done. Otherwise, you can strip down the `release_tasks.ex` file as shown below. 1. Create a file called `release_tasks.ex` which will contain the tasks that can be run from the release. You can place this file anywhere in your app's directory structure, but I will place it in `lib/myapp`. - **Note**: if you are seeding your database with certain files, these files must be placed in the `priv/` directory of your app to ensure that they are included with the generated release. Otherwise, seeding the database will not work because the files won't exist in the release. ```elixir defmodule MyApp.ReleaseTasks do @@ -693,5 +692,4 @@ init terminating in do_boot ({{badmatch,{error,{[_],[_]}}},[{Elixir.MyApp.Releas Crash dump is being written to: erl_crash.dump...done ``` The problem is with the `myapp()` function, since `Application.get_application/1` is known to sometimes not work and return `nil` when running in a release. To fix this, you should replace `Application.get_application(__MODULE__)` with your OTP app name which looks like `:myapp`. - **Note**: This solution **specifically addresses with `init terminating in do_boot` errors with something like `nil.app`** in them. Other `init terminating in do_boot` errors are probably unrelated. -
jswny revised this gist
Jul 12, 2018 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -693,4 +693,5 @@ init terminating in do_boot ({{badmatch,{error,{[_],[_]}}},[{Elixir.MyApp.Releas Crash dump is being written to: erl_crash.dump...done ``` The problem is with the `myapp()` function, since `Application.get_application/1` is known to sometimes not work and return `nil` when running in a release. To fix this, you should replace `Application.get_application(__MODULE__)` with your OTP app name which looks like `:myapp`. - **Note**: This solution **specifically addresses with `init terminating in do_boot` errors with something like `nil.app`** in them. Other `init terminating in do_boot` errors are probably unrelated. -
jswny revised this gist
Jul 12, 2018 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -692,4 +692,5 @@ init terminating in do_boot ({{badmatch,{error,{[_],[_]}}},[{Elixir.MyApp.Releas Crash dump is being written to: erl_crash.dump...done ``` The problem is with the `myapp()` function, since `Application.get_application/1` is known to sometimes not work and return `nil` when running in a release. To fix this, you should replace `Application.get_application(__MODULE__)` with your OTP app name which looks like `:myapp`. - **Note**: This solution **specifically addresses with `init terminating in do_boot` errors with something like `nil.app`** in them. Other `init terminating in do_boot` errors are probably unrelated. -
jswny revised this gist
Jul 12, 2018 . 1 changed file with 12 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -67,7 +67,7 @@ end ## 2. Running Migrations and Seeding the Database In order to be able to run migrations and seed the database from the release generated by Distillery, we will need to make a few modifications as generally outlined by the [Running Migrations](https://hexdocs.pm/distillery/running-migrations.html) guide. This section assumes that you have database seeding operations defined in the normal location under `priv/repo/`. If you don't have these, your database will just be migrated and no seeding will be done. Otherwise, you can strip down the `release_tasks.ex` file as shown below. 1. Create a file called `release_tasks.ex` which will contain the tasks that can be run from the release. You can place this file anywhere in your app's directory structure, but I will place it in `lib/myapp`. - **Note**: if you are seeding your database with certain files, these files must be placed in the `priv/` directory of your app to ensure that they are included with the generated release. Otherwise, seeding the database will not work because the files won't exist in the release. ```elixir @@ -682,4 +682,14 @@ It may be valuable to manually start the services in case you don't have access # Troubleshooting ## Old Images Sometimes, you may change something with your app but when you re-deploy the release it doesn't reflect those changes. Many times, especially as a precaution when you think something might be wrong, it is always good to do a completely fresh build of the Docker images. You can do this by running `$ docker rmi myapp-build myapp-release`. That way, you can be sure that cached Docker images or non-rebuilt images aren't messing with the changes that you made to your app. ## `init terminating in do_boot` If you are getting errors like the following: ``` {"init terminating in do_boot",{{badmatch,{error,{"no such file or directory","nil.app"}}},[{'Elixir.MyApp.ReleaseTasks',seed,0,[{file,"lib/MyApp/release_tasks.ex"},{line,19}]},{init,start_em,1,[]},{init,do_boot,3,[]}]}} init terminating in do_boot ({{badmatch,{error,{[_],[_]}}},[{Elixir.MyApp.ReleaseTasks,seed,0,[{_},{_}]},{init,start_em,1,[]},{init,do_boot,3,[]}]}) Crash dump is being written to: erl_crash.dump...done ``` The problem is with the `myapp()` function, since `Application.get_application/1` is known to sometimes not work and return `nil` when running in a release. To fix this, you should replace `Application.get_application(__MODULE__)` with your OTP app name which looks like `:myapp`. -
jswny revised this gist
Jun 5, 2018 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -33,8 +33,8 @@ This guide is written for Phoenix 1.2. However, all necesary changes to work wit ## V. Postgres Backups Disclaimer This guide currently doesn't support any kind of backups for the Docker container running your Postgres database. However, it shouldn't be hard to manually do this, or setup a simple shell script/cron job to do this automatically. For more information see [this StackOverflow post](https://stackoverflow.com/questions/24718706/backup-restore-a-dockerized-postgresql-database). I plan on adding this content when I have time to revisit this guide in the future. ## VI. Where to Get Help 💁 If you comment here on the Gist, I may see it but GitHub doesn't notify me when someone comments unfortunately. The much better place to ask me questions and get help with this guide is to post on my [Elixir Forum thread](https://elixirforum.com/t/flexible-dockerized-phoenix-deployments-1-2-1-3/12477). I get notifications for those and I check them frequently. Check out the thread if you have a question, it may have been discussed already! Thanks for reading and feel free to reach out to me if you have any questions :) # Guide -
jswny revised this gist
Jun 5, 2018 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -33,6 +33,9 @@ This guide is written for Phoenix 1.2. However, all necesary changes to work wit ## V. Postgres Backups Disclaimer This guide currently doesn't support any kind of backups for the Docker container running your Postgres database. However, it shouldn't be hard to manually do this, or setup a simple shell script/cron job to do this automatically. For more information see [this StackOverflow post](https://stackoverflow.com/questions/24718706/backup-restore-a-dockerized-postgresql-database). I plan on adding this content when I have time to revisit this guide in the future. ## VI. Where to Get Help If you comment here on the Gist, I may see it but GitHub doesn't notify me when someone comments unfortunately. The much better place to ask me questions and get help with this guide is to post on my [Elixir Forum thread](https://elixirforum.com/t/flexible-dockerized-phoenix-deployments-1-2-1-3/12477). I get notifications for those and I check them frequently. Thanks for reading and feel free to reach out to me if you have any questions :) # Guide ## 1. Add and Configure Distillery -
jswny revised this gist
May 11, 2018 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -30,6 +30,9 @@ Overall, the biggest motivation that made me want to create this guide was to se ## IV. Phoenix 1.3 This guide is written for Phoenix 1.2. However, all necesary changes to work with [Phoenix 1.3](http://phoenixframework.org/blog/phoenix-1-3-0-released) will be marked explicitly with "**Phoenix 1.3:** ...". ## V. Postgres Backups Disclaimer This guide currently doesn't support any kind of backups for the Docker container running your Postgres database. However, it shouldn't be hard to manually do this, or setup a simple shell script/cron job to do this automatically. For more information see [this StackOverflow post](https://stackoverflow.com/questions/24718706/backup-restore-a-dockerized-postgresql-database). I plan on adding this content when I have time to revisit this guide in the future. # Guide ## 1. Add and Configure Distillery -
jswny revised this gist
Mar 19, 2018 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -487,6 +487,7 @@ networks: external: true ``` Now your app can be started with a single `docker-compose up` command. This will start a database container, then a temporary container which seeds and migrates the database with `./myapp migrate`, and finally the actual Phoenix server container. However, it still won't be able to connect to the database as we haven't configured it yet. Also, it relies on an external Docker network to have already been created. - **Note:** the `expose` lines are not technically necessary. Your app will run fine without this in your Docker Compose file. However, it is good to include as it gives developers (including yourself) more information about which internal ports the container is exposing to other containers and services on the same network. In addition, running `docker ps` when the `expose` lines are present will show the port that you have your app mapped to via the `PORT` environment variable. This is especially useful if you are running multiple apps and need to keep track of which ports you are using for which apps. - **Note:** if you don't want to worry about setting up an NGINX container (which is mostly there to proxy traffic from domains to your app), then you can modify the file as follows and you will be able to access your app on port `5000` of your host machine. ```yaml ... -
jswny revised this gist
Mar 18, 2018 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -474,6 +474,8 @@ services: environment: - PORT=5000 - HOST="myapp.com" expose: - "5000" command: foreground networks: - nginx-network @@ -601,7 +603,7 @@ Now, you should be able to access your application on the domain that you specif ## 10. Extending for Multiple Applications If you want to extend your configuration for multiple applications and domains, it's very easy! 1. For your new application, follow the same application setup process above but change the `PORT` and the `expose` values in your app's `docker-compose.yml` so that your new app's port doesn't conflict with the original application's port siince they will both be on the same `nginx-network`. 2. Create a new configuration in `nginx/conf.d` for your new application, specifing the domain and the new port as necessary. -
jswny revised this gist
Mar 14, 2018 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -486,7 +486,7 @@ networks: ``` Now your app can be started with a single `docker-compose up` command. This will start a database container, then a temporary container which seeds and migrates the database with `./myapp migrate`, and finally the actual Phoenix server container. However, it still won't be able to connect to the database as we haven't configured it yet. Also, it relies on an external Docker network to have already been created. - **Note:** if you don't want to worry about setting up an NGINX container (which is mostly there to proxy traffic from domains to your app), then you can modify the file as follows and you will be able to access your app on port `5000` of your host machine. ```yaml ... server: @@ -553,7 +553,7 @@ Then, we will start an NGINX container and provide it with config files for our 2. Next, create a new directory wherever you want called `nginx` with `$ mkdir nginx` and `$ cd nginx` into it. This directory will be where we keep our NGINX config and Docker files. 3. Create a new `docker-compose.yml` file for your NGINX container. Here, we bind our `nginx-server` container to port `80` on the host machine so it can serve all of our application traffic. We also mount a read-only volume to `./conf.d`, where we will place all of our application configs. ```yaml version: "3" services: server: -
jswny revised this gist
Mar 14, 2018 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -636,6 +636,7 @@ Being able to re-deploy the server for your app without resetting or touching th 1. Rebuild the release: `./build.sh` 2. Rebuild the server container based off of the new release `docker-compose build` 3. Re-deploy the server container: `docker-compose up` - **Note:** you will most likely have to add execution permissions to the script with `chmod +x redeploy.sh`. - **Note:** when doing this, Docker knows that the `myapp-db` container is already up-to-date, so it will only restart the `admin` and `server` containers based on the changes that were made since last time. - **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up` **will** also restart the admin service and re-run any seeds and migrations. @@ -655,6 +656,7 @@ docker-compose build # Start the new containers docker-compose up ``` Then, you can easily redeploy your app from your local machine with something like `ssh -t user@server "cd /srv/myapp && ./redeploy.sh` - **Note:** you may want to start the new containers in detached mode instead of in foreground mode (where the `stdout` from your containers will take up your terminal). You can do this by adding `-d` to the end of the final command to start the containers. ## 13. Manually Starting the Services (Without Docker Compose) -
jswny revised this gist
Mar 10, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -639,7 +639,7 @@ Being able to re-deploy the server for your app without resetting or touching th - **Note:** when doing this, Docker knows that the `myapp-db` container is already up-to-date, so it will only restart the `admin` and `server` containers based on the changes that were made since last time. - **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up` **will** also restart the admin service and re-run any seeds and migrations. If you want to automate this process, you can create a simple shell script called `redeploy.sh` like so: ```shell #!/bin/sh -
jswny revised this gist
Mar 10, 2018 . 1 changed file with 18 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -639,6 +639,24 @@ Being able to re-deploy the server for your app without resetting or touching th - **Note:** when doing this, Docker knows that the `myapp-db` container is already up-to-date, so it will only restart the `admin` and `server` containers based on the changes that were made since last time. - **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up` **will** also restart the admin service and re-run any seeds and migrations. If you want to automate this process, you can create a simple shell script like so: ```shell #!/bin/sh # Pull source updates git pull # Rebuild the release ./build.sh # Rebuild the runner image docker-compose build # Start the new containers docker-compose up ``` - **Note:** you may want to start the new containers in detached mode instead of in foreground mode (where the `stdout` from your containers will take up your terminal). You can do this by adding `-d` to the end of the final command to start the containers. ## 13. Manually Starting the Services (Without Docker Compose) It may be valuable to manually start the services in case you don't have access to Docker Compose for whatever reason. Here are the steps needed to manually build and start everything after you have successfully configured everything. -
jswny revised this gist
Mar 9, 2018 . 1 changed file with 5 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -633,13 +633,11 @@ Then, you can run your releases without having to have the rest of the app's dir ## 12. Updating the App's Server Only Being able to re-deploy the server for your app without resetting or touching the database is crucial. In order to do this after a code change such as a `git pull`, do the following: 1. Rebuild the release: `./build.sh` 2. Rebuild the server container based off of the new release `docker-compose build` 3. Re-deploy the server container: `docker-compose up` - **Note:** when doing this, Docker knows that the `myapp-db` container is already up-to-date, so it will only restart the `admin` and `server` containers based on the changes that were made since last time. - **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up` **will** also restart the admin service and re-run any seeds and migrations. ## 13. Manually Starting the Services (Without Docker Compose) It may be valuable to manually start the services in case you don't have access to Docker Compose for whatever reason. Here are the steps needed to manually build and start everything after you have successfully configured everything. -
jswny revised this gist
Feb 25, 2018 . 1 changed file with 6 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -650,4 +650,9 @@ It may be valuable to manually start the services in case you don't have access 3. Run the Postgres container: `docker run --rm -it --name myapp-db --network maypp-network -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=maypp_prod -d postgres:10.2-alpine` 4. Build the runner image: `docker build -t myapp-release -f Dockerfile.run .` 5. Run migrations and seeds: `docker run --rm -it --network myapp-network myapp-server migrate` 6. Run the container with `docker run --rm -it --name myapp-server --network myapp-network -p 5000:5000 myapp-release foreground` # Troubleshooting ## Old Images Sometimes, you may change something with your app but when you re-deploy the release it doesn't reflect those changes. Many times, especially as a precaution when you think something might be wrong, it is always good to do a completely fresh build of the Docker images. You can do this by running `$ docker rmi myapp-build myapp-release`. That way, you can be sure that cached Docker images or non-rebuilt images aren't messing with the changes that you made to your app. -
jswny revised this gist
Feb 23, 2018 . 1 changed file with 13 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -441,11 +441,7 @@ USER default ENTRYPOINT ["./bin/myapp"] ``` Now, you have a container which includes Erlang to run your release in. ## 6. Create the Docker Compose File Next, we will create a [Docker Compose](https://docs.docker.com/compose/) file for our app. This file helps us provision and manage multiple containers so that we don't have to manually start each individual container with many parameters. To do this, create a `docker-compose.yml` file in the root directory of the app. @@ -643,4 +639,15 @@ Being able to re-deploy the server for your app without resetting or touching th 4. Rebuild the server container based off of the new release `docker-compose build` 5. Re-deploy the server container: `docker-compose up server` - **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up server` **will** also restart the admin service and re-run any seeds and migrations. ## 13. Manually Starting the Services (Without Docker Compose) It may be valuable to manually start the services in case you don't have access to Docker Compose for whatever reason. Here are the steps needed to manually build and start everything after you have successfully configured everything. ### Without NGINX 1. Build the release: `$ ./build.sh` 2. Create the Docker network: `docker network create myapp-network` 3. Run the Postgres container: `docker run --rm -it --name myapp-db --network maypp-network -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=maypp_prod -d postgres:10.2-alpine` 4. Build the runner image: `docker build -t myapp-release -f Dockerfile.run .` 5. Run migrations and seeds: `docker run --rm -it --network myapp-network myapp-server migrate` 6. Run the container with `docker run --rm -it --name myapp-server --network myapp-network -p 5000:5000 myapp-release foreground` -
jswny revised this gist
Feb 23, 2018 . 1 changed file with 0 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -428,9 +428,6 @@ Next, we need a Dockerfile to run the generated release that Distillery has buil ```Dockerfile FROM bitwalker/alpine-erlang:20.2.2 # Set environment variables ENV MIX_ENV=prod -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -542,7 +542,7 @@ config :myapp, MyApp.Repo, password: "postgres", hostname: "myapp-db" database: "myapp_prod", ... ... ``` -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -518,12 +518,12 @@ In order to run our releases inside the Docker environment, we need to change a ```elixir ... config :myapp, MyApp.Endpoint, http: [port: {:system, "PORT"}], url: [host: {:system, "HOST"}, port: {:system, "PORT"}], server: true, root: ".", version: Application.spec(:myapp, :vsn), ... ``` -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -631,7 +631,7 @@ To compile your release on a different machine than your deployment machine, do 2. Copy the release tarball to your deployment machine. If you already have your app's directory structure on that machine, you can place it in `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` (depending on your version). - Otherwise, if you don't have the entire app's directory structure on your deployment machine and are only using the Docker related files which you need to deploy the app, simply make new directories reflecting `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` in the root directory where your Docker files (see below) are located and place the tarball there. - **Note:** on your deployment machine, you really only need the following files to deploy the app: 1. `Dockerfile.run` 2. `docker-compose.yml` 3. Your release tarball in the correct directory as described above -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -415,7 +415,7 @@ docker run -it --rm --name myapp-build -v $(pwd)/_build/prod/rel:/opt/app/_build Now, you can run the script with `./build.sh` and it will build and run the Docker container which will build the release in `_build/prod/rel/myapp`. - **Note:** the `$(pwd)` variable may not function correctly with paths which include spaces. Therefore, you may have to substitute this value for the full path to your app instead. ### Diagram The following diagram depicts the build process: @@ -646,4 +646,4 @@ Being able to re-deploy the server for your app without resetting or touching th 4. Rebuild the server container based off of the new release `docker-compose build` 5. Re-deploy the server container: `docker-compose up server` - **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up server` **will** also restart the admin service and re-run any seeds and migrations. -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -415,6 +415,8 @@ docker run -it --rm --name myapp-build -v $(pwd)/_build/prod/rel:/opt/app/_build Now, you can run the script with `./build.sh` and it will build and run the Docker container which will build the release in `_build/prod/rel/myapp`. **Note:** the `$(pwd)` variable may not function correctly with paths which include spaces. Therefore, you may have to substitute this value for the full path to your app instead. ### Diagram The following diagram depicts the build process: -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 32 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -314,7 +314,7 @@ priv/static ``` 2. Add a file called `Dockerfile.build` to the root directory of your app. This file will be used to build the release inside a Docker container with Alpine Linux (the base image we will run the release in) as the target architecture. ```Dockerfile FROM bitwalker/alpine-elixir-phoenix:1.6.1 ENV MIX_ENV prod @@ -368,10 +368,39 @@ index fb7078b..6ea163e 100644 ENTRYPOINT ["mix"] ``` ```Dockerfile FROM bitwalker/alpine-elixir-phoenix:1.6.1 ENV MIX_ENV prod # Add the files to the image ADD . . # Cache Elixir deps RUN mix deps.get --only prod RUN mix deps.compile WORKDIR assets # Cache Node deps RUN npm i # Compile JavaScript RUN npm run deploy WORKDIR .. # Compile app RUN mix compile RUN mix phx.digest # Generate release ENTRYPOINT ["mix"] CMD ["release", "--env=prod"] ``` ## 4. Add a Build Script Next we will add a shell script which will build the release. This script first builds the release builder image using `Dockerfile.build`, and then it runs the container, with a volume connected to the host machine's `rel/` directory. This way, when the container is run, the release is built inside of the `rel/` directory inside of the container but the release remains on the host machine in the same directory after the container exists. Remember, since the release is built inside the container for the Alpine Linux architecture, you will probably not be able to run this release on your host machine. - **Note:** You will most likely have to add execution permissions to this file using `sudo chmod +x build.sh`. ```shell #!/bin/sh # Remove old releases @@ -394,7 +423,7 @@ The following diagram depicts the build process: ## 5. Create the Run Dockerfile Next, we need a Dockerfile to run the generated release that Distillery has built for us. In the root directory of your application, create a file called `Dockerfile.run`. In this file, we have not specified a default command via a `CMD` instruction for the container. This is because we will set this in the `docker-compose.yml` file later so that we can change the command there if needed. - **Note:** you may have to change the `0.0.1` part of the path in this file depending on the version of your OTP app which you have specified. ```Dockerfile FROM bitwalker/alpine-erlang:20.2.2 # Set exposed ports -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 20 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -293,6 +293,26 @@ index 858de0d..c20021c 100644 test ``` ``` # Git data .git # Elixir build artifacts _build # Don't ignore the directory where our releases get built !_build/prod/rel deps # Node build artifacts assets/node_modules # Tests test # Compiled static artifacts priv/static ``` 2. Add a file called `Dockerfile.build` to the root directory of your app. This file will be used to build the release inside a Docker container with Alpine Linux (the base image we will run the release in) as the target architecture. ``` FROM bitwalker/alpine-elixir-phoenix:1.6.1 -
jswny revised this gist
Feb 22, 2018 . 1 changed file with 39 additions and 15 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -135,7 +135,45 @@ defmodule MyApp.ReleaseTasks do end ``` If your app only needs to run migrations and not seed the database, you can use a stripped-down version of the file. In this version, the `seed()` function only runs migrations via `migrate()`, it does not seed the database. ```diff diff --git a/release_tasks.ex b/release_tasks.ex index 8e0d066..f8117de 100644 --- a/release_tasks.ex +++ b/release_tasks.ex @@ -29,9 +29,6 @@ defmodule MyApp.ReleaseTasks do # Run migrations migrate() - # Run seed script - Enum.each(repos(), &run_seeds_for/1) - # Signal shutdown IO.puts "Success!" :init.stop() @@ -47,19 +44,8 @@ defmodule MyApp.ReleaseTasks do Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true) end - def run_seeds_for(repo) do - # Run the seed script if it exists - seed_script = seeds_path(repo) - if File.exists?(seed_script) do - IO.puts "Running seed script.." - Code.eval_file(seed_script) - end - end - def migrations_path(repo), do: priv_path_for(repo, "migrations") - def seeds_path(repo), do: priv_path_for(repo, "seeds.exs") - def priv_path_for(repo, filename) do app = Keyword.get(repo.config, :otp_app) repo_underscore = repo |> Module.split |> List.last |> Macro.underscore ``` ```elixir defmodule MyApp.ReleaseTasks do @@ -169,9 +207,6 @@ defmodule MyApp.ReleaseTasks do # Run migrations migrate() # Signal shutdown IO.puts "Success!" :init.stop() @@ -187,19 +222,8 @@ defmodule MyApp.ReleaseTasks do Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true) end def migrations_path(repo), do: priv_path_for(repo, "migrations") def priv_path_for(repo, filename) do app = Keyword.get(repo.config, :otp_app) repo_underscore = repo |> Module.split |> List.last |> Macro.underscore -
jswny revised this gist
Feb 21, 2018 . 1 changed file with 11 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -561,4 +561,14 @@ To compile your release on a different machine than your deployment machine, do 2. `docker-compose.yml` 3. Your release tarball in the correct directory as described above Then, you can run your releases without having to have the rest of the app's directory structure and code on your deployment machine. ## 12. Updating the App's Server Only Being able to re-deploy the server for your app without resetting or touching the database is crucial. In order to do this after a code change such as a `git pull`, do the following: 1. Stop only the server container: `docker-compose stop server` 2. Remove only the server container: `docker-compose rm server` 3. Rebuild the release: `./build.sh` 4. Rebuild the server container based off of the new release `docker-compose build` 5. Re-deploy the server container: `docker-compose up server` **Note:** since the `server` service defined in `docker-compose.yml` depends on the `admin` service (the database seeds and migrations), running `docker-compose up server` **will** also restart the admin service and re-run any seeds and migrations. -
jswny revised this gist
Feb 15, 2018 . 1 changed file with 5 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -543,6 +543,11 @@ If you want to extend your configuration for multiple applications and domains, That's it! Your NGINX container will now proxy traffic appropriately for both of your apps. ### Diagram The following diagram depicts running multiple apps using a single NGINX container to proxy traffic to the appropriate app containers:  ## 11. Compiling Releases Separately A huge advantage of this deployment strategy is the fact that compiling the releases is completely decoupled from deploying them. That means that you can compile your Distillery release anywhere you want, even on your development machine. It will be compiled for the correct architecture using Docker. Both the release builder image and the deployment (runner) image are based on [Alpine](https://hub.docker.com/_/alpine/). -
jswny revised this gist
Feb 14, 2018 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -342,6 +342,11 @@ docker run -it --rm --name myapp-build -v $(pwd)/_build/prod/rel:/opt/app/_build Now, you can run the script with `./build.sh` and it will build and run the Docker container which will build the release in `_build/prod/rel/myapp`. ### Diagram The following diagram depicts the build process:  ## 5. Create the Run Dockerfile Next, we need a Dockerfile to run the generated release that Distillery has built for us. In the root directory of your application, create a file called `Dockerfile.run`. In this file, we have not specified a default command via a `CMD` instruction for the container. This is because we will set this in the `docker-compose.yml` file later so that we can change the command there if needed. - **Note:** you may have to change the `0.0.1` part of the path in this file depending on the version of your OTP app which you have specified. @@ -426,6 +431,11 @@ server: ... ``` ### Diagram The following diagram depics the process of running the application with Docker Compose:  ## 7. Configure Your App In order to run our releases inside the Docker environment, we need to change a few Elixir config files. This section is loosely based on the [Using Distillery With Phoenix](https://hexdocs.pm/distillery/use-with-phoenix.html). -
jswny revised this gist
Feb 13, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -539,7 +539,7 @@ A huge advantage of this deployment strategy is the fact that compiling the rele To compile your release on a different machine than your deployment machine, do the following: 1. Run your `build.sh` script as described above on whichever machine you want to compile your release. You should now have a release built at `_build/prod/rel/myapp`. And a tarball release in `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` (depending on your app version). 2. Copy the release tarball to your deployment machine. If you already have your app's directory structure on that machine, you can place it in `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` (depending on your version). - Otherwise, if you don't have the entire app's directory structure on your deployment machine and are only using the Docker related files which you need to deploy the app, simply make new directories reflecting `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` in the root directory where your Docker files (see below) are located and place the tarball there. **Note:** on your deployment machine, you really only need the following files to deploy the app: 1. `Dockerfile.run` -
jswny revised this gist
Feb 13, 2018 . 1 changed file with 21 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ # Prelude ## I. Preface and Motivation This guide was written because I don't particularly enjoy deploying Phoenix (or Elixir for that matter) applications. It's not easy. Primarily, I don't have a lot of money to spend on a nice, fancy VPS so compiling my Phoenix apps on my VPS often isn't an option. For that, we have Distillery releases. However, that requires me to either have a separate server for staging to use as a build server, or to keep a particular version of Erlang installed on my VPS, neither of which sound like great options to me and they all have the possibilities of version mismatches with ERTS. In addition to all this, theres a whole lot of configuration which needs to be done to setup a Phoenix app for deployment, and it's hard to remember. @@ -28,6 +30,8 @@ Overall, the biggest motivation that made me want to create this guide was to se ## IV. Phoenix 1.3 This guide is written for Phoenix 1.2. However, all necesary changes to work with [Phoenix 1.3](http://phoenixframework.org/blog/phoenix-1-3-0-released) will be marked explicitly with "**Phoenix 1.3:** ...". # Guide ## 1. Add and Configure Distillery For generating releases, we will be using [Distillery](https://github.com/bitwalker/distillery), which allows us to package a release of our application into a single tarball. @@ -514,6 +518,8 @@ Now we have everything set up. Our application will run itself in the appropriat Now, you should be able to access your application on the domain that you specified. # Extras ## 10. Extending for Multiple Applications If you want to extend your configuration for multiple applications and domains, it's very easy! @@ -526,3 +532,18 @@ If you want to extend your configuration for multiple applications and domains, 4. Then, restart your NGINX container by running `docker-compose restart`. Make sure your new app's server is started before you restart NGINX. That's it! Your NGINX container will now proxy traffic appropriately for both of your apps. ## 11. Compiling Releases Separately A huge advantage of this deployment strategy is the fact that compiling the releases is completely decoupled from deploying them. That means that you can compile your Distillery release anywhere you want, even on your development machine. It will be compiled for the correct architecture using Docker. Both the release builder image and the deployment (runner) image are based on [Alpine](https://hub.docker.com/_/alpine/). To compile your release on a different machine than your deployment machine, do the following: 1. Run your `build.sh` script as described above on whichever machine you want to compile your release. You should now have a release built at `_build/prod/rel/myapp`. And a tarball release in `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` (depending on your app version). 2. Copy the release tarball to your deployment machine. If you already have your app's directory structure on that machine, you can place it in `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` (depending on your version). - Otherwise, if you don't have the entire app's directory structure on your deployment machine and are only using the Docker related files which you need to deploy the app, simply make new directories reflecting `_build/prod/rel/myapp/releases/0.0.1/myapp.tar.gz` in the root directory where your Docker files (see below) are located and place the tarball there. **Note:** on your deployment machine, you really only need the following files to deploy the app: 1. `Dockerfile.run` 2. `docker-compose.yml` 3. Your release tarball in the correct directory as described above Then, you can run your releases without having to have the rest of the app's directory structure and code on your deployment machine.
NewerOlder