JTI - Production
Goals
In the previous exercises, you have learned how to develop your application locally. Now, it's time to take the next step and push the code to production. This includes:
- Setting up the infrastructure.
- Creating production versions of your Docker and Compose files.
- Setting up a pipeline for CI/CD that deploys the application on a staging and production server.
Prerequisites
By now, you should have an application with Docker and Docker Compose files in a repository at gitlab.lnu.se.
Ensure you watch or follow along in the previous exercise.
1. Setting up the infrastructure
For this application to work on a server in Open Stack we need to have Docker (runtime) and Nginx (reverse proxy) installed.
Here is our cloud-init installation script for Docker (docker-install-cloud-init.yaml
).
This script has already been run on the servers you will be using, so you do not need to take any active steps with it. The information below is solely for your knowledge and understanding of how the infrastructure has been set up.
2. Docker and Docker Compose
Now, switch to the application project.
You have already created Docker and Docker Compose files. However, these are optimized for local development and not production. Now, you need to:
- Create a Dockerfile for production
- Create a Docker Compose structure for production and development
2.1 Dockerfile
Create a new Dockerfile named Dockerfile.production
and make it production-ready.
The main differences between Dockerfile
and Dockerfile.production
:
npm ci --omit=dev
to not install dev dependencies.Start by:
CMD ["node", "src/server.js"]
2.2 Docker Compose
Docker Compose files are composable. You can provide many files and they will all merge together where the last file has the highest priority. Because of this, create two new files:
docker-compose.development.yaml
docker-compose.production.yaml
In the original docker-compose
file, include everything that is common in both development and production. This includes:
- For the mongodb service
- The container name
- The image beeing useed
- For the just-task-it service
- The container name
- build context
- environment variables
- depends on mongodb
- port mapping
In the docker-compose-development.yaml
file, specify:
- volumes for development
- use .env-file for evironment variables
In the docker-compose-production.yaml
file, specify:
- volume for MongoDB in production (no need for volumes for taskit).
- NODE_ENV=production
- That you want to use
Dockerfile.production
when building taskit.
Example project - Dockerized Web Application
Environment variables
For convenience, most of the environment variables are defined in the docker.compose.yaml file. However, for development purposes, we choose to specify some in the .env file. Later, these will be set in GitLab for staging and production environments.
See Example project - docker.compose.yaml for reference.
In our .env-file, we need to specify at a minumum:
Confirm production files
You can test your production files by executing them locally but instructing Docker to run them at your staging server.
Docker will look for the environment variable DOCKER_HOST
. If found, Docker will execute its commands against that host. You should be able to:
MacOS and Linux
Windows
...where you need to change the IP to the IP of your staging server. In this case, you also need to add your private SSH key to the SSH agent using the ssh-add
command.
Don't proceed until you get everything to work. (It's a slower process to troubleshoot using the a GitLab pipeline.)