Assume you are building a microservices system that comprises a Node JS server, Mongo database, and nginx for load balancing.
version: "3"
services:
nginx:
image: nginx:stable-alpine
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- veezo
veezo:
build: .
image: veestram.azurecr.io/levelupjs-backend_veezo
environment:
- PORT=4000 # this is the port our node app will be listening to in the docker container, so if we direct traffic here, our node app will be accessed
depends_on:
- mongo
mongo:
image: mongo:4.4.18
volumes:
- mongo-db:/data/db #here we are saying we want to persist this data. the path is where data is stored
volumes:
mongo-db:
Your base docker-compose file might look something like the above.
Then you’d have a production docker-compose file as shown below.
version: "3"
services:
nginx:
ports:
- "80:80"
- "443:80"
veezo:
build:
context: .
args:
NODE_ENV: production
environment:
- NODE_ENV=production
- AZURE_CONNECTION_STRING=${AZURE_CONNECTION_STRING}
- MONGO_USERNAME=${MONGO_USERNAME}
- MONGO_PASSWORD=${MONGO_PASSWORD}
- MONGO_IP=${MONGO_IP}
- MONGO_PORT=${MONGO_PORT}
- MONGO_DATABASE=${MONGO_DATABASE}
command: node index.js
mongo:
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
One possible development to production workflow would be.
Pushing the code to GitHub, logging in to your production server, and pulling the code changes from Github, rebuilding the image.
However, this is not a good practice. Your production server shouldn’t waste any CPU and memory in building images. It's a bad practice to build images in your production server.
A better approach would be building the image on the local machine, pushing it to a container registry, and pulling the image into the production server. For that, we have to make some changes in our docker-compose.yml.
veezo:
build: .
image: veestram.azurecr.io/levelupjs-backend_veezo
Add the image property specifying the name of the image from your container registry. I have used the Azure container registry.
Here are the steps for building the image locally and pushing it to the registry.
docker-compose -f docker-compose.yml -f docker-compose.prod.yml build veezo
docker login veestram.azurecr.io #login to your registry
docker image tag image:tag veestram.azurecr.io/image:tag # tag the image with your account info
docker push veestram.azurecr.io/image:tag #push the image to the registry
After the image is pushed to the registry, log in to your production server and pull the image, then restart the container.
docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps veezo
That way, our server does not use up CPU and memory in building images.