This post is part of the Elixir Setup Series, and the Ecto Series.

Onboarding new team members quickly is crucial for maintaining momentum. This post is about setting up an Elixir/Ecto project so new developers can get up and running with minimal friction.

Ecto supports multiple databases, but the typical choice in the Elixir environment is PostgreSQL.

Docker

Start with a basic docker-compose.yml file, which boots up a PostgreSQL instance. Note the port remap from PostgreSQL’s 5432 to 5482; this distinguishes this instance from other PostgreSQL instances running on your local machine.

version: '3.1'

services:
  game_db_dev:
    image: postgres
    environment:
      POSTGRES_DB: game_db_dev
      POSTGRES_USER: dev_user
      POSTGRES_PASSWORD: dev_password
    ports:
      - "5482:5432"
    networks:
      - test_network

The database name, user, and password are not secret, as this is only running locally.

Config

Update the config/dev.exs file to match the PostgreSQL instance that will be running in Docker.

config :game_app, GameApp.Repo,
  username: "dev_user",
  password: "dev_password",
  hostname: "localhost",
  database: "game_app_dev",
  port: 5482,
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

Makefile

While you can use the mix.exs file’s aliases, I prefer using a Makefile to manage tasks.

up:
	@echo "Starting up all containers..."
	@docker-compose up -d

down:
	@echo "Shutting down all containers..."
	@docker-compose down

setup.dev:
	@echo "Getting dependencies for the development environment..."
	MIX_ENV=dev mix deps.get
	@echo "Creating the database for the development environment..."
	MIX_ENV=dev mix ecto.create
	@echo "Running migrations for the development environment..."
	MIX_ENV=dev mix ecto.migrate
	@echo "Adding dialyzer..."
	MIX_ENV=dev mix dialyzer --plt

migrate.dev:
	@echo "Running migrations for the development environment..."
	MIX_ENV=dev mix ecto.migrate

serve.dev:
	@echo "Recompiling and running the dev server..."
	MIX_ENV=dev mix clean
	MIX_ENV=dev mix compile
	MIX_ENV=dev mix phx.server

reset.dev:
	@echo "Resetting the database for the development environment..."
	MIX_ENV=dev mix ecto.drop
	@echo "Recreating the database for the development environment..."
	MIX_ENV=dev mix ecto.create
	@echo "Migrating the database for the development environment..."
	MIX_ENV=dev mix ecto.migrate

The tasks above manage the basic application dev setup.

  • up: Runs the Docker commands in the docker-compose.yml file in detached mode (so it doesn’t shut down when the terminal is closed).
  • down: Shuts down all Docker instances from the docker-compose.
  • setup.dev: I typically run my Makefile commands with the environment as a suffix. This command runs all setup tasks (getting dependencies, creating and migrating the database, and adding Dialyzer).
  • migrate.dev: A stand-alone command to migrate the database.
  • serve.dev: Runs the Phoenix server with hot reloading. This command includes a clean and recompile step to prevent issues when recompiling, ensuring a clean slate.
  • reset.dev: Drops and creates a fresh instance of the development database.