Deploy and Run Refinitiv Real-Time SDK in Docker
Introduction
Docker is an open containerization platform for developing, testing, deploying, and running any software applications. In Docker, the applications are presented as lightweight, portable, and self-sustaining containers which can be simultaneously run in a loosely isolated and virtual environment on a given host. Containers are lightweight because they don’t use the extra load of a hypervisor, but they run directly within the host machine’s kernel. This means more containers can be run concurrently on a given host compared to other virtual machine technologies.
Developers can use Docker to automate repetitive chores, such as setting up and configuring controlled development environments. Each environment or container has its own resources that are independent of other containers. Numerous containers of separate applications are running on completely different stacks. Therefore, developers can avoid common problems, such as run-time library conflicts, and unsupported environments and focus totally on developing software. Moreover, they can simply delete the containers without any footprints left on the host machine.
This article demonstrates a way to deploy and run Refinitiv Real-Time SDK applications in the Docker platform. It starts with building a Docker image for Refinitiv Real-Time SDK and then shows usages of this image including running the provider and consumer examples.
However, the Refinitiv Real-Time SDK isn't qualified on the Docker platform. If you find any problems while running it on the Docker platform, the issues must be replicated on bare metal machines before contacting the helpdesk support.
Docker Installation
Docker is available on many platforms including Windows, Mac, CentOS, Debian, Oracle Linux, RHEL, and Ubuntu. In this article, Oracle Linux Server 6 and Docker 1.12.6 are used. Please follow the following steps to install a Docker on Oracle Linux Server 6.
- Installing Docker Engine
The Docker Engine is a lightweight and powerful client-server application used to build, manage, and containerize the applications. It is built on top of the Linux kernel with extensively leveraging its features. It can be installed by using the corresponding packaging tool of the Linux distribution, such as using the apt-get command for Debian and Ubuntu, and the yum command for RedHat, Fedora, and CentOS.
$ sudo yum install docker-engine
- Starting and activating the Docker service
After installing the Docker, its service must be started and activated on restart by using the following commands.
$ sudo service docker start
$ sudo chkconfig docker on
- Verifying the Docker service
After starting the Docker service, the following commands can be used to verify the version and status of the Docker service.
$ sudo docker info
...
Server Version: 1.12.6
...
$ sudo service docker status
docker (pid 1290) is running...
The running status indicates that the Docker service is ready to be used. The next section briefly explains a Docker image and container.
Docker Image and Container
A Docker image is a lightweight, stand-alone, executable package that includes everything for running an application including the code, runtime libraries, environment variables, and configuration files. There are a lot of public Docker images registered in the Docker registry. The registry is for registering the Docker images, whereas the repository is for storing those registered Docker images. The following command pulls an Ubuntu Docker image from the Docker repository.
$ sudo docker pull ubuntu
You can list the available Docker image in the host machine by using the following command.
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED
ubuntu latest 2d696327ab2e 2 weeks ago 121.6 MB
A docker image can be run inside a container. The following command creates a new running instance of Ubuntu Docker image and prints Hello World by using the echo command.
$ sudo docker run --rm ubuntu echo "Hello World"
Option | Description |
--rm | Automatically remove the container when it exits |
If --rm isn't used, docker rm command can be used to remove the container.
At this point, you have already understood the basic concepts of Docker image and container. The next section explains how to build a new Docker image for Refinitiv Real-Time SDK.
Refinitiv Real-Time SDK Docker Image
Docker allows users to build a new Docker image from an existing Docker image by using the Dockerfile. Dockerfile is a text-based script that contains special commands in a sequence for building the new images from the existing base images. The commands include selecting a base image from the Docker repository, adding metadata, installing all the required applications, compiling the applications, and setting up environment variables, and making the necessary file changes.
The list of instructions in the Dockerfile for building a Refinitiv Real-Time SDK Docker image is:
- Set a base image for a build process to Oracle Linux 7
FROM oraclelinux:7
The FROM instruction is the first valid instruction of a Dockerfile. It sets a base image for a build process. Subsequent instructions would build on top of this base image. Refinitiv Real-Time SDK supports Oracle Linux 7 so it is used as a base image for building a Refinitiv Real-Time SDK Docker image.
- Set author's detail of the image
LABEL maintainer="Refinitiv Developer Advocate"
The LABEL instruction adds key-value pair metadata to an image. The above instruction adds metadata for a maintainer of this image. Users can use the docker inspect command to view an image's labels.
- Load and build Refinitiv Real-Time SDK libraries
In this step, the RUN instruction is used to load all required packages, and build Refinitiv Real-Time SDK libraries and examples. It accepts multiple commands separated by an && operator. The backslash is also used to split long RUN statements into multiple lines.
First, it runs the yum command to install gcc, ksh, and lsb packages. These packages are required to build Refinitiv Real-Time SDK libraries.
RUN yum -y install gcc-c++.x86_64 git.x86_64 ksh redhat-lsb-core.x86_64 openssl-devel wget.x86_64
Then, it creates a directory (/opt/refinitiv) for installing Refinitiv Real-Time SDK and uses git command to clone the Refinitiv Real-Time SDK package from github.
...
RUN mkdir -p /opt/refinitiv \
&& cd /opt/refinitiv \
&& git clone --recursive https://github.com/refinitiv/Real-Time-SDK.git \
&& wget https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.tar.gz \
&& wget http://xmlsoft.org/sources/libxml2-2.9.9.tar.gz \
&& tar -xvf cmake-3.11.2-Linux-x86_64.tar.gz
...
Next, it follows steps in the github page to build Real-Time SDK - C/C++ edition.
RUN cd /opt/refinitiv/Real-Time-SDK \
&& mkdir rtsdk \
&& export PATH=/opt/refinitiv/cmake-3.11.2-Linux-x86_64/bin:$PATH \
&& cd rtsdk \
&& mkdir -p external/dlcache \
&& cp /opt/refinitiv/libxml2-2.9.9.tar.gz external/dlcache \
&& cmake ../ -DBUILD_UNIT_TESTS=OFF \
&& make \
Finally, it compiles provider and consumer examples in the Refinitiv Real-Time SDK C package and creates softlinks to compiled binaries and data dictionary files.
...
&& cp /opt/refinitiv/Real-Time-SDK/Cpp-C/etc/* /opt/refinitiv/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64*/Optimized \
&& ln -s /opt/refinitiv/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64* /opt/refinitiv/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64
...
- Set a working directory
WORKDIR /opt/refinitiv/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64/Optimized
The above WORKDIR instruction sets a working directory to the Examples directory of Refinitiv Real-Time SDK C package. This directory contains softlinks to provider and consumer applications which can be executed in Docker containers.
- Set a default command for an executing container
CMD /bin/sh
The CMD instruction specifies a default command which will be executed when a container is launched from a Docker image. However, it can be overridden by the docker run subcommand arguments. The default command executed when launching this image is shell command.
The full Dockerfile is available in GitHub.
To build a Docker image from this Dockerfile, you can copy this Docker file to a host machine, and then run the following command in the same directory that contains this Dockerfile.
$ ls -al
...
-rw-rw-r--. 1 user1 user1 1004 Oct 9 04:27 Dockerfile
...
$ sudo docker build -t real-time-sdk .
Option | Description |
-t | Specify the optional tag name for the image |
It will take some time to build the Refinitiv Real-Time SDK image. The built image will be tagged or named with real-time-sdk.
Alternatively, Docker can build an image directly from the Dockerfile in GitHub by using the following command:
$ sudo docker build -t real-time-sdk https://github.com/Refinitiv-API-Samples/Article.EMA.ETA.Docker.git
To do this, please make sure that git 2.x package is installed on the host machine.
After building, the docker images command can be used to list all available Docker images on the host machine.
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
real-time-sdk latest 2155a4084df2 14 seconds ago 2.142 GB
...
Now, the Refinitiv Real-Time SDK Docker image is ready to be used. The next section shows how to use and run this image in various scenarios.
Usages
1. Run Provider and Consumer on the same Docker host
The Provider and Consumer examples are built in the image and ready to run in Docker containers. This section shows how to run the provider and consumer examples in Docker containers on the same Docker host.
To run these examples, the example name must be specified as an argument of the docker run command in order to override the default shell command.
The following command launches a Docker container with the real-time-sdk image and runs the provider example in the container. The example's arguments can also be defined after the application's name.
$ sudo docker run --name provider -t real-time-sdk ./Provider -p 14002 -s DIRECT_FEED -runtime 300
Option | Description |
--name | Assign a name to the container |
-t | Allocate a pseudo-TTY for this container |
This command sets a name of the container to "provider" by using the --name option so it can be used by other Docker commands. It also uses the -t option to attach a terminal to the container in order to see the output when running the provider example.
After running the command, you will see the output of the provider example on the screen.
$ sudo docker run --name provider -t real-time-sdk ./Provider -p 14002 -s DIRECT_FEED
portNo: 14002
serviceName: DIRECT_FEED
serviceId: 1
Server IPC descriptor = 3 bound on port 14002
Press Ctrl+c to detach the terminal.
Next, launch another Docker container with the consumer example to consume the data from the provider container.
$ sudo docker run --name consumer -t --link provider:prov1 real-time-sdk ./Consumer -h prov1 -p 14002 -s DIRECT_FEED -mp TEST
Option | Description |
--name | Assign a name to the container |
-t | Allocate a pseudo-TTY for this container |
--link | Add a link to another container |
This command sets the name of the container to "consumer". It uses the --link option to link this container to the container named "provider" and set an alias to "prov1". After linking, the application in the container can use this alias to create a network connection to the linked Docker container.
After running the command, you will see the output of the consumer example on the screen.
$ sudo docker run --name consumer -t --link provider:prov1 real-time-sdk ./Consumer -h prov1 -p 14002 -s DIRECT_FEED -mp TEST
Proxy host:
Proxy port:
Input arguments...
Using Connection Type = 0
srvrHostname: prov1
srvrPortNo: 14002
serviceName: DIRECT_FEED
Attempting to connect to server prov1:14002...
Attempting to connect to server prov1:14002...
Channel IPC descriptor = 3
Channel 3 In Progress...
Channel 3 Is Active
Connected to eta3.1.1.L1.linux.rrg 64-bit Static device.
Ping Timeout = 60
Received Login Response for Username: root
State: Open/Ok/None - text: "Login accepted by host 38ec020e0900"
Received Source Directory Response
State: Open/Ok/None - text: "Source Directory Refresh Completed"
Received serviceName: DIRECT_FEED
TEST
DOMAIN: RSSL_DMT_MARKET_PRICE
State: Open/Ok/None - text: "Item Refresh Completed"
RDNDISPLAY 100
RDN_EXCHID SES(155)
DIVPAYDATE 22 OCT 2010
TRDPRC_1 1.00
BID 0.99
ASK 1.03
ACVOL_1 100000.00
NETCHNG_1 2.15
ASK_TIME 09:34:00:000:000:000
Press Ctrl+c to detach the terminal.
After detaching the terminal, the containers are still running in the background. The following Docker commands can be used with the container names to manage the containers.
Option | Description |
docker ps -a | List all containers |
docker start CONTAINER [CONTAINER...] | Start one or more stopped containers |
docker stop CONTAINER [CONTAINER...] | Stop one or more running containers |
In summary, to run provider and consumer containers on the same Docker host, the --link option is used to create a link between containers.
2. Run Provider and Consumer on different Docket hosts
The provider and consumer containers can be run on different Docker hosts. The real-time-sdk Docker image must be built on both Docker hosts. In this scenario, the provider container is on host A and the consumer container is on host B.
Use the following command to launch the provider container on host A.
$ sudo docker run -t --name providerA -p 14002:14002 real-time-sdk ./Provider -s DIRECT_FEED -p 14002
portNo: 14002
serviceName: DIRECT_FEED
serviceId: 1
Server IPC descriptor = 3 bound on port 14002
Option | Description |
--name | Assign a name to the container |
-t | Allocate a pseudo-TTY for this container |
-p | Publish a container's port(s) to the host |
It sets a name of the container to "providerA" by using the --name option. It uses the -t option to attach the terminal in order to see the output when running the provider example and uses the -p option to publish the TCP 14002 port used by the container to TCP 14002 port on the host machine. Therefore, the consumer container can connect to this port on the host machine to the consumer the data from the container.
Then, use the following command to launch the consumer container on host B.
$ sudo docker run -t --name consumerB real-time-sdk ./consumer -h <host_A_IP> -p 14002 -s DIRECT_FEED -mp TEST
You need to change the IP address of host A machine. This command launches a container from the real-time-sdk image. The container will run consumer example which connects to TCP 14002 port on host A and consumes data from DIRECT_FEED service.
In summary, to run provider and consumer examples on different Docker hosts, the -p option must be used when running the provider container to publish the listening TCP port used by the provider to the host machine. Then, the consumer container can connect to that published port on that host machine.
3. Access shell command to develop applications or build examples
If a Docker container is launched from the real-time-sdk image without any arguments, the default command (/bin/sh) will be executed.
$ sudo docker run -it --name rtsdk real-time-sdk
Option | Description |
-i | Keep the standard input open for this container |
-t | Allocate a pseudo-TTY for this container |
--name | Assign a name to the container |
After running this command, you can access the shell in the container. Then, you can use the container to build Refinitiv Real-Time SDK applications or modify and build other examples. The Refinitiv Real-TimeSDK is in /opt/refinitiv/Real-Time-SDK/ directory.
To run other ETA examples, such as the VAConsumer, you need to set the LD_LIBRARY_PATH environment variable.
export LD_LIBRARY_PATH=/opt/refinitiv/Real-Time-SDK/rtsdk/install/lib64 |
Conclusion
Docker is an open containerization platform for developing, testing, deploying, and running any software applications. This article shows how to deploy and run Refinitiv Real-Time SDK's applications in the Docker platform. It starts with building a Docker image for Refinitiv Real-Time SDK and then showing some use cases including running the provider and consumer examples.