Dockerizing MERN — 2021

Dockerized MERN on OpenShift — Part 2

Charlie Campbell
3 min readJun 14, 2021

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.

  1. 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/app
COPY 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.

  1. 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-network
networks:
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.

  1. Head to https://hub.docker.com and create a repository for both the project client and server Docker images.
  2. 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!

--

--