Dockerizing MERN — 2021
Dockerized MERN on OpenShift — Part 2
In part one of this series you have learnt to install OpenShift and Docker on a Ubuntu instance. This part will cover Dockerizing an existing MERN stack and pushing the images to DockerHub ready to be deployed to OpenShift.
Prerequisites
- Basic command line knowledge
- Basic Docker understanding
- A Docker account
Setting up a MERN application
There are plenty of guides out there on how to setup a MERN stack, so I won’t be covering that here. I will however recommend the following guide by Sam Barrows: https://medium.com/swlh/how-to-create-your-first-mern-mongodb-express-js-react-js-and-node-js-stack-7e8b20463e66
Dockerizing MERN — Server
Now let’s get stuck in. Assuming you’ve got Docker set up on your machine it is time to create a Dockerfile for each ‘instance’. We will start by creating a Dockerfile for the node.js server.
- Create a new file in the server directory
cd <project_name>
cd server/
touch Dockerfile
2. Populate the Dockerfile as follows:
FROM node:15.12-alpineRUN mkdir -p/usr/src/app
WORKDIR /usr/src/appCOPY package*.jsonRUN npm install --silentCOPY . .EXPOSE 3000CMD["npm", "start"]
3. Build and tag the server image
docker build -t <project_name>_server:<project_version> .
i.e.
docker build -t demo_server:v0.1.0
4. Verify that the docker images has built correctly
docker images
Expect a response similar to:
> REPOSITORY TAG ....
<project_name>_server <project_version> ....
Dockerizing MERN — Client
Now we will create the Dockerfile for the React client.
1.Create a new file in the client directory
cd <project_name>
cd client/
touch Dockerfile
2. Populate the Dockerfile as follows:
FROM node:15.12-alpineWORKDIR /usr/src/appCOPY package*.jsonRUN yarn install --silentCOPY . .EXPOSE 8000CMD["yarn", "start"]
3. Build and tag the client image
docker build -t <project_name>_client:<project_version> .
i.e.
docker build -t demo_client:v0.1.0
4. Verify that the docker image has built correctly
docker images
Expect a response similar to:
> REPOSITORY TAG ....
<project_name>_server <project_version> ....
<project_name>_client <project_version> ....
5. Check that the image runs locally on port 3000 with:
docker run -p 3000:3000 demo_server:v0.1.0
or in my case…
> REPOSITORY TAG ....
demo_server v0.1.0 ....
demo_client v0.1.0 ....
5. Check that the image runs locally on port 8000 with:
docker run -p 8000:8000 demo_client:v0.1.0
Creating a docker-compose file to run both images
Now that we have created and tested both our Dockerfiles we can run both simultaneously and get them talking to eachother with docker-compose.
- Create a file in the project repository (outside of client and server)
touch docker-compose.yml
2. Populate the docker-compose.yml file as follows:
version: '3.8'services:
server:
build:
context: ./server
dockerfile: Dockerfile
image: <project_name>-server
container_name: <project_name>-node-server
command: /usr/src/app/node_modules/.bin/nodemon server.js
volumes:
- ./server/:usr/src/app
- /usr/src/app/node_modules
ports:
- "3000:3000"
depends_on:
- mongo
environment:
- NODE_ENV=development
networks:
- app-network mongo:
image: mongo
container_name: <project_name>-mongo
volumes:
- data-volume:/data/db
ports:
- "27017:27017"
networks:
- app-network
restart: always client:
build:
context: ./client
dockerfile: Dockerfile
image: <project_name>-client
container_name: <project_name>-react-client
command: yarn start
volumes:
- ./client/:/usr/app
- /usr/app/node_modules
depends_on:
- server
ports:
- "8000:8000"
networks:
- app-networknetworks:
data-volume:
node_modules:
web-root:
driver: local
3. Build and run the docker containers using the follow command:
docker-compose build
docker-compose up
Pushing Docker Images to DockerHub
Now that we have built and tested our images and have a successful docker-compose configuration it’s time to push our containers to DockerHub.
- Head to https://hub.docker.com and create a repository for both the project client and server Docker images.
- Login to Docker in the CLI
docker login
Note: Enter your username and password as requested
3. Push both the Docker client and server images
docker push <docker_id>/<project_name>_server:<project_version>
docker push <docker_id>/<project_name>_client:<project_version>
or in my case…
docker push charliecampbell/demo_server:v0.1.0
docker push charliecampbell/demo_client:v0.1.0
4. Verify that the images have been successfully pushed in the DockerHub UI
Now that we have the Docker images on DockerHub we can start looking at pushing these to OpenShift and running something live!