The only thing you need to download/have installed is Docker.
Please refer to the official Docker documentation for instructions on how to install Docker locally. Please not that if you do not download the Docker Desktop client and install Docker in a different way, you need to make sure you install both Docker AND Docker-Compose. The Docker Desktop client handles installing both for you:
Once you have Docker and Docker-Compose installed, clone this repo and open a terminal window in the root project
directory (draftivist/
).
From there, just run docker-compose up
and all of the containers will be built and started! It will probably take a
while to build the first time, but subsequent runs will be significantly faster.
To stop all of the containers, you can just use Ctrl+C
(the standard terminal command for stopping the current
process.)
See below for more helpful Docker commands.
When first setting up your environment (or any time there are changes to the database schema), just run the following to update your database to the latest:
docker-compose run api python manage.py migrate
To load an initial campaign that is pre-populated with issues and statements (note, you must run the database initialize command above first so the expected DB tables are already set up):
docker-compose run api python manage.py loaddata api/fixtures/test_campaign.json
To start the the Draftivist UI app:
- Ensure Node v14 is installed: Node installation
- Ensure
yarn
is installed: yarn installation docs - Run
yarn install
to install all packages. - Run
yarn start
to manually run the application. Once running, the application will be available at http://localhost:3000.
Note that this method is a longer process and prone to more errors than using the docker configurations. You will also have to ensure you have Postgres installed locally (this is included in the instructions below for Mac setup).
- install postgresql, pyenv, and pyenv-virtualenv (Mac Only)
brew install pyenv pyenv-virtualenv postgresql
Then add the following to ~/.zshrc
(or ~/.bash_profile
if you are not using zsh) to automatically initialize the
virtualenv when you are in this directory
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
if which pyenv-virtualenv-init > /dev/null; then
eval "$(pyenv virtualenv-init -)"
fi
Restart your shell. Now that PYENV_ROOT
is set, install python version 3.9.0 and create a virtualenv for draftivist:
pyenv install 3.9.0
pyenv virtualenv 3.9.0 draftivist
Restart your shell once more. At this point, if you navigate to draftivist/draftivist_api
in a terminal, you should
see something like this:
(draftivist) knewman@Keiths-MacBook-Pro draftivist_api %
indicating that you are within the draftivist virtual environment. The reason it says "(draftivist)" is because of the
.python-version
file in the draftivist_api/
directory.
To further verify that it is working correctly, you can run this:
pyenv which pip
Which should point to the local paths we set up within PYENV_ROOT
. Something like:
/Users/knewman/.pyenv/versions/draftivist/bin/pip
Once we know that we are inside the virtualenv, you can just install the requirements:
pip install -r requirements.txt
The basic structure for our production app is to build the frontend app in a Docker container using webpack, and then
copy those static assets into the draftivist_api/frontend/static
. We then leverage Django's built-in collectstatic
to upload all of the static assets to DigitalOcean Spaces (similar to Amazon S3), which we then use to serve the frontend
app's CSS and JS files, as well as the static assets for the Django admin and Rest Framework assets.
####Running a production-like app locally Note that these steps are a bit finnicky, as we are faking several of the steps in an actual production setup. If you are still seeing this message, then I probably have not gotten around to making it more robust, so proceed at your own risk. :)
- Copy the contents of
.env-example
into a file called.env
- Tweak
draftivist_ui/config/webpack.config.production.js
with the following values:'__API_HOSTNAME__': JSON.stringify("http://localhost:8000/api")
publicPath: "http://localhost:8000/static"
- Start up your local database
docker-compose up -d db
- Build the app! From the root directory, just run
./scripts/run_production.sh
####A few notes
- As you may have noticed, in the
.env-example
file, we havePROJECT_ENVIRONMENT="DEV"
. On our actual production environment, we use the environment "PROD", but building with that configuration will cause an error locally since you do not have the production database or DigitalOcean Spaces credentials. As an alternative, the static assets are served locally from the system, which also leverages Django's built-in static asset collection. - The app runs on port 8000. On production, we have
nginx
running as a reverse-proxy which allows port 80 on our production server to deliver the application.
Sometimes it can be helpful to add an alias for a terminal command that you know you will use frequently. Since
docker-compose
can be annoying to keep typing, I recommend adding this line to your currently shell profile:
alias dc="docker-compose"
This will allow you to just type dc
instead of docker-compose
every time.
Note: depending on your operation system and which terminal shell you are using, the location and name of your shell profile may vary. Some common options are:
- Mac/Linux
~/.zshrc
(if using zsh, the new standard on macs)~/.bash_profile
(if using an older/standard terminal)
- Windows
- Unfortunately, bash profiles and aliases are a bit more complicated to set up in Windows. If you are on a Windows machine and this becomes an issue for you, please raise your concern and we can lock down an official recommended protocol.
Here are a list of some of the most helpful Docker and Docker-Compose commands. Unless otherwise noted, you can assume that these should all be run in the project's root directory.
Also, there are some commands where I mention being able to pass in a container name. To view the list of possible
containers, check the docker-compose.yaml
file. The containers are each listed at the first nested level, under
services
(i.e. api
, db
, ui
).
docker ps -a
docker-compose up
docker-compose up -d
This is particularly useful if you started your containers in detached mode.
docker-compose stop
You can run pretty much any docker-compose
command by passing in a specific container's name as the last argument.
For example:
# Only starts api in detached mode
docker-compose up -d api
# Restart UI
docker-compose restart ui
docker-compose run api bash
This allows you to pass any command-line input to the container.
docker-compose run api <custom command>
# Examples
docker-compose run ui yarn install
docker-compose run api python manage.py migrate
Having all of the console output streaming to a single terminal window can be hard to follow. Often, it is easier to start all containers in detached mode, and then use the following command to get a live readout of the terminal output for a given container.
docker-compose logs -ft <container name>
# Example
docker-compose logs -ft api
Each time you kick off a different command, you are creating a new docker container. For example, try running the following commands:
docker-compose up -d
docker-compose run api bash
# Ctrl+D to exit the bash shell you just opened
docker ps -a
You will notice 4 containers. 1 for the DB, 1 for the UI, 1 for the API, and 1 for the bash
command that you just ran.
In order to fix this, you can do the following:
# Ensure all containers are stopped
docker-compose stop
# Now start up only the containers defined in docker-compose.yaml
docker-compose up -d
# Remove any dangling docker containers or resources
docker system prune
By default, Docker has a concept called Volumes. A Volume represents data that persists between instances of the application. This is the reason you can start and stop your containers without affecting your local database. Becaus the database is defined as a Volume.
If you run into a situation where you want to completely remove and rebuild all containers AND volumes, do the following:
# Ensure all containers are stopped
docker-compose stop
# Remove any dangling docker containers, resources, AND volumes
docker system prune --volumes
# Rebuild your containers
docker-compose build
docker-compose up
The official Docker-Compose documentation is very good. Feel free to check there to look into the other commands not listed here.