Besides images and containers, Docker has a third very important term called a Dockerfile. A Dockerfile is like a process on how to create an environment for a specific application, which means that it contains the blueprint and exact description of how to build a specific image file. For example, if we would like to containerize a webserver-based application, we would define all the dependencies for it, such as the base Linux system that provides the system dependencies such as Ubuntu, Debian, CentOS, and so on (this does not mean we virtualize the complete operating system but just use the system dependencies), as well as all applications, dynamic libraries, and services such as PHP, Apache, and MySQL in the Dockerfile and also all special configuration options or environment variables. There are two ways to build your own custom images. One, you could download an existing base image as we did in the previous Wordpress process and then attach to the container using BASH, install your additional software, make the changes to your configuration files, and then commit the container as a new image to the registry. Alternatively, here in this process, we will teach you how to build your own Docker image from a new Dockerfile for an Express.js web application server and upload it to your own Docker Hub account.
To Start With: What Do You Need?
To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to communicate with the Docker Hub. It is expected that Docker is already installed and is running. Also, for uploading your new image to the Docker Hub, you need to create a new Docker Hub user account there. Just go to https://hub.docker.com/ and register there for free. In our example, we will use a fictitious new Docker Hub user ID called johndoe.
The Process
- To begin, log in as root and create a new directory structure using your Docker Hub user ID (substitute the johndoe directory name appropriately with your own ID), and open an empty Dockerfile where you put in your image’s building blueprint:
mkdir -p ~/johndoe/centos7-expressjs
cd $_; vi Dockerfile - Put in the following content into that file:
FROM centos:centos7
RUN yum install -y epel-release;yum install -y npm;
RUN npm install express --save
COPY . ./src
EXPOSE 8080
CMD ["node", "/src/index.js"] - Save and close the file. Now create your first Express.js web application, which we will deploy on the new container. Open the following file in the current directory:
vi index.js
- Now put in the following JavaScript content:
var express = require('express'), app = express();
app.get('/', function (req, res) {res.send('Hello CentOS 7
cookbook!\n');});
app.listen(8080); - Now to build an image from this Dockerfile, stay in the current directory and use the following command (don’t forget the dot at the end of this line and replace johndoe with your own Docker Hub ID):
docker build -t johndoe/centos7-expressjs .
- After successfully building the image, let’s run it as a container:
docker run -p 8081:8080 -d johndoe/centos7-expressjs
- Finally, test if we can make an HTTP request to our new Express.js web application server running in our new container:
curl -i localhost:8081
- If the Docker image is successfully running on the Express.js server, the following HTTP response should occur (truncated to the last line):
Hello CentOS 7 cookbook!
Uploading your image to the Docker Hub
- After creating a new Docker Hub account ID called johndoe, we will start to login to the site using the following command—stay in the directory where you put your Dockerfile from the last step–for example ~/johndoe/centos7-expressjs (provide the username, the password, and the registration e-mail when asked):
docker login
- Now, to push your new image created in this process to the Docker Hub (again replace johndoe with your own user ID), use:
docker push johndoe/centos7-expressjs
- After uploading, you will be able to find your image on the Docker Hub web page search. Alternatively, you can use the command line:
docker search expressjs
How Does It Work?
Here in this short process, we showed you how to create your first Dockerfile which will create a CentOS 7 container to serve Express.js applications, which is a modern alternative to LAMP stacks where you program JavaScript on the client-and server-side.
So what did we learn from this experience?
As you can see, a Dockerfile is an elegant way to describe all the instructions on how to create an image. The commands are straight-forward to understand and you use special keywords to instruct Docker what to do in order to produce an image out of it. The FROM command tells Docker which base image we should use. Fortunately, someone has already created a base image from the CentOS 7 system dependencies (this will be downloaded from Docker Hub). Next, we used the RUN command, which just executes commands as on a BASH command-line. We use this command to install dependencies on our system in order to run Express.js applications (it’s based on the Node.js rpm package which we access by installing the EPEL repository first). The COPY command copies files from our host machine to a specific location on the container. We need this to copy our index.js file which will create all our Express.js web server code in a later step on to the container. EXPOSE, as the name implies, exposes an internal container port to the outside host system. Since by default Express.js is listening on 8080, we need to do this here. While all these commands shown up to this point will only be executed once when creating the image, the next command CMD will be run every time we start the container. The command node /src/index.js will be executed and instructs the system to start the Express.js web server with the index.js file (which we already provided in this directory by copying it from the host machine). We don’t want to go into any details about the JavaScript part of the program—it just handles HTTP GET requests and returns the Hello World string. In the second part of this process, we showed you how to push our new created image to the Docker Hub. In order to do so, login with your Docker user account. Then we can push our image to the repository.
As this is a very simple Dockerfile, there is much more to learn about this subject. To see a list of all the commands available in the Dockerfile, use man Dockerfile. Also, you should visit the Docker Hub and browse the Dockerfiles (under the section Source Repository hosted on GitHub) of some interesting projects to learn how to create some highly sophisticated image files with just a handful of commands on your own.