Blog Detail
Developing services for Cisco NSO requires a development environment, which can be set up locally on your laptop or on a dedicated server. When a developer starts working on an NSO service, it has to install a correct NSO version, all required NEDs, and dependencies. This is where Docker can come in handy. It is a tool to make packaging easy, which means that you can pre-build a Docker image, which contains NSO, NEDs, and all dependencies.
In this blog post, I will show you how to create an NSO Docker image that can be used for development. There are a couple of advantages of using Docker containers for development. The most important is that everything can be packaged together in a single unit.
To build a Docker image, Docker requires a Dockerfile, where you put build instructions to create an image. I can create Dockerfile
from scratch. But there is a better way. NSO in Docker from Cisco is a repository that contains scripts and files to create a base NSO Docker image. Using the NSO in Docker project will produce a base image, which can be extended with additional packages.
This blog post is divided in three sections:
- Prepare a base image
- Extend the base image
- Run a Docker container
Prepare a Base Image
The first step in the process is to build a base image, which is a bare NSO installation that contains NSO only. The NSO in Docker project is used in this step.
Clone the Repository
The NSO in Docker repository should be cloned first.
$ git clone git@github.com:NSO-developer/nso-docker.git
Cloning into 'nso-docker'...
remote: Enumerating objects: 4597, done.
remote: Counting objects: 100% (1579/1579), done.
remote: Compressing objects: 100% (635/635), done.
remote: Total 4597 (delta 1043), reused 1395 (delta 871), pack-reused 3018
Receiving objects: 100% (4597/4597), 1.36 MiB | 2.08 MiB/s, done.
Resolving deltas: 100% (2932/2932), done.
$
$ cd nso-docker/
nso-docker$
Download Installation Files
To install NSO, you need the installation file, which is not included in the NSO in Docker project. You can download the installation file from the Cisco DevNet page. The installation file is an executable script, which verifies a signature and creates the installer file when executed.
You should put the file into the ./nso-install-files
directory, which is a default path, where the build script will take a look for the NSO installer.
nso-docker$ cd nso-install-files
nso-install-files$ ls
nso-5.5.linux.x86_64.signed.bin
The script should be executed to extract the installer file.
nso-install-files$ sh nso-5.5.linux.x86_64.signed.bin
Unpacking...
Verifying signature...
Retrieving CA certificate from http://www.cisco.com/security/pki/certs/crcam2.cer ...
Successfully retrieved and verified crcam2.cer.
Retrieving SubCA certificate from http://www.cisco.com/security/pki/certs/innerspace.cer ...
Successfully retrieved and verified innerspace.cer.
Successfully verified root, subca and end-entity certificate chain.
Successfully fetched a public key from tailf.cer.
Successfully verified the signature of nso-5.5.linux.x86_64.installer.bin using tailf.cer
This produces multiple files. All these files should be removed and you should only keep the actual installer in the directory.
nso-install-files$ ls
nso-5.5.linux.x86_64.installer.bin
Build the Base Image
Now that the installer is in the ./nso-install-files
you are ready to build the base image. You need to run the make
command in the root of the project.
nso-install-files$ cd ..
nso-docker$ make
...
OMITTED FOR BREVITY
...
This creates a base image. It is as simple as that.
nso-docker$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
cisco-nso-base 5.5-foobar 856ffdeef133 6 days ago 564MB
cisco-nso-dev 5.5-foobar 04f1f5da57b3 6 days ago 1.4GB
The make
command creates two images:
- a production image, which contains only required packages
- a development image, which also contains documentation, compilers, and other tools
The make
command adds the username to the image tag (5.5-foobar
), but you should add another tag that only includes the NSO version.
Add a New Tag to the Base Image
The Makefile
comes with another directive (tag-release
), which will be used to tag the image.
nso-docker$ make NSO_VERSION=5.5 tag-release
docker tag cisco-nso-dev:5.5-foobar cisco-nso-dev:5.5
docker tag cisco-nso-base:5.5-foobar cisco-nso-base:5.5
nso-docker$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
cisco-nso-base 5.5 856ffdeef133 6 days ago 564MB
cisco-nso-base 5.5-foobar 856ffdeef133 6 days ago 564MB
cisco-nso-dev 5.5 04f1f5da57b3 6 days ago 1.4GB
cisco-nso-dev 5.5-foobar 04f1f5da57b3 6 days ago 1.4GB
The base image is now ready.
Extend the Base Image
The base image will be extended with additional packages such as NEDs. The cisco-nso-base
image will be used as a base image. All instructions to extend the base image will be added into the Dockerfile
.
Create Dockerfile
Let’s first create Dockerfile
. The following Docker image is pretty simple, but it can be more complex than that. The file contains the instructions to extend the cisco-nso-dev:5.5
base image. In the build process, Docker will create a directory and copy NED files from local neds
directory to /var/opt/ncs/packages/
inside the container.
nso-docker$ cd ../nso-dev-image
nso-dev-image$ cat Dockerfile
FROM cisco-nso-dev:5.5
RUN mkdir -p /var/opt/ncs/packages/
COPY neds/*.tar.gz /var/opt/ncs/packages/
Download NEDs
You can download NEDs from DevNet and add these as compressed .tar.gz
files to the neds
directory.
nso-dev-image$ ls neds
cisco-ios-cli-6.69.tar.gz cisco-nx-cli-5.21.tar.gz
Build Docker Image
Now all components are prepared to build an NSO Docker image.
nso-dev-image$ docker build -t nso:5.5-neds .
[+] Building 2.2s (8/8) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 144B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/cisco-nso-dev:5.5 0.0s
=> [1/3] FROM docker.io/library/cisco-nso-dev:5.5 0.1s
=> [internal] load build context 1.4s
=> => transferring context: 83.84MB 1.4s
=> [2/3] RUN mkdir -p /var/opt/ncs/packages/ 0.7s
=> [3/3] COPY neds/*.tar.gz /var/opt/ncs/packages/ 0.2s
=> exporting to image 0.4s
=> => exporting layers 0.4s
=> => writing image sha256:2ee95dcc017a77e3725f984de62c9f896f5c73d8fc00130fd43ca6c0fc2aee6e 0.0s
=> => naming to docker.io/library/nso:5.5-neds 0.0s
After a couple of moments the image is ready. The name of the image is nso
and it is tagged as 5.5-neds
.
nso-dev-image$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nso 5.5-neds 2ee95dcc017a 30 seconds ago 1.48GB
cisco-nso-base 5.5 856ffdeef133 6 days ago 564MB
cisco-nso-base 5.5-foobar 856ffdeef133 6 days ago 564MB
cisco-nso-dev 5.5 04f1f5da57b3 6 days ago 1.4GB
cisco-nso-dev 5.5-foobar 04f1f5da57b3 6 days ago 1.4GB
Push the Image to the Registry
In order to allow other developers to use the same image, the image can be pushed to a registry, such as Docker Hub. To do that, another tag must be added to the image.
nso-dev-image$ docker tag nso:5.5-neds networktocode/nso:5.5-neds
nso-dev-image$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nso 5.5-neds 2ee95dcc017a 3 minutes ago 1.48GB
networktocode/nso 5.5-neds 2ee95dcc017a 3 minutes ago 1.48GB
cisco-nso-base 5.5 856ffdeef133 6 days ago 564MB
cisco-nso-base 5.5-foobar 856ffdeef133 6 days ago 564MB
cisco-nso-dev 5.5 04f1f5da57b3 6 days ago 1.4GB
cisco-nso-dev 5.5-foobar 04f1f5da57b3 6 days ago 1.4GB
Once the image is tagged, it can be pushed to the registry.
nso-dev-image$ docker push networktocode/nso:5.5-neds
From this point, the image is available to anyone that has access to the registry.
Run a Docker Container
To make everything easier and repeatable, you can create a Makefile
, which contains commands to start and purge NSO containers.
Create Makefile
Let’s first create a Makefile
. There are two directives we’ll add to the Makefile
. The first one starts a container, while the other is used to stop and remove the container.
There are a couple of options in the run
directive. The one that should be pointed out is the -v
option. This option maps a directory on a local filesystem to a directory in a container. You can map an existing git repository with NSO services to the directory inside the container. NSO loads services from that directory. Because files are originally located on a local filesystem, you can use preferred tools for development, while using Docker as a runtime environment. In this example the services
directory is mapped.
nso-dev-image$ cat Makefile
.PHONY: run
run:
docker run -itd --name nso \
-v ${PWD}/../services:/nso/run/packages \
-e ADMIN_PASSWORD=admin \
-p 2024:22 \
networktocode/nso:5.5-neds
.PHONY: purge
purge:
docker stop nso
docker rm nso
Start a Container
You can now start a container using the make run
command.
nso-dev-image$ make run
And voila, the container with NSO is running. After a couple of moments the container is ready to use.
nso-dev-image$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3623e63ab2a6 networktocode/nso:5.5-neds "/run-nso.sh" 4 minutes ago Up 4 minutes (healthy) 80/tcp, 443/tcp, 830/tcp, 4334/tcp, 0.0.0.0:2024->22/tcp nso
Connect to NSO
You can now use ssh
to connect to the NSO instance. The port 22
in the container is mapped to the port 2024
on the host. Let’s open an ssh session to port 2024
.
nso-dev-image$ ssh admin@localhost -p 2024
admin@localhost's password:
User admin last logged in 2021-04-26T21:31:21.009543+00:00, to 3623e63ab2a6, from 172.17.0.1 using cli-ssh
admin connected from 172.17.0.1 using ssh on 3623e63ab2a6
admin@ncs>
Verify Packages
You can now work with NSO as you would with any other instance running natively on the system or running on a dedicated server. The following example displays the packages that are deployed in NSO.
admin@ncs> switch cli
admin@ncs# show packages package oper-status
PACKAGE
PROGRAM META FILE
CODE JAVA PYTHON BAD NCS PACKAGE PACKAGE CIRCULAR DATA LOAD ERROR
NAME UP ERROR UNINITIALIZED UNINITIALIZED VERSION NAME VERSION DEPENDENCY ERROR ERROR INFO
-----------------------------------------------------------------------------------------------------------------------------
cisco-ios-cli-6.69 X - - - - - - - - - -
cisco-nx-cli-5.21 X - - - - - - - - - -
l3vpn X - - - - - - - - - -
There are two NEDs that were added during the build process. Another package called l3vpn
is included in my services
directory, which is mapped to the container. You can make changes to the l3vpn
packages locally on the host, and when you are ready, you can reload packages in NSO and test the new functionality.
Cleanup
It is also quite simple to remove the development environment. Since you have the purge
directive in the Makefile
, you can simply run the make purge
command to stop and remove the container.
nso-dev-image$ make purge
docker stop nso
nso
docker rm nso
nso
Conclusion
Using Docker for NSO development brings many advantages. It is easy to set up an environment. Developers only need to run a Docker container, while an image is automatically pulled from a Docker registry. The same image can be used later in test and development environments, and you can be pretty sure that all packages and dependencies are installed. You can avoid “it works on my laptop” issues, because the same runtime environment can be used in development and in production.
The build process requires more steps, but it can be easily automated. Typically, the process will be running as a job in a CI/CD pipeline.
Hopefully this post shows you how to build an NSO development environment using Docker containers.
-Uros
References
Tags :
Contact Us to Learn More
Share details about yourself & someone from our team will reach out to you ASAP!