In the previous post I wrote about Docker and how it can be installed and used on Oracle Enterprise Linux 6. In this post we will create an Oracle Enterprise Linux 6 base image, which we can use to create other images, for example to run Oracle XE in. To use the examples in this post, you have to setup a system as described in the previous post.
1. The first step required is to download the script mkimage-yum.sh. This script can be used to create a base images for RHEL based systems. Use the url of the raw version for that:

[root@oel6-docker ~]# mkdir scripts[root@oel6-docker ~]# cd scripts/[root@oel6-docker scripts]# wget https://raw.githubusercontent.com/dotcloud/docker/master/contrib/mkimage-yum.sh
--2014-05-03 16:51:22-- https://raw.githubusercontent.com/dotcloud/docker/master/contrib/mkimage-yum.sh
Resolving raw.githubusercontent.com... 185.31.16.133
Connecting to raw.githubusercontent.com|185.31.16.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2496 (2.4K) [text/plain] Saving to: “mkimage-yum.sh”

100%[==========================================================================================>] 2,496 --.-K/s in 0s

2014-05-03 16:51:23 (59.2 MB/s) - “mkimage-yum.sh” saved [2496/2496] [root@oel6-docker scripts]# ls -l
total 4
-rw-r--r--. 1 root root 2496 May 3 16:51 mkimage-yum.sh[root@oel6-docker scripts]# chmod u+x mkimage-yum.sh

2. Copy the files /etc/yum.conf and /etc/yum.repos.d/public-yum-ol6.repo to the same scripts directory:
[root@oel6-docker scripts]# cp -p /etc/yum.conf /root/scripts/[root@oel6-docker scripts]# cp -p /etc/yum.repos.d/public-yum-ol6.repo /root/scripts

3. Modify the copied configuration file yum.conf by adding the following entry to the file:

reposdir=/root/scripts/

Also change the file public-yum-ol6.repo. Change the line:

enabled=$uek

to:

enabled=0

and the line:

enabled=$uekr3

to:

enabled=0

4. Start the script mkimage-yum.sh with the following options:
[root@oel6-docker scripts]# ./mkimage-yum.sh -y /root/scripts/yum.conf oel6-base

This will start the creation of the base image and will install 184 packages. At the end the image is tarred and imported in docker:
[root@oel6-docker scripts]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
oel6-base 6.5 2b4d946816d1 5 minutes ago 495.8 MB
ubuntu latest 99ec81b80c55 9 days ago 266 MB

It’s also tested:
[root@oel6-docker scripts]# ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7f13a7059d2 oel6-base:6.5 echo success 26 minutes ago Exited (0) 26 minutes ago sleepy_hopper

5. Now that we have a base image we can use this image to create our application images. In the following example we’re going to create a container, which will be a webserver. The easiest way to do this is to create a so called Dockerfile. In this file you specify the content of your container. Take a look at the following example:
[root@oel6-docker webserver]# cat Dockerfile
FROM oel6-base:6.5

MAINTAINER Rob den Braber

RUN yum install -y httpd
RUN yum clean all
RUN echo "A simple Docker webserver" > /var/www/html/index.html

EXPOSE 80
CMD /usr/sbin/httpd -D FOREGROUND

I’ve created a directory called webserver and changed to that directory. In that directory I’ve created the file Dockerfile.
An explanation of the commands used in the Dockerfile:
FROM: sets the base image used for the rest of the instructions
MAINTAINER: The name of the maintainer of the image
RUN: Excecutes the commands behind the instruction on the current image and commits the results. The resulting commited image will be used for the next step in the Dockerfile. In our example it installs the webserver and does a cleanup of the yum cache. It also creates a file /var/www/html/index.html, which will be our homepage.
EXPOSE: informs Docker that the container will listen on specific network ports at runtime. In our case this is the webserver port (80).
CMD: The main purpose of a CMD is to provide defaults for an executing container. In our case it starts the httpd deamon with the parameter -D FOREGROUND, which means that the httpd process is started in the foreground.

6. With the docker build command and this Dockerfile we can create our new image:
[root@oel6-docker webserver]# docker build -t oel6-webserver .
Uploading context 2.56 kB
Uploading context
Step 0 : FROM oel6-base:6.5
---> 5b393d2e7219
Step 1 : MAINTAINER Rob den Braber
---> Running in 094a172b2736
---> d03f9c8f77b6
Step 2 : RUN yum install -y httpd
---> Running in abdcc23d5328
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.2.15-30.0.1.el6_5 will be installed
--> Processing Dependency: httpd-tools = 2.2.15-30.0.1.el6_5 for package: httpd-2.2.15-30.0.1.el6_5.x86_64
--> Processing Dependency: /etc/mime.types for package: httpd-2.2.15-30.0.1.el6_5.x86_64
--> Processing Dependency: apr-util-ldap for package: httpd-2.2.15-30.0.1.el6_5.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.2.15-30.0.1.el6_5.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.2.15-30.0.1.el6_5.x86_64
--> Running transaction check
---> Package apr.x86_64 0:1.3.9-5.el6_2 will be installed
---> Package apr-util.x86_64 0:1.3.9-3.el6_0.1 will be installed
---> Package apr-util-ldap.x86_64 0:1.3.9-3.el6_0.1 will be installed
---> Package httpd-tools.x86_64 0:2.2.15-30.0.1.el6_5 will be installed
---> Package mailcap.noarch 0:2.1.31-2.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
httpd x86_64 2.2.15-30.0.1.el6_5 public_ol6_latest 820 k
Installing for dependencies:
apr x86_64 1.3.9-5.el6_2 public_ol6_latest 122 k
apr-util x86_64 1.3.9-3.el6_0.1 public_ol6_latest 87 k
apr-util-ldap x86_64 1.3.9-3.el6_0.1 public_ol6_latest 15 k
httpd-tools x86_64 2.2.15-30.0.1.el6_5 public_ol6_latest 72 k
mailcap noarch 2.1.31-2.el6 public_ol6_latest 26 k

Transaction Summary
================================================================================
Install 6 Package(s)

Total download size: 1.1 M
Installed size: 3.6 M
Downloading Packages:
--------------------------------------------------------------------------------
Total 1.2 MB/s | 1.1 MB 00:00
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : apr-1.3.9-5.el6_2.x86_64 1/6
Installing : apr-util-1.3.9-3.el6_0.1.x86_64 2/6
Installing : apr-util-ldap-1.3.9-3.el6_0.1.x86_64 3/6
Installing : httpd-tools-2.2.15-30.0.1.el6_5.x86_64 4/6
Installing : mailcap-2.1.31-2.el6.noarch 5/6
Installing : httpd-2.2.15-30.0.1.el6_5.x86_64 6/6
Verifying : httpd-2.2.15-30.0.1.el6_5.x86_64 1/6
Verifying : apr-util-ldap-1.3.9-3.el6_0.1.x86_64 2/6
Verifying : apr-1.3.9-5.el6_2.x86_64 3/6
Verifying : httpd-tools-2.2.15-30.0.1.el6_5.x86_64 4/6
Verifying : mailcap-2.1.31-2.el6.noarch 5/6
Verifying : apr-util-1.3.9-3.el6_0.1.x86_64 6/6

Installed:
httpd.x86_64 0:2.2.15-30.0.1.el6_5

Dependency Installed:
apr.x86_64 0:1.3.9-5.el6_2
apr-util.x86_64 0:1.3.9-3.el6_0.1
apr-util-ldap.x86_64 0:1.3.9-3.el6_0.1
httpd-tools.x86_64 0:2.2.15-30.0.1.el6_5
mailcap.noarch 0:2.1.31-2.el6

Complete!
---> a38301a0a63b
Step 3 : RUN yum clean all
---> Running in 61082bd37e47
Cleaning repos: public_ol6_UEKR3_latest public_ol6_latest
Cleaning up Everything
---> 50b6756db7a0
Step 4 : RUN echo "A simple Docker webserver" > /var/www/html/index.html
---> Running in 58b1bbf09ef6
---> 444f79db2414
Step 5 : EXPOSE 80
---> Running in 1ddffc61cc3a
---> 95fa37a5c0ef
Step 6 : CMD /usr/sbin/httpd -D FOREGROUND
---> Running in 8faae83312b1
---> af6a014ed8c6
Successfully built af6a014ed8c6
Removing intermediate container 094a172b2736
Removing intermediate container abdcc23d5328
Removing intermediate container 61082bd37e47
Removing intermediate container 58b1bbf09ef6
Removing intermediate container 1ddffc61cc3a
Removing intermediate container 8faae83312b1

The commands in the Dockerfile are executed one after another and in the end the new image is created:

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
oel6-webserver latest af6a014ed8c6 2 minutes ago 863.1 MB
oel6-base 6.5 5b393d2e7219 9 hours ago 495.8 MB

7. We can start the image with the docker run command with some extra options:
[root@oel6-docker webserver]# docker run -d -p 5001:80 oel6-webserver
12348359b7af51d2ce552e8728e0ba0108097bba87e8e6641ace0a7aea4f4c9c

The -d option runs the container in the background and prints the new container id. The -p option maps a network port to the container. In our case it maps port 5001 to port 80 of the container.
Use the docker ps command to view the status of the container:
[root@oel6-docker webserver]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
12348359b7af oel6-webserver:latest /bin/sh -c '/usr/sbi 4 minutes ago Up 4 minutes 0.0.0.0:5001->80/tcp suspicious_ardinghelli

As show in the output the container is running. You can see the logging of the container with the docker logs command:
[root@oel6-docker webserver]# docker logs 12348359b7af
httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2 for ServerName

8. We can test our webserver with the curl command:
[root@oel6-docker webserver]# curl localhost:5001
A simple Docker webserver

If you want your webserver to available to the outside world, you must enable ip forwarding on the host that runs docker. This can be done with the following steps:
• Modify the entry net.ipv4.ip_forward in the file /etc/sysctl.conf from 0 to 1.
• Use the command sysctl -p to active the change

Start a browser and use the url: http://ip-address of your vm:5001.

Screen Shot 2014-05-10 at 09.21.29

If you need more webservers, you just start more containers, but each on a different port. So for example the next one you start, would use port 5002. And if you don’t need them any more, you just stop them. This way you can also for example a complete image with the WordPress application. There are enough examples for different configurations on the internet. And if you don’t want to create your own image, you just pull one from the Docker index.