In this article, you’ll learn how to prepare an Angular app for production deployment using Docker.
This post is part of the Dockerized Django Back-end API with Angular Front-end Tutorial. Check out all the parts of the tutorial there.
In the last part of the tutorial, we’ve learned how to prepare a Django DRF API for production in Docker. In this blog post, we’ll learn how to prepare our Angular app for deployment in a production environment using Docker.
To get the code to where we left off in the last blog post, use:
$ git checkout v1.15
Environment Files and Variables in Angular
First of all, I want to talk (OK, write) a bit about the idea of environments. When developing an app, you should have a minimum of two environments, such as one for development and one for production.
The Angular CLI supports the concept of environments.
When you create a new app, you’ll find under the src
directory an environments
directory. By default, two environment files are created:
environment.ts
– used for development (within it, the production
variable is set to false
)
environment.prod.ts
– used for production (within it, the production
variable is set to true
)
Now, do you remember how our Angular app accesses the Django API? It’s using the ApiService
service found in angular/angular-app/src/api.service.ts
.
In this file, we store the API URL that’s served by the Django back-end:
API_URL = 'http://localhost/api';
For development, this URL is fine, but in a production setting we need to point the URL to a domain name or IP address instead of localhost
.
Therefore, let’s add a new apiUrl
variable in our environment files to specify the API URL for our development and production cases, respectively.
Edit src/environments/environment.ts
and add the apiUrl
variable as follows:
Next, do the same for the production environment file src/environments/environment.prod.ts
, but also add the auth
variable:
Here you should replace <YOUR-DOMAIN-OR-IP-ADDRESS>
with the corresponding location where you’ll host the API. I will replace this with the IP address of the Google Cloud Platform instance on which we’ll deploy our stack in a future post.
Using Environment Variables in Angular
Next, we’ll see how we can use the apiUrl
variable in our Angular code.
Edit the angular-app/src/api.service.ts
file as follows:
Wherever we want to use environment variables, we import the environment file in our code. The Angular CLI will know how to select the correct environment file when we build the app.
Building the Angular App in a Production Configuration
We’re now ready to actually build the Angular app for deployment.
To do this, you can simply build the app with the production configuration:
$ ng build --prod
The production flag --prod
has a few important functions such as merging your application files in a few bundles, removing comments and excess whitespace, and rewriting the code to use short, cryptic variable and function names.
Also, the production flag will tell Angular to use the production environment file, so API_URL
will resolve to http://<YOUR-DOMAIN-OR-IP-ADDRESS>/api
when building with --prod
.
Building the Angular app in Docker
We don’t really want to just use ng build --prod
blindly as we’re not keeping track of the build environment in which we’re setting up the app.
To make sure that build environments are reproducible, we want to use Docker.
Let’s go to our angular/Dockerfile
file we’ve created way back in part 3 of the tutorial and change the build step as follows:
Here, we’re using configuration
as a build-time variable using the ARG
instruction.
As you can see, configuration
is set to production
by default.
Next, we pass the configuration
variable to our npm run build
command. This will build the app using the provided configuration.
The nice thing about ARG
variables is that you can pass different values when you’re building the Docker image from the command-line using the --build-arg
option like so:
$ docker build --build-arg some_variable_name=the_given_value
Therefore, if you want to build the app in the production configuration, you’d use:
docker build --build-arg configuration=production
If you want to build the app in the development configuration, you can just pass an empty value like so:
docker build --build-arg configuration=""
Lastly, you can also supply these variables using docker-compose
.
Copying the Angular Files Locally
Now that we can build the Angular app in the Docker container, let’s also copy the built files from the container to our local filesystem.
To do this, we can use the command docker cp
that has the following format:
docker cp <containerId>:/file/path/within/container /host/path/target
If you now start the containers using docker-compose up
, you can copy the Angular files locally using something like:
$ docker cp ng:/usr/share/nginx/html/. /Users/dragos/static_angular
Here, we’re getting the files from the ng
container, namely from NGINX’s HTML directory where the app files are found, and we’re copying them to a directory on the host, in the above example to /Users/dragos/static_angular
.
The next step would be to upload these files to a server.
In a later blog post we’ll see how we can serve these files from a Google Cloud Storage bucket.
Bonus: Adding a Staging Environment
I thought it would be useful to also include information on how to add a staging environment.
To include a new environment, open the angular-app/angular.json
file. In the configurations
key, you can see the default production
configuration.
Now, you can just replicate the production
configuration with a new configuration such as one named staging
:
Next, in the environments
directory, create a environment.staging.ts
file with the contents similar to environment.prod.ts
:
Lastly, to build the app using the staging
configuration just use:
$ ng build --configuration=staging
And that’s it!
To get the code to this stage, see my git commit or use:
$ git checkout v1.16
Just so you know, I haven’t included the extra staging
configuration in the repository, so follow the steps above if you want that configuration.
Summary
In this part of the tutorial, we’ve learned how to prepare an Angular app for deployment in a production environment using Docker. We’ve covered the Angular CLI’s environment files and we’ve seen how to build the app for production in a reproducible manner using Docker.
In the next part of the tutorial, we’ll start working on deploying our Docker container on Google Cloud Platform.
Credit: For this tutorial, I’ve used the following resources: