Elixir/Phoenix Project: Dockerizing
Noel Worden
Posted on October 14, 2020
Goals:
- Dockerize project
- Update README with new instructions on launching app with Docker
Dockerize project
Although this is implied with all of my writing, it's especially true with Docker, so it bears to be said explicitly: I am by no means a Docker expert. What I will be talking about in this post are the steps I took to get my project running in Docker from online resources and my past experience. If there is any aspect of what I'm about to talk about that could be improved, I would greatly appreciate any feedback. With that caveat out of the way, here is what I did to build my app in Docker images.
Actually, before I dive into the files, here's a quick refresher on whats what in the world of Docker:
- A
Dockerfile
builds an image - A container is started from that image
-
docker-compose.yml
defines which containers (aka services) make up a complete app
The first step was to create a Dockerfile
, which is a file of specifications that Docker uses to build an image. For my Dockerfile
I used an image from Docker Hub that I have used in the past, alpine-elixir-phoenix. I have been happy with it, and I'm also familiar with how to setup a Dockerfile
with it. I used the image docs as a starting point for my Dockerfile
but ended up simplifying it a bit for my needs:
Heres the breakdown of the file:
This is declaring which version of elixir will be used.
This is executing the RUN
command to create a new directory ,/app
. Then WORKDIR
is setting that newly created folder as the working directory.
This is executing the COPY
command to move the mix.exs
and mix.lock
files from the local directory into the image directory, then using RUN
to execute a mix
command in the image directory.
Similar to the previous command, this is executing COPY
to move the necessary assets
from the local directory to the image, then RUN
to execute an npm install --prefix
into the folder on the image.
This copies the rest of the files and folders from the root of the local directory to the root of the image.
Lastly, an execution of CMD
to start the server
With the Dockerfile
complete, the next step was to create a docker-compose.yml
file. Like I said earlier, this file defines the containers that will make up the complete app. There's a good amount of content, so I'll utilize comments in the example code to explain what is what, instead of listing everything out individually:
One last thing that I needed to do before taking this for a test run was to change to the dev.exs
file. This change was not on any of the tutorials I used, and it caused me enough trouble that when I found the solution I actually wrote up a standalone post about it. The change is pretty painless, the hostname
field of the Repo
config needs to be updated from localhost
to db
to match the name of the container running the database:
With the two docker files created, the update to dev.exs
, and Docker for Mac installed an running on my machine, the app is up and running with three commands (I recommend executing in two tabs of the terminal):
- Terminal Tab 1
docker-compose build
docker-compose up
Once its spun up, the db
container shows the following error:
Although the db
container is up and running, the app is looking for the database that is declared in dev.exs
, in this case atlas_dev
. The third command will take care of this:
- Terminal Tab 2
docker-compose exec web mix ecto.setup
That command uses exec web
to execute the mix
command in the currently running web
container. The ecto.setup
command is from the mix.exs
file, and runs a list of commands:
Although I don't have any migrations or seeds at the moment, I still use that command, it's mostly a muscle memory thing at this point.
With that command executed in a second tab, the logs in the first tab no longer display an error, and everything is ready to go. The app can now be viewed at localhost:4000. Of course, since I have yet to actually code anything in this new app, it's still the generic Phoenix startup page, but that will change soon.
Update README with new instructions on launching app with Docker
With the project Dockerized, I also updated the README with new instructions on how to spin up the app:
Spinning up project with Docker
- Install Docker for Mac
- In one terminal tab:
docker-compose build
docker-compose up
- In a second tab, once the two commands in the first tab are completed:
docker-compose exec web mix ecto.setup
- If everything spins up with no errors, site will be live at localhost:4000
It's essentially the steps from above, but I believe that keeping docs updated is important, so it's worth noting as part of my process
Bonus - Ignoring files for a faster Docker build
A file can be created that is similar to what .gitignore
does for git, but for Docker. This file is .dockerignore
and Docker looks for this file before each build to see if there are files that can be skipped in the execution of the build. Skipping files creates a smaller image and therefore a faster build. I pulled the contents of my .dockerignore
from the Distillery hexdocs:
Adding this file was one of my last steps in the process, and I kind of regret that, as the build is noticeably faster with Docker ignoring these files. Adding this earlier in the process would have saved me a lot of time while experimenting with the proper Dockerfile
and docker-compose.yml
configurations.
Closing thoughts
Docker will be the last devops aspect I am going to setup. I am ready to do some feature coding and get that default Phoenix splash page out of there. But, I am very happy that I have taken the time to set my project up with these tools and make the process as streamlined as possible right out of the gate. From here on out I can basically just concern myself with features and whatever random thing I want to try, and all the checks I have in place will keep my code tidy and easy to deploy.
This is my repo at the end of this block of work.
References
- https://docs.docker.com/engine/reference/builder/
- https://hub.docker.com/r/bitwalker/alpine-elixir-phoenix/
- https://medium.com/swlh/use-docker-to-create-an-elixir-phoenix-development-environment-e1a81def1d2e
- https://codereviewvideos.com/course/elixir-phoenix-and-docker-tutorial/video/docker-compose-tutorial-for-elixir-and-phoenix-framework
- https://codefresh.io/docker-tutorial/not-ignore-dockerignore-2/
This post is part of an ongoing series. I encourage any critique, feedback, or suggestions in the comments.
Posted on October 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.