Getting Started with Docker on Oracle Linux

Version 6

    by Ginny Henningsen

     

    Learn how to customize a Docker container image and use it to instantiate application instances across different Linux servers. This article describes how to create a Dockerfile, how to allocate runtime resources to containers, and how to establish a communication channel between two containers (for example, between web server and database containers).

     

    Introduction

     

    The best system administrators I know are downright lazy. I mean "lazy" in a good way, though—they're experts at finding ways to work smarter, not harder. They're skilled at discovering new techniques and technologies that help them efficiently manage operations. It's no surprise that many of them are excited about Docker, an open source virtualization technology that creates lightweight Linux application containers.

     

    Docker is exciting because it can easily capture a full application environment into a virtual container that can be deployed across different Linux servers. System administrators and software developers are learning that Docker can help them deploy application images on Linux quickly, reliably, and consistently—without dependency and portability problems that can inject delays into planned deployment schedules. Docker containers can define an application and its dependencies using a small text file (a Dockerfile) that can be moved to different Linux releases and quickly rebuilt, simplifying application portability. In this way, "Dockerized" applications are easily migrated to different Linux servers where they can execute on bare metal, in a virtual machine, or on Linux instances in the cloud.

     

    Developers love Docker because they can capture the full software environment, including dependencies, and replicate it easily for testing. Administrators love it because it simplifies the task of deploying applications without having to worry about the configuration nuances of the target system. If you're already an Oracle Linux Premier Support customer, you'll love the fact that Oracle provides support for Docker application containers on Oracle Linux automatically, at no additional cost.

     

    This article is designed to help you get a taste for how you can use Docker to simplify application provisioning on Linux. It demonstrates how to create a Docker container on Oracle Linux, modify it, and use it to instantiate multiple application instances. It also describes how to allocate system CPU and memory resources to a Docker container, how to set up a database container, and how other containers can connect to that database container. Because the Docker test environment that I created runs on Oracle Linux, this article also shows to use Ksplice to update the kernel without rebooting—while all of the Docker application containers continue to run.

     

    Docker Lightweight Virtualization Containers

     

    Docker containers are a lightweight virtualization technology for Linux. They provide isolation from other applications and processes running on the same system but make system calls to the same shared Linux kernel, similar to Linux LXC application containers. If you have a background in Oracle Solaris, Docker containers might remind you of non-global zones in Oracle Solaris 10 or 11, which provide application isolation while sharing an underlying Oracle Solaris operating system kernel. Docker containers have their own namespace, so they are fully isolated from one another—processes running in one container can't see or impact processes running in another. By default, each container gets its own networking stack, private network interfaces, and IP address, and Docker creates a virtual bridge so containers can communicate.

     

    Shared container access to the underlying Linux kernel is one reason why Docker containers are deemed lightweight. When a Docker image is modified, the new container shares the same binaries and libraries as the base container, which contributes to a smaller overall footprint (Figure 1). In building and customizing containers, Docker also uses the concept of layering, storing only differences from the base container.

     

    f1.gif

    Figure 1. Docker containers versus hypervisor-based virtualization.

     

    As shown in Figure 1, Docker containers consume fewer resources than "heavyweight" hypervisor-based solutions. Hypervisor-based solutions host a full-blown operating system instance in each virtual machine guest, but this also allows them to support different operating systems. (Oracle VM, for example, can host Oracle Linux, Oracle Solaris, and Microsoft Windows in virtual machines.)

     

    Getting Started

     

    In Figure 1, the Linux host runs the Docker Engine, a service that packages, manages, and executes Docker containers. To use Docker, the first step is to download and install the Docker Engine RPM packages. Oracle publishes Docker Engine RPMs for Oracle Linux 6 and Oracle Linux 7 on the public yum site and on the Unbreakable Linux Network (ULN).

     

    Instructions for installing the Docker Engine are available in the Oracle Linux 6 Docker User's Guide, the Oracle Linux 7 Docker User's Guide, or in Avi Miller's blog article, "Ahoy! Cast Off with Docker on Oracle Linux". The initial steps are pretty simple: first enable the add-ons channel in /etc/yum.repos.d/public-yum-ol*.repo and then run yum install docker.

     

    The resources above also describe how to configure Docker to use the Btrfs file system for storing container images. Because Btrfs has built-in snapshot capabilities, it is fast and efficient when replicating Docker container layers.

     

    After configuring Docker to use Btrfs, initialize the Docker Engine service:

     

    [root@ol7-host ~]# systemctl enable docker
    [root@ol7-host ~]# systemctl start docker

     

     

    The Docker Hub Registry (Figure 2) is a public cloud store of images hosted by Docker, Inc. that can be used to build running containers. Repositories provide a mechanism for Docker image distribution and sharing. Docker, Inc. also hosts private repositories for a monthly fee. Alternatively, you can create a private Docker Registry behind your own corporate firewall, implementing protection mechanisms, such as SSL encryption and HTTP authentication, to restrict and protect access.

     

    f2_small.gif

    Figure 2. The Docker Hub Registry stores preconfigured container images.

     

    The following commands pull the Oracle Linux 6 and Oracle Linux 7 images from the public Docker Hub Registry, downloading them to the Oracle Linux host that's my test environment:

     

    [root@ol7-host ~]# docker pull oraclelinux:6
    Pulling repository oraclelinux 68f3f88739c9: Pulling dependent layers  511136ea3c5a: Download complete  ad98bd7101f2: Download complete  Status: Downloaded newer image for oraclelinux:6 [root@ol7-host ~]# docker pull oraclelinux:7
    Pulling repository oraclelinux  3200155fe586: Download complete   511136ea3c5a: Download complete   ad98bd7101f2: Download complete   fa5a10a28322: Download complete   Status: Downloaded newer image for oraclelinux:7

     

     

    If no version number is specified in the docker pull command, then the latest available version is pulled from the Docker Hub repository (for example, at the time of this publication, the latest Oracle Linux version is actually Oracle Linux 7.1).

     

    Oracle also publishes Docker container images for its verified version of MySQL on the public Docker Hub Registry (note that docker pull mysql will pull the Ubuntu version of MySQL):

     

    [root@ol7-host ~]# docker pull mysql/mysql-server
      Pulling repository mysql/mysql-server  296ef3e8959e: Download complete      32 B/32 B: Download complete   ad98bd7101f2: Download complete   8f0a27825a9a: Download complete   c94023a2b919: Download complete   92af7065aa1f: Download complete    a81965d5ac77: Download complete   be7d80f12dd8: Download complete   54c55eca1c4c: Download complete   45dd68192dba: Download complete   d8aaad0b9379: Download complete   Status: Downloaded newer image for mysql/mysql-server:latest

     

     

    The command docker images lists the images available locally that I can run and customize:

     

    [root@ol7-host ~]# docker images
      REPOSITORY          TAG            IMAGE ID            CREATED             VIRTUAL SIZE  mysql/mysql-server  latest         461d07d927e6        10 days ago         283 MB  oraclelinux         6.6            68f3f88739c9        4 weeks ago         161.9 MB  oraclelinux         6              68f3f88739c9        4 weeks ago         161.9 MB  oraclelinux         7              3200155fe586        5 weeks ago         195.1 MB  oraclelinux         7.0            3200155fe586        5 weeks ago         195.1 MB  oraclelinux         latest         3200155fe586        5 weeks ago         195.1 MB

     

     

    Customizing a Container for Application Provisioning

     

    Suppose that I want to provision multiple, identical web servers across multiple Linux servers in my data center. Docker makes it easy to create a preconfigured, cookie-cutter environment in a container image. I can then use this prebuilt image and deploy it across one or many Linux hosts.

     

    To build a customized container image, I must first build a guest container, install the web server, and configure it to deliver web server content. I use the docker run command to run an Oracle Linux 7 base container and execute a bash shell in the guest container:

     

    [root@ol7-host ~]# docker run -i -t --name guest oraclelinux:7 /bin/bash 
    [root@f85d55a6893f /]# 

     

     

    The Docker Engine assigns an image ID to every running container instance. Because I used the arguments -i and -t, the bash shell runs interactively, and the prompt reflects the first 12 characters (f85d55a6893f) of my running container's image ID. The --name argument specifies a name for the running container instance. (If you choose not to enter a name, the Docker Engine generates a random string that incorporates the name of a notable scientist, inventor, or developer, such as evil_jones; sad_ritchie; sleepy_curie; and prickly_mestorf).

     

    In a shell on my Linux host, the docker ps command shows information about the running guest container, including the shortened form of the image ID, the base image used to create this container, and the container name:

     

    [root@ol7-host ~]# docker ps
    CONTAINER ID  IMAGE          COMMAND      CREATED          STATUS         PORTS  NAMES f85d55a6893f  oraclelinux:7  "/bin/bash"  28 seconds ago   Up 28 seconds         guest

     

     

    On the guest, I install the httpd and perl RPM packages using yum, just as I would on any other physical or virtual server. I also specify yum clean all to remove cache files that yum creates during package installation, because that will ultimately save some space in the exported container image:

     

    [root@f85d55a6893f /]# yum install -y httpd perl && yum clean all
    ol7_UEKR3                                                    | 1.2 kB  00:00:00      ol7_latest                                                   | 1.4 kB  00:00:00      (1/5): ol7_UEKR3/x86_64/updateinfo                           |  24 kB  00:00:00  (2/5): ol7_latest/x86_64/group                               | 652 kB  00:00:01      (3/5): ol7_latest/x86_64/updateinfo                          | 348 kB  00:00:01      (4/5): ol7_UEKR3/x86_64/primary                              | 6.2 MB  00:00:05      (5/5): ol7_latest/x86_64/primary                             | 8.4 MB  00:00:06     ol7_UEKR3                                                                   149/149  ol7_latest                                                                9226/9226  Resolving Dependencies  . . .  Installed:     httpd.x86_64 0:2.4.6-31.0.1.el7   perl.x86_64 4:5.16.3-285.el7 Dependency Installed:    apr.x86_64 0:1.4.8-3.el7                            apr-util.x86_64 0:1.5.2-6.0.1.el7                 httpd-tools.x86_64 0:2.4.6-31.0.1.el7             . . .                   Complete!  Cleaning repos: ol7 UEKR3 ol7_latest Cleaning up everything

     

     

    At this point, I can configure content for the web server to display. For simplicity, I'll create a basic opening page in the /var/www/html hierarchy on the guest:

     

    [root@f85d55a6893f /]# echo "Example Web Server Content" > /var/www/html/index.html

     

     

    My guest container is now configured with the software environment that I want. Typing exit stops the running guest, returning a prompt for the Linux host:

     

    [root@f85d55a6893f /]# exit
    exit  [root@ol7-host ~]#

     

     

    Now I want to create a new Docker image that reflects the contents of the guest container that I just configured. The following docker commit command captures the modified container into a new image named mycon/httpd:r1:

     

    [root@ol7-host ~]# docker commit -m "OL7-httpd" `docker ps -l -q` mycon/httpd:r1
    2fb1c664f394a9b2c5b9fbe2138754adc2c63fe4bdd1715bfbcebf0147981b3d

     

     

    The commit command takes as input the image ID number of the guest container (f85d55a6893f, returned from the docker ps -l -q command) and assigns and returns an ID number for the new image. Running the docker images command now lists the new image, mycon/httpd, along with the Oracle Linux and MySQL images I pulled earlier from the public registry:

     

    [root@ol7-host ~]# docker images
    REPOSITORY          TAG      IMAGE ID          CREATED              VIRTUAL SIZE  mycon/httpd         r1       2fb1c664f394      About a minute ago   414.9 MB  mysql/mysql-server  latest   461d07d927e6      10 days ago          283 MB  . . .  

     

     

    Now that I've built a new Docker image from the guest container, I no longer need the guest container:

     

    [root@ol7-host ~]# docker rm guest

     

     

    Because Docker containers persist even though they're no longer running, removing unneeded containers is simply a housekeeping step to reduce clutter on my host, and it allows me to reuse the name guest for a new container.

     

    Deploying the Configured Docker Image

     

    I can deploy any number of web servers now using the new Docker image as a template. The following docker run commands run the container image mycon/httpd, creating the containers guest1, guest2, and guest3 and executing httpd in each one:

     

    [root@ol7-host ~]# docker run -d --name guest1 -p 8080:80 mycon/httpd:r1 \
    /usr/sbin/httpd -D FOREGROUND
    [root@ol7-host ~]# docker run -d --name guest2 -p 8081:80 mycon/httpd:r1 \
    /usr/sbin/httpd -D FOREGROUND
    [root@ol7-host ~]# docker run -d --name guest3 -p 8082:80 mycon/httpd:r1 \
    /usr/sbin/httpd -D FOREGROUND

     

     

    The -p argument maps port 80 in each guest to ports 8080, 8081, or 8082 on the host. The docker ps command shows the running guests:

     

    [root@ol7-host ~]# docker ps
    CONTAINER ID IMAGE          COMMAND             CREATED       STATUS       PORTS NAMES  af521fe5c96f mycon/httpd:r1 "/usr/sbin/httpd -D 5 seconds ago Up 4 seconds 0.0.0.0:8082-> 80/tcp guest3 e6320d4adf50 mycon/httpd:r1 "/usr/sbin/httpd -D 8 seconds ago Up 9 seconds 0.0.0.0:8081-> 80/tcp guest2 603c6d5db100 mycon/httpd:r1 "/usr/sbin/httpd -D 2 minutes ago Up 2 minutes 0.0.0.0:8080-> 80/tcp guest1

     

     

    The default IP address value of 0.0.0.0 means that the port mapping applies to all network interfaces on the host. To access the running guest containers, you might need to enable firewall access first. On an Oracle Linux 7 host, I can use firewall-cmd (rather than using iptables, as you would for Oracle Linux 6):

     

    [root@ol7-host ~]# firewall-cmd --add-port=8080/tcp --add-port=8081/tcp --add-port=8082/tcp
    success

     

     

    Using a web browser or curl, I can test the web server running in each guest:

     

    [root@ol7-host ~]# curl http://ol7-host:8080
    Example Web Server Content  [root@ol7-host ~]# curl http://ol7-host:8081
    Example Web Server Content  [root@ol7-host ~]# curl http://ol7-host:8082
    Example Web Server Content

     

     

    Docker containers can communicate to other containers and hosts through a virtual bridge created by the Docker Engine. By default, the virtual bridge is named docker0 and assigned a random IP address from a range not in use on the host:

     

    [root@ol7-host ~]# ifconfig -a
    docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500          inet 172.17.42.1  netmask 255.255.0.0  broadcast 0.0.0.0          inet6 fe80::5484:7aff:fefe:9799  prefixlen 64  scopeid 0x20<link>          ether 56:84:7a:fe:97:99  txqueuelen 0  (Ethernet)          .          .          .

     

     

    The Docker Engine also assigns each running container a virtual network interface, which you can see with the docker inspect command:

     

    [root@ol7-host ~]# docker inspect -f '{{ .NetworkSettings.IPAddress }}' guest1
    172.17.0.2

     

     

    Publishing and Porting

     

    I can now easily move my web server container to another machine and run it there. If I push the Docker image mycon/httpd to a Docker registry, I can then pull it to any other Linux machine running a Docker Engine. I can also backup the image to a tar file using the docker save command:

     

    [root@ol7-host ~]# docker save -o webserver.tar mycon/httpd:r1

     

     

    I can move the tar file to another host and load the image into that host's Docker Engine:

     

    [root@another-host ~]# docker load -i webserver.tar
    [root@another-host ~]# docker images
    REPOSITORY          TAG         IMAGE ID            CREATED              VIRTUAL SIZE  mycon/httpd         r1          2fb1c664f394        About a minute ago   414.9 MB  oraclelinux         7           3200155fe586        5 weeks ago          195.1 MB  oraclelinux         7.0         3200155fe586        5 weeks ago          195.1 MB  oraclelinux         latest      3200155fe586        5 weeks ago          195.1 MB

     

     

    Using a Dockerfile

     

    Now that you've seen how to create and manipulate Docker containers using the command line, the preferred way to build and customize containers is actually using Dockerfiles. A Dockerfile is a small text file that contains the instructions required to construct a container. When a Dockerflle is built, each instruction adds a layer to the container in a step-by-step process. The build creates a container, runs the next instruction in that container, and then commits the container. Docker then runs the committed image as the basis for adding the next layer. The benefit of this layered approach is that Dockerfiles with the same initial instructions reuse layers.

     

    Dockerfiles also create an easily readable and modifiable record of the steps used to create a Docker image. Publishing a Dockerfile to the public Docker Hub or to an internal repository is generally the preferred method of creating and sharing Docker images.

     

    To create a Dockerfile, first create a directory for it:

     

    [root@ol7-host ~]# mkdir /home/Dockerf-web
    [root@ol7-host ~]# cd !$

     

     

    In that directory, use a text editor to create a file called Dockerfile that contains the following contents:

     

    # Dockerfile for creating a Docker image for OL 7 and httpd and perl

    FROM oraclelinux:7

    MAINTAINER E. Jones <ejones@email-address.com>

    RUN yum install -y httpd perl && yum clean all

    RUN echo "Example Web Server Content" > /var/www/html/index.html

    EXPOSE 80

    CMD /usr/sbin/httpd -D FOREGROUND

     

     

     

    This Dockerfile reflects the same steps as the example in which I manually built the Docker image for my web server—it configures a new container from a base Oracle Linux 7 image, installs the httpd and perl RPMs, and adds placeholder content for the opening web page.

     

    The docker build command constructs a new Docker image from this Dockerfile, creating and removing temporary containers as needed during its step-by-step build process:

     

    [root@ol7-host Dockerf-web]# docker build -t mycon/httpd:r2 .
    Sending build context to Docker daemon  2.56 kB

    Sending build context to Docker daemon 

    Step 0 : FROM oraclelinux:7  ---> 3200155fe586

    Step 1 : MAINTAINER E. Jones <ejones@email-address.com

    ---> Running in ed340c7747a2 

    ---> 243472b305b6

    Removing intermediate container ed340c7747a2

    Step 2 : RUN yum install -y httpd perl && yum clean all

    ---> Running in ff8c659c6cac

    Resolving Dependencies . . . Complete! 

    Cleaning repos: ol7 UEKR3 ol7_latest

    Cleaning up everything

    ---> dfc8af8ff45c

    Removing intermediate container ff8c659c6cac

    Step 3 : RUN echo "Example Web Server Content" > /var/www/html/index.html 

    ---> Running in aefb62199d66

    Example Web Server Content 

    ---> b0fea1180c8e

    Removing intermediate container aefb62199d66

    Step 4 : EXPOSE 80 

    ---> Running in df6b1f699468 

    ---> fe4c4ce82aa3

    Removing intermediate container df6b1f699468

    Step 5 : CMD /usr/sbin/httpd -D FOREGROUND 

    ---> Running in 141571047fdc 

    ---> 16e2d42c3acf

    Removing intermediate container 141571047fdc

    Successfully built 16e2d42c3acf

     

     

     

    The docker images command lists the new mycon/httpd:r2 image created from the Dockerfile:

     

    [root@ol7-host ~]# docker images
    REPOSITORY          TAG          IMAGE ID            CREATED             VIRTUAL SIZE mycon/httpd         r2           16e2d42c3acf        16 minutes ago      420 MB  mycon/httpd         r1           2fb1c664f394        22 hours ago        414.9 MB  . . .

     

     

    More information is available in the Dockerfile reference guide and in the article "Best practices for writing Dockerfiles."

     

    Limiting Runtime Resources

     

    A Docker container uses underlying control group (cgroup) technologies, creating a cgroup for each Docker container. Cgroups provide useful capabilities, such as collecting metrics for CPU, memory, and block I/O usage and providing resource management capabilities. For each Docker container, you can find metrics in the host's corresponding cgroup hierarchy; for example, on an Oracle Linux 7 host running the Unbreakable Enterprise Kernel Release 3 (UEKR3), a memory.stat file in the directory /sys/fs/cgroup/memory/system.slice/docker-<container ID> lists memory-related metrics for that container. (See the blog article "Gathering LXC and Docker containers metrics.")

     

    The docker run command provides options that enable runtime limits for memory and relative CPU allocations. These options provide a degree of resource control when executing container images. The -m or --memory option limits the amount of physical and swap memory available to processes within a container. For example, the following command places a limit of 256 MB for physical memory (and up to 512 MB for memory plus swap):

     

    [root@ol7-host ~]# docker run -d --memory=256m --name guest1 -p 8080:80 mycon/httpd:r2
    c9f26a16a4b701b8cb3bcfebb7f8dd90accc906440acb22ba3d33f5ca55a1e85

     

     

    The -c or --cpushares option provides a method of assigning a relative number of CPU shares:

     

    [root@ol7-host ~]# docker run -d --cpushares=512 --name guest2 -p 8080:80 mycon/httpd:r2
    d7479853f7d1a797e663199809f462e6fcc30f306236d7895814c7825df5f9fa

     

     

    By default, a container gets 1024 CPU shares, so in this example, the guest2 container gets a relative 50 percent share of the available computing resources. Note that the host kernel applies limits only when there is resource contention. For example, if guest2 is assigned 512 shares (50 percent, as shown above) and guest1 is assigned 1024 shares (100 percent), processes in guest2 will still get 100 percent of the available CPU resources if all guest1 processes are idle.

     

    For more information about options to the docker run command, enter docker run --help or see the Docker run reference guide.

     

    Connecting a Web Server Container to a MySQL Container

     

    Suppose I want to connect my web server container to a container running an instance of MySQL. Docker makes it possible to link containers together, creating a secure channel for one container to access certain information from another.

     

    Previously I pulled the Oracle-verified MySQL image from the Docker Hub using the command docker pull mysql/mysql-server. To run the MySQL image as a container named db, I enter the following command:

     

    [root@ol7-host ~]# docker run --name db -d -e MYSQL_ROOT_PASSWORD=s5cr5t \
    -v /home/datadir:/var/lib/mysql mysql/mysql-server:db1

     

     

    The -d flag starts the db container in detached or background mode. The -e switch passes the environment variable MYSQL_ROOT_PASSWORD to the container.

     

    Using the -v or --volume flag is how you can associate database storage (or, in general, any files or folders) that a Docker container needs to change while it's running. Remember that Docker containers are "ephemeral"—that is, they are transient in nature and data does not persist beyond the lifespan of a container's execution. Associating a data volume with a container using the -v flag allows the container to access, modify, and persist data on the host.

     

    Reminiscent of an NFS mount, the -v flag causes the directory /home/datadir on the host to be mounted as /var/lib/mysql (the default database location for MySQL) on the container. From an operational standpoint, the ability to mount a database directory as a container volume in this way also provides an easy way to enable database backups.

     

    The Docker Hub mysql/mysql-server image includes an entrypoint script (entrypoint.sh) that sets up the database server automatically, initializing mysqld. I can view log messages generated from a container using the docker logs command:

     

    [root@ol7-host ~]# docker logs db
    Running mysql_install_db 2015-04016 05:48:31 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated.  Please use -explicit_defaults_for_timestamp server option (see documentation for more  details). 2015-04016 05:48:31 0 [Note] /usr/bin/mysqld (mysqld 5.6.24) starting as process 22 ... PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER ! ... Finished mysql_install_db MYSQL init process in progress... MYSQL init process in progress... MYSQL init process in progress... MYSQL init process done Ready for start up. 2015-04016 05:48:44 0 [Note] /usr/bin/mysqld (mysqld 5.6.24) starting as process 1 ...

     

     

    I can execute a bash shell to investigate the running MySQL container further. Because I mounted the data directory /home/datadir on the host as /var/lib/mysql on the container, I can see the sample database file mysqlsampledatabase.sql that I previously placed in /home/datadir:

     

    [root@441db2bac0b1 /]# docker exec -it db bash
    [root@441db2bac0b1 /]# ls /var/lib/msql
    auto.cnf         ibdata1         mysqlsampledatabase.sql ib_logfile0      mysql           mysqlsampledatabase.zip ib_logfile0      mysql.sock      performance_schema

     

     

    By running the MySQL monitor in the guest container, I can connect to the database server and load the sample database. By default, the Docker image mysql/mysql-server exposes port 3306 (the standard MySQL port) for database access:

     

    [root@441db2bac0b1 /]# mysql -h 127.0.0.1 -u root -p
    Enter password:  Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.6.24 MySQL Community Server (GPL) Copyright © 2000, 2015, Oracle and/or its affiliates.  . . .  Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  mysql> source /var/lib/mysqlsampledatabase.sql
    Query OK, 0 rows affected (0.06 sec) Query OK, 2996 rows affected (0.25 sec) Records: 2996 Duplicates: 0 Warnings 0 . . .  Query OK, 110 rows affected (0.25 sec) Records: 110 Duplicates: 0 Warnings 0 Query OK, 0 rows affected (0.00 sec)  mysql> quit
    Bye [root@441db2bac0b1 /]#

     

     

    By linking containers using the --link flag, other application containers can access the MySQL database running in the db container. This simplifies the separation of database, application, and web services, making it easier to isolate services in different containers. I can run my web server image as a container and connect it to the database container using the following command:

     

    [root@ol7-host ~]# docker run -d --name web1 -v /home/webdir -p 80:80 \
    --link db:db mycon/httpd:r2
    1d99444c4f536a4b7accc906440acb22ba3d33f5c2c63fe4bdd3a55a1e850e0d

     

     

    Assuming I've configured /etc/httpd/conf/httpd.conf to allow CGI script execution on the web server and I created a Perl script to perform some kind of SQL query, I can run queries against the database in the db container (note that I can use the docker inspect command to obtain the web server IP address I need for the query):

     

    [root@ol7-host ~]# curl http://172.17.0.23/cgi-bin/doquery.pl?150
    +---------------------------+ | customerName              | +---------------------------+ | Atelier graphique         | | La Rochelle Gifts         | | Savely & Henriot, Co.     | | ... +---------------------------+ 12 rows in set (0.00 sec)

     

     

    The Oracle Linux documentation includes a detailed example of how to link a web container with a MySQL database, and it provides sample scripts that configure httpd.conf, create a database, and perform queries. Additional background on linking containers and using data volumes is available there and also in the Docker user guide.

     

    Using Ksplice

     

    Because the host for my Docker test environment is running Oracle Linux, this article wouldn't be complete without a discussion of using Ksplice. Ksplice can perform kernel updates on Oracle Linux without the need to reboot. If I were deploying web and database servers in a production environment using Docker containers, this means that I could apply the latest security errata or kernel updates without having a planned outage. The Docker containers, web servers, and database services (or whatever workloads are running in my containers) can continue to function without interruption.

     

    Ksplice is included with an Oracle Linux Premier Support contract, which also includes support for Docker at no additional charge. Oracle offers a 30-day trial version of Ksplice for the Unbreakable Enterprise Kernel or the Red Hat Compatible Kernel (RHCK).

     

    Logging into my Oracle SSO account, I follow the installation instructions provided to install the Ksplice packages on my Linux host:

     

    [root@ol7-host ~] wget -N https://www.ksplice.com/uptrack/install-uptrack
    [root@ol7-host ~] sh install-uptrack \
    881f3ce6da85b13f0c1845f591cfa0770c064e19d458270bc3ee0acd0015aa4c
    [ Release detected: ol ] --2015-03-04 20:16:39--  https://www.ksplice.com/yum/uptrack/ol/ksplice-uptrack-release.noarch.rpm Resolving www.ksplice.com (www.ksplice.com)... 137.254.56.32 . . . Installed:  uptrack.noarch 0:1.2.24-0.el7 Dependency Installed:  PyYAML.x86_64 0:3.10-11.el7    libyaml.x86_64 0:0.1.4-11.el7_0    perl-autodie.noarch 0:2.16-2.el7 Complete! Effective kernel version is 3.8.13-55.1.5.el7uek Nothing to be done. [ Installation Complete! ] [ Please run '/usr/sbin/uptrack-upgrade -y' to bring your system up to date ]

     

     

    Once the Ksplice uptrack program is installed, I can use it to perform a rebootless upgrade:

     

    [root@ol7-host ~] /usr/sbin/uptrack-upgrade -y
    The following steps will be taken: Install [kxc75rp4] CVE-2014-7825, CVE-2014-7826: Perf DoS and local privilege escalation. Install [nwr7zb2b] CVE-2014-8160: iptables rules by-pass when the protocol module is not loaded. .  .  . Installing [kxc75rp4] CVE-2014-7825, CVE-2014-7826: Perf DoS and local privilege escalation. Installing [nwr7zb2b] CVE-2014-8160: iptables rules by-pass when the protocol module is not loaded. .  .  . Installing [lrex34wm] Multiple NULL pointers dereference in Emulex LightPulse SCSI driver. Your kernel is fully up to date. Effective kernel version is 3.8.13-68.el7uek

     

     

    In the meantime, the Docker containers are still running on this system:

     

    [root@ol7-host ~] # docker ps
    CONTAINER ID IMAGE          COMMAND              CREATED     STATUS      PORTS     NAMES  441db2bac0b1 mysql/mysql-server:latest "/entrypoint.sh mysq  2 hours ago Up 1 hour  3036/tcp->80/tcp db 06517cd0a7bd mycon/httpd:r2 "/bin/sh -c '/usr/sb 2 hours ago Up 2 hours   0.0.0.0:8082->80/tcp guest3 d7479853f7d1 mycon/httpd:r2 "/bin/sh -c '/usr/sb 3 hours ago Up 3 hours   0.0.0.0:8081->80/tcp guest2 154293f56f74 mycon/httpd:r2 "/bin/sh -c '/usr/sb 4 hours ago Up 4 hours   0.0.0.0:8080->80/tcp guest1

     

     

    Learn More

     

    In addition to the Oracle Linux documentation on Docker, there are excellent resources for learning more about Docker at http://docs.docker.com/ including information on installing Docker on different Linux operating systems. An application called Boot2Docker even runs a lightweight Linux VM and a Docker daemon on Mac OS X and Microsoft Windows. The Docker user guide and Docker reference manual are also excellent references.

     

    About the Author

     

    Ginny Henningsen has worked for the last 17 years as a freelance writer developing technical collateral and documentation for high-tech companies. Prior to that, Ginny worked for Sun Microsystems, Inc. as a Systems Engineer in King of Prussia, PA and Milwaukee, WI. Ginny has a BA from Carnegie-Mellon University and an MSCS from Villanova University.

     

     

    Revision 1.0, 05/06/2015

     

     

     

    Follow us:
    Blog | Facebook | Twitter | YouTube