Managing local resources with Tilt or how do I setup my local dev environment
Tags: tilt, docker, elixir, react
Published: 2021-01-27 19:58:27

---
title: Managing local resources with Tilt or how do I setup my local dev environment
published: true
tags: tilt, docker, elixir, react
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/qf9qocnkb1elqfsx6vin.png
canonical_url: https://geoffroybaumier.hashnode.dev/managing-local-resources-with-tilt-or-how-do-i-setup-my-local-dev-environment
---

I have been working with Tilt for almost a year now and I find it very useful to manage local resources and applications. I'm currently working on a side project called flashcards and I have done the setup of my local environment with Tilt.

What we want to achieve here is to setup:
- A local database running in a container
- A bare Phoenix project (API)
- A bare React project
- A Tiltfile to rule them all

Here is the tree of my directory:
```
├── backend
├── docker
│   └── docker-compose.yml
├── env
│   └── postgres.env
├── frontend
└── Tiltfile
```

## Setup the database

Prerequisite:
- Have Docker installed and running

First let's setup the docker-compose.yml file. I want to have a simple postgres database running in a docker container.
```
version: '3.8'
services:
  postgres:
    image: postgres:13
    container_name: flashcards_database
    volumes:
      - postgres-data:/var/lib/postgresql/data/
    env_file:
      - ../env/postgres.env
    ports:
      - 5432:5432

volumes:
  postgres-data:
```

Nothing out of the ordinary here, the only thing I like to do is having the environment variables in an external file.
```
POSTGRES_USER=geoffroy_baumier
POSTGRES_PASSWORD=password
POSTGRES_DB=flashcards_dev
```

Perfect, now that this is done I can spin it up in order to setup my Phoenix project.
```
$ docker-compose -f docker/docker-compose.yml up
[...]
Creating fashcards_database ... done
Attaching to fashcards_database
[...]
fashcards_database | 2021-01-27 18:18:23.825 UTC [1] LOG:  database system is ready to accept connections
```

The database is now listening on the port default postgres port 5432.

## Setup the API

Prerequisites:
- Have erlang installed
- Have elixir installed
- And have the database running

_"If we have just installed Elixir for the first time, we will need to install the Hex package manager as well. Hex is necessary to get a Phoenix app running (by installing dependencies) and to install any extra."_
[Source: hexdocs.pm](https://hexdocs.pm/phoenix/installation.html)

Let's install the hex package manager:
```
$ mix local.hex
```
Now let's install the Phoenix application generator:
```
$ mix archive.install hex phx_new
```

I only want to create an API and not use the views in Phoenix. So I do not want to generate the project with views and use webpack. I will use the corresponding options (for more info see [here](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.New.html)):
```
mix phx.new flashcards --no-html --no-webpack

Fetch and install dependencies? [Yn] y
	* running mix deps.get
  * running mix deps.compile
```

Now that our project is generated we can edit the database configuration in `config/dev.exs`:
```
# Configure your database
config :flashcards, Flashcards.Repo,
  username: "geoffroy_baumier",
  password: "password",
  database: "flashcards_dev",
  hostname: "localhost",
  [...]
```

Now we can create the database:
```
$ mix ecto.create
Compiling 11 files (.ex)
Generated flashcards app
The database for Flashcards.Repo has already been created
```
Good, now let's start the application:
```
$ mix phx.server
[info] Running FlashcardsWeb.Endpoint with cowboy 2.8.0 at 0.0.0.0:4000 (http)
[info] Access FlashcardsWeb.Endpoint at http://localhost:4000
```

Perfect! If you want to see the project running, go to [http://localhost:4000/dashboard/home](http://localhost:4000/dashboard/home).

## Setup the frontend

Prerequisites:
- Have NodeJS installed
- Choose a package manager, personally I use yarn

Now we have our database and our API. As you see they already take two tabs of my terminal (dramatic tone, I could also just run in detached mode). We are only missing the frontend, let's jump into it without many details (more info [here](https://create-react-app.dev/docs/getting-started/)).

```
$ yarn create react-app my-app
$ yarn start
```

Now the frontend is running on [http://localhost:3000/](http://localhost:3000/). And a third tab in my terminal is being used!

## Setup Tilt

Here come the best part, we can regroup and manage those resources all in one place using Tilt. Thanks to Tilt we can automate processes: start of the applications, watch for file changes, build our containers, watch the logs,...

If you are using Homebrew you can install Tilt with this command:
```
$ brew install tilt-dev/tap/tilt
```

**For the magic to happen, I strongly suggest that you stop your container (even delete it), stop the Phoenix application and also the React application. Stop everything!**
<br/><br/>

Now let's create our Tiltfile at the root of the project.

The first thing we want to do is create and start our database container. All I have to is reference the docker-compose file:
```
docker_compose('docker/docker-compose.yml')
```

Then just below let's add our Phoenix application, I will call it 'api':
```
local_resource(
  'api',
  'cd backend && mix deps.get',
  deps=['backend/config', 'backend/mix.exs', 'backend/mix.lock'],
  serve_cmd='cd backend && mix phx.server',
  resource_deps=['postgres']
)
```
Let's go through the list of these parameters:
- The first one is the name
- Then it is the command to be executed
- After we find the deps: which is _"a list of files or directories to be added as dependencies to this cmd. Tilt will watch those files and will run the cmd when they change."_
- Then we have the serve command which will be run on update
- And finally the resources of which this current resource depends on. As you can see we can directly reference the docker service.

There are more parameters available: [link](a list of resources on which this resource depends.)

And finally we can add our frontend:
```
local_resource(
  'frontend',
  'cd frontend && yarn install --frozen-lockfile',
  serve_cmd='cd frontend && yarn start',
  deps=['frontend/package.json', 'frontend/yarn.lock'],
  resource_deps=['api']
)
```

Here is the whole Tiltfile:
```
docker_compose('docker/docker-compose.yml')

local_resource(
  'api',
  'cd backend && mix deps.get',
  serve_cmd='cd backend && mix phx.server',
  deps=['backend/config', 'backend/mix.exs', 'backend/mix.lock'],
  resource_deps=['postgres']
)

local_resource(
  'frontend',
  'cd frontend && yarn install --frozen-lockfile',
  serve_cmd='cd frontend && yarn start',
  deps=['frontend/package.json', 'frontend/yarn.lock'],
  resource_deps=['api']
)
```

To run it we simply have to run this command in the root of our directory:
```
$ tilt up
```

And everything spins up and we have a nice interface to manage every individual service just in one place. I think that it's wonderful and I gladly recommand using it for local developement. It makes everything easier to start the whole stack with just one command. It also watches the files and does a reload. You can also manually reload a resource. And you have access to all the logs in one tab!

Ho I almost forgot, to stop it you can run:
```
$ tilt down
```

More info on managing local resources [here](https://docs.tilt.dev/local_resource.html).