Docker enables developers to experiment with new languages without leaving any lasting effects or cruft on our machines. To encourage other developers to try Phoenix & Elixir, below are instructions to get up and running with Phoenix on Docker in just a few minutes.

1. Create the docker config

First, we need to set up the docker configuration for the app. Create the app directory ./hello (we will use hello in order to mirror the Phoenix Guides) and 3 files inside:

hello/.env

# empty, but syntax is
# NAME=value

This file is empty, but we can use it to pass in runtime config as ENV vars. See also https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-application-configuration regarding application configuration with the new mix release in Elixir 1.9.

hello/Dockerfile

FROM elixir:1.9.1

ENV PHX_VERSION 1.4.10
ENV NODE_MAJOR 12

ENV APP_HOME /app
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

RUN set -x &&\
  mix local.hex --force &&\
  mix local.rebar --force &&\
  mix archive.install hex phx_new $PHX_VERSION --force &&\
  curl -sL https://deb.nodesource.com/setup_$NODE_MAJOR.x | bash - &&\
  apt-get install -y nodejs inotify-tools

This dockerfile uses the Elixir 1.9.1 image (Debian Stretch) and installs Phoenix & node.

hello/docker-compose.yml

version: "3"
volumes:
  node_modules:
  build:
services:
  db:
    image: postgres:11-alpine
  web:
    build: .
    env_file: .env
    command: mix phx.server
    volumes:
      - .:/app
      - node_modules:/app/assets/node_modules
      - build:/app/_build
    ports:
      - "4000:4000"
    depends_on:
      - db

The compose file sets up a Postgres 11 database and a web service that uses the Dockerfile and .env files we created.

The node_modules and _build directories use named volumes so that writes are not performed across the docker VM boundary on MacOS and Windows. This will result in a large speedup for npm install and mix compile on MacOS and Windows docker. The downside is that _build and node_modules will be empty on the host as the directory contents live in the VM. This can be removed or ignored for linux users as linux docker is not inside a VM.

We're done with docker. From here on out it is mostly a standard Phoenix installation process (running in docker-compose).

2. Create the Phoenix application

Run the following command from within ./hello to generate a Phoenix application with the name hello. The app is created in the existing hello directory due to the use of . and --app hello.

docker-compose run web mix phx.new . --app hello

Answer yes to any questions.

Note: Steps 1 and 2 seem a little backwards since we created the directory and config first, then generated the app within it. This is because we want to run all Elixir code within docker. The resulting application is identical to running mix phx.new hello on a system Elixir install, outside of docker.

3. Update the database connection

The default database connection needs to be updated to connect to the docker-compose database service. Open hello/config/dev.exs and update the password and hostname in the Hello.Repo config block:

# Configure your database
config :hello, Hello.Repo,
  username: "postgres",
  password: "",
  database: "hello_dev",
  hostname: "db",
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

Remove the password and change hostname to "db" (the name of our Postgres service in docker-compose.yml).

4. Create the database

docker-compose run web mix ecto.create

5. Start the Phoenix application

docker-compose up

Visit http://localhost:4000 to see the Phoenix start page. If you change anything on the start page hello/lib/hello_web/templates/layout/app.html.eex and save, you should see the page refresh in the browser.

Tip: add alias dc='docker-compose' to your bashrc (or whatever) to avoid typing a lot

What's next

You can continue the Guides from here, or feel free to start playing with interesting Phoenix features like LiveView or Channels.