Here’s part 1 of my series of how to serve an Angular 6 SPA web application in Django, without modifying the Angular CLI generated html.
- Part 1: Configuring Django to Serve an Angular SPA
- Part 2: Running Django and Angular Auto-build Together
- Part 3: Putting it all in a Docker Container
Putting it all in a Docker Container
I use Docker for development projects as it gives me a clean development environment where I can have all my dependancies isolated from other projects and stuff running on my system.
Disclaimer: this may not be the best way to do Django and Angular in Docker. I chose this method because I wanted to have my Angular app served by Django to avoid CORS problems and just keep the architecture as close to what it’ll be in production as possible. Obviously it wouldn’t be running on Django’s runserver in production however.
Here’s how to build a docker configuration to run my Django frontend and Angular backend together in the one container.
First create a docker-compose.yml file:
version: '3'
services:
db:
image: postgres
web:
build:
context: .
dockerfile: Dockerfile
working_dir: /code
env_file:
- web_variables.env
command: sh devservers.sh
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
This docker-compose file first creates a postgresql database container and then a web container using a Dockerfile. When the container is started it runs the devservers.sh script we created in Part 2.
It mounts the current directory(the django root) to /code within the container. It then exposes port 8000 inside the container to port 8000 outside the container.
In the Dockerfile put:
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /code RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - RUN apt install nodejs WORKDIR /code ADD requirements.txt /code/ RUN pip install -r requirements.txt ADD . /code/ RUN mkdir -p /code/static WORKDIR /code/frontend RUN npm install -g @angular/cli RUN npm install RUN ng build --outputPath=/code/static
This creates a new Docker container from the Python 3 official image. It creates a /code directory in the container.
It then installs node.js as as dependancy for the Angular CLI and installs all the Django project dependancies from the requirements.txt file.
Finally to test that the environment is ready it copies in the code from the Django root, installs the Angular CLI globally, installs the Angular project dependancies and does a test build of them.
Note that in the docker-compose, we’re telling it to mount the current working directory as a volume on /code. So the /code path in the container will be replaced with the Django root from the host system.
Really this means that the lines from ADD onwards in the Dockerfile are unnecessary. However I’ve left them in there to just ensure that that we know about it at image build time if the environment won’t be ready to use.
Using the Docker environment
To start the dev servers run the following command in the Django project root:
docker-compose up -d
As your Django project root is mounted in the Docker container, any changes you make to the Django/Angular project will also be in /code in the Docker container. The Django manage.py runserver will automatically detect any changes on the Django side and recompile and serve them.
Angular build watch will detect changes to the Angular code in <Django project root>/frontend and rebuild them, putting the output SPA into /code/static where it’s served by Django’s static file serving.
If you add new files or npm dependancies to the Angular project, you’ll need to restart the web container using:
docker-compose restart web
If you add new dependancies to the Django project do a full rebuild with:
docker-compose up --build -d
In my case I actually run my dev install on a different machine than the one I write code on, so I just upload via Webstorm or PyCharm to the project root on my dev server. The changes are detected and ready to use within seconds.