Containerized CLIs with Docker — Making DevOps easier

Lucas Gomes
Oracle Developers
Published in
8 min readAug 25, 2017

Installing a Command-line interface tool usually is very straightforward. You need to download some packages specific to your Platform, then go through some installation procedures, configure some files and you should be ready to go. It shouldn’t take longer than 10' to complete all these tasks — perhaps this is not always true. You may run into some issues related to your specific environment (missing or incompatible dependencies, kernel version, lack of permission, etc) that would make this process taking longer than expected.

Have you imagined a scenario where you have to install multiple CLIs from different softwares on all your CI servers, all of them running on different platforms?

You can find several examples of CLIs for Developers and IT Administrators built as a Docker Image on github. But I can give you some usage scenarios at Oracle. For example, if you want to deploy your custom image template to Oracle Cloud Infrastructure Classic (OCIC — former Oracle Compute Cloud), you first need to upload your image template file to the OCI Object Storage Classic using the Storage CLI, and then you call the OCIC CLI to register the image. The same applies if you need to deploy your application to Application Container Cloud Service — you first need to upload the application package to a Storage container and then use the ACCS CLI to start your application.

With Docker, instead of having to install all the CLIs on your host or VMs, you can take the advantage of the Docker portability and build your own Docker Image that can be leveraged to any platform. This will give you agility on your DevOps process, allowing you to get started quickly by running only one command, but this can also be used to distribute all the Oracle Cloud toolset in a portable way, including running on environments that don’t (yet) have native support or the CLI tools, without having to worry about complex setup tasks and installation process.

In this article we will create a Docker container containing the CLIs for the following Oracle Cloud services:

If you want to try these services, you can request a trial account on https://cloud.oracle.com/tryit.

Software Requirements

If you have not done so already, install Docker on your local machine.

The individual CLI tools can be downloaded from Oracle Technology Network. Download and save the files locally as you will need them later.

The File Transfer Manager CLI requires a Java run-time environment

  • We recommend you to use Oracle Java 8 Docker image available on the Docker Store as a base image. This image is certified by Docker Inc. and free of charge for Developers and Commercial usage. To install the image, you need to follow the steps below:
  1. Sign up to a Docker Store account (in case you haven’t done it yet)
  2. Go to https://store.docker.com/images/oracle-serverjre-8 to access the Oracle Java 8 Docker Image
  3. Click on Proceed to Checkout
  4. Login with your Docker ID
  5. Fill up the form
  6. Accept the Agreement terms
  7. Click on Get Content button
  8. Follow the installation instructions on the Docker page

Docker Image vs Containers

Before we get started, I just want to bring you some general Docker concepts. A Docker Image is a lightweight, stand-alone, executable package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables and config files. A container is a runtime instance of an image — what the image becomes in memory when actually executed. It runs completely isolated from the host environment by default, only accessing host files and ports if configured to do so.

Docker Containers run apps natively on the host machine’s kernel. They have better performance characteristics than virtual machines that only get virtual access to host resources through a hypervisor. Containers can get native access, each one running in a discrete process, taking no more memory than any other executable.

Docker can build images automatically by reading the instructions from a Dockerfile, which is a file that contains all the commands, in order, needed to build a given image. You can find a recommendation guide with some best-practices on how to build your Docker Image here.

Building an Oracle Cloud Toolset Docker Image

The first step to build your image is to create a working directory.

$ mkdir ~/oracle-cloud-tools
$ cd ~/oracle-cloud-tools

Place all the required downloaded software in the working directory.

$ ls -la
total 21592
drwxr-xr-x 4 lgomes staff 136B Jan 22 14:57 ./
drwxr-xr-x 10 lgomes staff 340B Jan 22 14:57 ../
-rw-r--r-- 1 lgomes staff 3.4M Jan 12 18:02 ftmcli-v2.3.3.zip
-rw-r--r-- 1 lgomes staff 7.1M Jan 12 07:44 opc-cli.17.2.2.zip

Install the store/oracle/serverjre:8 Docker image on your local computer. If you already done so, make sure you have the latest one:

$ docker pull store/oracle/serverjre:88: Pulling from store/oracle/serverjre
7bd9e1692b54: Pull complete
cd53021a057e: Pull complete
Digest: sha256:e95d11f91814d051d5807b96f4fd6be733f127c9c03530beb65e77155be8b59a
Status: Downloaded newer image for store/oracle/serverjre:8

The next step is to create your Dockerfile. You can note that I am referring to the locally installed store/oracle/serverjre:8 as the base image. You can find the Dockerfile definition for that image on GitHub. I also created some environment variables which maps to the installation packages. I used ARG instruction to specify a default version for the installed libraries. The value set in the ARG instruction can be overwritten when you build the image by specifying --build-arg as a parameter of the docker build command.

Last but not least, in order to enable access to the latest channels available in the yum repo, you should download the public yum configuration file from the server before calling any other command within the RUN instruction. This is required because the base Docker image was created prior to the channels, thus, they don't exist in the public-yum-ol7.repo file within the base image itself.

RUN curl -o /etc/yum.repos.d/public-yum-ol7.repo http://yum.oracle.com/public-yum-ol7.repo \
&& yum-config-manager --enable ol7_developer_EPEL \
&& yum-config-manager --enable ol7_developer \

In case you will run your image behind your corporate proxy, you need to specify the appropriate proxy environment variables - you can remove the comments related to the http_proxy and https_proxy on my example and refer to the Troubleshooting section on this article in case you have any issue. You optionally can specify an owner for this Image by entering the name and e-mail address in the Maintainerproperty.

FROM store/oracle/serverjre:8
MAINTAINER John Doe <your-email-address-here>
ENV LC_ALL=en_US.utf8 \
LANG=en_US.utf8
ARG OPC_CLI_VERSION=17.2.2
ARG CS_FTM_CLI_VERSION=2.3.3
ENV OPC_CLI_PKG=opc-cli.$OPC_CLI_VERSION.zip
ENV CS_FTM_CLI_PKG=ftmcli-v${CS_FTM_CLI_VERSION}.zip
ADD ${OPC_CLI_PKG} ${CS_FTM_CLI_PKG} /oracle-cloud-tools/WORKDIR /oracle-cloud-tools/RUN curl -o /etc/yum.repos.d/public-yum-ol7.repo http://yum.oracle.com/public-yum-ol7.repo \
&& yum-config-manager --enable ol7_developer_EPEL \
&& yum-config-manager --enable ol7_developer \
&& yum -y install unzip python-oci-cli \
&& unzip /oracle-cloud-tools/${OPC_CLI_PKG} \
&& unzip -j ${CS_FTM_CLI_PKG} */*.jar \
&& yum -y install opc-cli-${OPC_CLI_VERSION}.x86_64.rpm \
&& rm -f opc-cli-${OPC_CLI_VERSION}.x86_64.rpm ${OPC_CLI_PKG} ${CS_FTM_CLI_PKG} \
&& rm -rf /var/cache/yum/*
CMD ["/bin/bash"]

Now you can build your image. The docker build command builds Docker images from a Dockerfile and a context. A build’s context is the set of files located in the specified PATH or URL, in the command: docker build [OPTIONS] PATH

The image name is made up of slash-separated name components, optionally prefixed by a registry hostname. By specifying the -t flag on our command line, we can create a TAG to append it to your image name.

On our example, we are specifying the image name lucassrg/oracle-cloud-tools and the tag name 2018.01, where lucassrg is the repository name on the public Docker Registry (DockerHub). Path is set to our current "." working directory .

You should replace lucassrg by your own repository name. And don't forget to refer to your repository name in the further steps.

Run the docker build command as suggested below. This process would take awhile to complete due to download and installation of all packages.

docker build -t lucassrg/oracle-cloud-tools:2018.01 .

At the end, you should get a Successfully built message:

Successfully built 38cee208f94f
Successfully tagged lucassrg/oracle-cloud-tools:2018.01

Running your Toolset as a Docker Container

Once you complete building your image you can run it. I created a bash script to act as a wrapper.

oci.sh

#!/bin/shdocker run \
--interactive --tty --rm \
--volume "$PWD":/oracle-cloud \
--workdir /oracle-cloud \
lucassrg/oracle-cloud-tools:2018.01 "$@"

Now you can run any Oracle Cloud CLI command by calling the wrapper, for example:

$ sh ./oci.sh oci --version
2.4.13
$ sh ./oci.sh opc --version
opc version 17.2.2
$ sh ./oci.sh java -jar /oracle-cloud-tools/ftmcli.jar -v
Version 2.3.3

As an alternative to the wrapper, you can create aliases containing all the required parameters to connect to one specific account/environment.

For example, on Oracle Cloud Infrastructure, you can create a configuration file calledoci_config on the workdir folder and then you set the --config-file parameter pointing to it (make sure you also copied the ssh key you referenced in the configuration file into the same workdir):

$ cat oci_config
[DEFAULT]
user=ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq
fingerprint=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34
key_file=/oracle-cloud/my-ssh-key-file.pem
tenancy=ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq
region=us-ashburn-1
$ alias oci="docker run --interactive --tty --rm --volume "$PWD":/oracle-cloud --workdir /oracle-cloud:ro,private lucassrg/oracle-cloud-tools:2018.01 oci --config-file /oracle-cloud/oci_config"

For OCI-Classic, you create a profile file (and password file) and set the permission to 600. I created a folder named opc_profiles under the workdir folder to place those files and then, on the alias, I referenced the folder and file as environment variables via the -e parameter.

$ ls -la opc_profiles
total 16
drwxr-xr-x 4 lgomes staff 136B Aug 30 12:38 ./
drwxr-xr-x 8 lgomes staff 272B Aug 30 11:46 ../
-rw------- 1 lgomes staff 243B Aug 30 12:38 my-profile
-rw------- 1 lgomes staff 17B Aug 30 12:38 my-profile-pwd
$ alias opc="docker run --interactive --tty --rm --volume "$PWD":/oracle-cloud:ro,private --workdir /oracle-cloud -e "OPC_PROFILE_DIRECTORY=/oracle-cloud/opc_profiles" -e "OPC_PROFILE_FILE=my-profile" lucassrg/oracle-cloud-tools:2018.01 opc"

For Storage Classic, you need to specify some environment variables:

$ alias ftmcli="docker run  --interactive --tty --rm --volume "$PWD":/oracle-cloud  --workdir /oracle-cloud -e "FTM_AUTH_URL=https://myidentitydomain.storage.oraclecloud.com" -e "FTM_USER=Storage-myidentitydomain:myusername" -e "FTM_SERVICE=Storage" -e "FTM_IDOMAIN=myidentitydomain" lucassrg/oracle-cloud-tools:2018.01 java -jar /oracle-cloud-tools/ftmcli.jar"

Then you just need to call the alias you specified as if you had the CLI installed on your own computer:

$ oci --version
2.4.13
$ opc --version
opc version 17.2.2
$ ftmcli -v
Version 2.3.3

For additional details on the usage, you should check the specific CLI documentation.

$ oci --help
Usage: oci[OPTIONS] COMMAND [ARGS]...
$ opc --help
USAGE:
opc [global_options...] service_name [service_options...] resource_name command [arguments...] [opt
ions...]
$ ftmcli --help
Usage: java -jar ftmcli.jar <command> [-A, --auth-url <auth url>]
[-S, --service <service>]
[-I, --identity-domain <identity domain>]
[-U, --user <user>]
[-d, --debug]
[-i, --silent]
[-v, --version]
[-h, --help]
[--properties-file <file path>]
[--save-auth-key]

Next Steps

Now you can easily manage all your infrastructure resources and applications in a portable and reliable way on different platforms. You can design your images containing as many CLIs as you need. For example, you can add the Oracle PaaS Service Manager CLI to your image for managing PaaS services. Or you can have an image with multiple Cloud providers CLIs installed to support all your Cloud solutions. You can also distribute your image via an Automated build process on a Public/Private Registry such as Docker Hub .

Credits

Thanks to Avi Miller who provided a great support with the design and optimization of the Dockerfile for Oracle Linux.

This is an updated version of the article with an optimized version of the Dockerfile.

Originally published: August 2017

Last update: January 2018.

--

--

Lucas Gomes
Oracle Developers

Oracle Cloud Specialist, Software Developer, DevOps, Microservices, Containers