I want to describe another way to run the Highscores-Service of the #BlueCloudMirror game . In the game I use IBM Cloud Foundry apps, now I want to explore IBM Cloud Kubernetes.
Note: The #BlueCloudMirror game we @Niklas, @Harald and I made, is available as an Pattern on IBM Developer.
Let’s get started with the first step, building a container which contains the Scores-Service using Docker .
This blog post is all about building and running a docker container on a local machine.
Topics you will find in this post: my experience of learning how configure a Dockerfile along with my creation of the Dockerfile for the score-service, including following steps:
- Choosing the base image
- Installing the needed packaging tools
- Defining the source code location and copying the source code into the container
- Configuring a new user and group for Bower , a package manager
- Setting up the Score-Service
- Running the Score-Service container locally
Note: This is not a blueprint, this is just how I did it and I share my experience with you.
Architecture of the Scores-Service
This is the relevant architecture for building the Docker container. The Scores-Service UI and the Scores Core Service will run in the Docker container locally. The Cloudant service still runs on IBM Cloud.
Choosing the base docker image
I haven’t done much research, which Node image on Dockerhub fits best to my requirements. Usually search is what you should do first and this is known as a best practice for using containers to reduce your maintenance effort in the future.
My decision was to build the container image from scratch and I chose the open source centos as my starting point for the container.
The following steps describe: How to create the Dockerfile in detail
Get started with the first line in the Docker file, build the container based on the centos image with the FROM instruction.
FROM centos
Installing the needed packaging tools
These are the tools I need to run my scores-service inside the container:
- Node
- Bower (because, I am using this package manager for the scores-service UI )
- Git for the installation
- Scores-service application source code.
I configure the execution of the download with RUN and installation of Node.js and git.
RUN curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
RUN yum install -y nodejs
RUN yum install -y git
Defining the source code location and copying the source code into the container
Now I create the directories I need for my source code inside the image.
The folder public contains the scores-service UI and the app folder contains the scores-core-service.
# setup folder structure in centos
# service (node server)
RUN mkdir usr/app
# webapplication
RUN mkdir usr/app/public
RUN mkdir usr/app/public/lib
Then I COPY
the source code from the local machine into the defined directories.
As you can see, I use more then needed copy statements, because I want to highlight some of the files inside the app folder for myself s.
The .env file contains Cloudant access information for the scores-core-service.
I decided not to use ENV in the Dockerfile and refine all environment variables already defined in the .env file.
# Bundle app source
COPY ./public /usr/app/public
RUN ls
COPY ./server.js /usr/app
COPY ./.cfignore /usr/app
COPY ./highscore_view.json /usr/app
COPY ./sampledata.json /usr/app
COPY ./score_index.json /usr/app
COPY ./manifest.yml /usr/app
COPY ./.env /usr/app
Configuring a new user and group for a package manager
During the installation of bower modules, Bower uses the folder public/lib. Bower is not allowed be executed as root. When you use the instruction RUN in a Dockerfile, by default the root user is used.
Bower needs rights to create or change folders.
So, I need to add a user and give him rights to the folders.
By the way, I install the needed Bower modules in the folder called lib and not to the default folder bower_components.
I add a user called bower and provide him specific rights to access folders . I found the easiest way to provide the rights was defining a user group and giving the group access to the needed folders.
# create group and user
RUN groupadd installer
RUN useradd -ms /bin/bash bower --group installer
# set user rights to allow the bower user to setup custom lib folder
RUN chown -R bower:installer usr
RUN chown -R bower:installer usr/app
RUN chown -R bower:installer usr/app/public
RUN chmod g+rwX usr/app/public
RUN chmod g+rwX usr/app
RUN chmod g+rwX usr
Setting up the score-service
To setup the scores-core-service I set the working directory to execute commands from the /usr/app
with WORKDIR
. Then I copy the npm package.json, and I install the modules for the scores-core-service with the npm package manager .
# Install app npm dependencies
WORKDIR /usr/app
COPY ./package.json /usr/app
RUN npm install
The setup of the scores-core-service is done. Only the scores-service UI setup is missing.
As you know, I am using bower package manager to setup the scores-service UI.
In the following steps, I install bower and copy the needed configuration files into the image. Then I change the USER
and run bower install .
# Create app directory
WORKDIR /usr/app
# install bower
RUN npm install --global bower
# Install app bower dependencies
COPY ./bower.json /usr/app
COPY ./.bowerrc /usr/app
USER bower
RUN bower install
The few remaining steps are:
- Defining the port which the container should
EXPOSE
. I define my port inside the server.js file line 57 var port = process.env.PORT || 3000; . - Defining the default execution at the startup of the container. To start the node server at the startup of container I use the command
CMD
.
Dockerfile steps:
# Server listens on
EXPOSE 3000
CMD [ "npm", "start" ]
For now the score-core-service and score-service UI setup in the Dockerfile is done.
To access the Cloudant database the .env file I copied before, which contains the information for the score-core-service.
Note: The .env file is not a part of the git repository, because normally I create the values with a bash script automatically and it contains keys, which should not be saved inside the github source code.
Here is a sample for the .env file.
# CF APP
SERVICE_USER=admin
SERVICE_PASSWORD=a12345678
BASE_PATH=/scores-service
# CLOUDANT
CLOUDANT_NAME=blue-cloud-mirror-scores-service-db
CLOUDANT_DES_SCORES=_d_scores
CLOUDANT_IDX_SCORES=_idx_scores
CLOUDANT_DES_HIGHSCORE=_d_highscores
CLOUDANT_IDX_HIGHSCORE=_v_highscores
CLOUDANT_USERNAME=XXXXX
CLOUDANT_PASSWORD=XXXXX
CLOUDANT_URL=https://XXXXX-bluemix.cloudantnosqldb.appdomain.cloud
CLOUDANT_PORT=443
SERVICE_URL=
Running the score-service container locally
The last remaining steps are building, running, and using this docker image locally.
- Build it
- Run it
- Use it
Build a container with the tag v1.
docker build -t scores-service:v1 .
Now run the container exposing port 3000 to the local machine.
docker run -d -p 3000:3000 scores-service:v1
Now the scores-service is running the container is locally available on http://localhost:3000 .
I hope this was useful for you and let’s see what’s next?
Greetings,
Thomas
FYI: You can find the next step here: How to deploy a container to the IBM Cloud Kubernetes Service.
PS: By the way, you can use the IBM Cloud for free, if you simply create an IBM Lite account. Here you only need an e-mail address.
#BlueCloudMirror, #Docker #Container, #Bower, #IBMDeveloper