swift+docker+containers

I thought it might help to review the steps for creating an IBM Container to host a sample server side application written in the Swift programming language. The sample application listens on port 8080 and returns a basic HTML response to clients. Though this is not a production-ready application, it gives you an idea of the different types of server-side applications that you can develop using Swift.

For those who are not familiar with Swift, it’s a modern programming language created by Apple that can be used to develop applications for macOS and Linux. Along with Swift, Apple has implemented the Swift Package Manager (SwiftPM) tool for building Swift applications and specifying their dependencies. It is worth mentioning that the sample server application follows the structure and conventions required by SwiftPM. Hence, SwiftPM can be used for the compilation and creation of the executable sample server program.

Before going over the steps for creating an IBM Container to host the Swift sample server application, let’s briefly discuss some of the reasons why a developer may choose to do so:

  • Using IBM Containers gives you the flexibility to run an application in the cloud without having to make any changes to it. This is possible because IBM Containers leverage Docker. Through IBM Containers, developers can instantiate and run a Docker image on the cloud. They could package an application in a Docker container and have it run in any environment that supports Docker. This makes deploying applications a breeze and portability is no longer just a concept.
  • Packaging an application and all the services that it depends on into a single unit is also possible. Though you probably may want to decompose your application from the services it leverages to separate containers, you could package all components into a single deployable unit for testing the functionality of your application or for building a quick prototype or proof of concept.
  • Swift packages that serve as wrappers for system-level packages (e.g. libhttp-parser) require those packages to be installed before you attempt to build your application using the Swift Package Manager. These system packages can then be specified in the Docker image as dependencies.

Let’s now go over those steps that brought you here! If you follow the following 10 simple steps, you’ll be running the Swift sample application in an IBM Container on Bluemix with minimal effort.

I Install Docker

You should first install that latest version of Docker on your development system. If working on a Mac, you will be installing Docker for Mac, which uses native capabilities on macOS to virtualize the Docker Engine environment (at the time of writing, the latest version of Docker for Mac is 1.12). Once Docker is installed on your system, you should be able to issue Docker commands from your terminal window.

II Install Cloud Foundry Command Line

The second step is to install the latest version of the Cloud Foundry command line on your system. This command line allows you to execute commands against the Bluemix cloud.

III Configure the Cloud Foundry Command Line

Before you attempt to use the Cloud Foundry command line, you should first configure it so that it communicates with your Bluemix region:

  • United Kingdom – https://api.eu-gb.bluemix.net
  • Sydney – https://api.au-syd.bluemix.net
  • US South – https://api.ng.bluemix.net

You specify your Bluemix region URL using the cf api command as shown in the example below:

$ cf api https://api.ng.bluemix.net
Setting api endpoint to https://api.ng.bluemix.net...
OK
...

You should now authenticate and access your Bluemix organization(s) and spaces using the cf login command:

$ cf login
API endpoint: https://api.ng.bluemix.net

Email> john_doe@us.ibm.com
...
IV Install and Configure the IBM Containers Plugin

After completing the configuration of the Cloud Foundry command line, you should install and initialize the IBM Containers plugin. On a macOS system, you can issue the following command to install the plugin:

$ cf install-plugin https://static-ice.ng.bluemix.net/ibm-containers-mac

After installation of the IBM Containers plugin, you need to initialize it by executing the cf ic init command. Please note that any commands that are to be interpreted by the IBM Containers plugin (cf ic <cmd>) should be submitted from a Docker terminal window:

$ cf ic init
Deleting the old configuration file...
Retrieving client certificates from IBM Containers...
...
V Get your namespace

To leverage the IBM Containers plugin, you need to obtain the namespace assigned to your organization. You can find your namespace by issuing the following command:

$ cf ic namespace get
space1

Make note of the namespace value (e.g. space1) returned since you will be using it soon!

VI Pull Docker Image

Our team published two Docker images to Docker Hub under the IBM organization:

  • ibmcom/swift-ubuntu – An Ubuntu v14.04 LTS image that contains the latest Swift binaries [at the time of writing] and its dependencies. From this image, you can create your own custom images to host your applications.
  • ibmcom/swift-helloworld-ubuntu – An image that extends the ibmcom/swift-ubuntu image by adding the Swift sample application.

To deploy your own Swift application to an IBM Container on Bluemix, you can create a new Docker image that builds on top of the ibmcom/swift-ubuntu image. Note that this is exactly what we did for the Swift sample application!

You can find the Dockerfile for the ibmcom/swift-ubuntu image in its GitHub repo. This Dockerfile downloads and installs 1) the Swift binaries and its dependencies and 2) several system level packages that we have found useful in our Swift development efforts.

The contents of the Dockerfile for the ibmcom/swift-helloworld-ubuntu image is shown next (this file is stored in the sample application’s GitHub repo:

FROM ibmcom/swift-ubuntu:latest
MAINTAINER IBM Swift Engineering at IBM Cloud
LABEL Description="Image to run the swift-helloworld sample application inside an IBM Container on Bluemix."

EXPOSE 8080

RUN mkdir /root/swift-helloworld

ADD Sources /root/swift-helloworld
ADD Package.swift /root/swift-helloworld
ADD LICENSE /root/swift-helloworld
ADD .swift-version /root/swift-helloworld

# Build Swift Started App
RUN cd /root/swift-helloworld && swift build

USER root
CMD ["/root/swift-helloworld/.build/debug/Server"]

As we can see above, the source code for the Swift sample application is added and compiled during the creation of the Docker image. We can also see that the CMD instruction in the Dockerfile contains the command that starts the sample Swift application.

Let’s now download the ibmcom/swift-helloworld-ubuntu image from Docker Hub using the following command:

$ docker pull ibmcom/swift-helloworld-ubuntu:latest
VII Tag Docker Image

The next step is to tag the ibmcom/swift-helloworld-ubuntu Docker image with your private Bluemix registry and an image name. Tagging an image with the registry information lets Docker know that you intend to push that image to the Bluemix registry instead of Docker Hub:

docker tag ibmcom/swift-helloworld-ubuntu <bluemix registry>/<namespace>/swift-helloworld-ubuntu

You should replace <namespace> with the namespace assigned to your organization and <bluemix registry> with the name of the registry for your Bluemix region. For instance, for the US South region, the name of the registry is registry.ng.bluemix.net.

Note that executing the docker tag command creates a reference to the original Docker image. You can verify this by executing the docker images command (note that the IMAGE ID values are the same for both images):

$ docker images
REPOSITORY                                               TAG     IMAGE ID       CREATED         VIRTUAL SIZE
registry.ng.bluemix.net/space1/swift-helloworld-ubuntu   latest  d5182f1d33b1   21 hours ago    1.248 GB
ibmcom/swift-helloworld-ubuntu                           latest  d5182f1d33b1   21 hours ago    1.248 GB
VIII Push Docker Image to Bluemix Registry

We are now ready to push the tagged image to Bluemix by issuing the following command:

$ docker push <bluemix registry>/<namespace>/swift-helloworld-ubuntu

As before, make sure you replace <namespace> with your namespace and <bluemix registry> with the name of the registry for your Bluemix region.

IX Obtain a Public IP Address

To access an IBM Container, a public IP address must be assigned to it. You can request an IP address using the IBM Containers plugin by issuing the following command:

$ cf ic ip request
OK
The IP address "X.X.X.X" was obtained.
X Create IBM Container

We are now ready to create an IBM Container that hosts the Swift sample application. Creating the IBM Container and assigning the IP address you obtained in the previous step can be done by executing one simple command:

$ cf ic run -p <ip_address>:8080:8080 --name swift-helloworld <bluemix registry>/<namespace>/swift-helloworld-ubuntu

Please note that you should replace <ip_address>, <bluemix registry>, and <namespace> with the corresponding values.

That’s it! You should now have an IBM Container that runs the Swift sample application. If you access your IBM Containers dashboard on Bluemix, you should see an entry for the swift-helloworld container you just created. You can click that entry to verify that the container is up and running. Also, using a browser, you can test that the Swift sample server is indeed running by going to http://<ip_address>:8080, where <ip_address> is the IP address you assigned to your IBM Container. The “Hello from Swift on Linux!” message should be displayed on your browser.

These are very exciting times for Swift developers. Initially Swift was a language used only for the development of iOS applications. Now, you can also use it to develop the back-end components that iOS and other mobile platforms can leverage to deliver unique experiences and functionality to your users!

References

Ricardo Olivieri, Senior Software Engineer, IBM Swift Engineering at IBM Cloud

6 Comments on "10 Steps To Running a Swift App in an IBM Container"

  1. Alexei Karve March 01, 2016

    Thank you for the detailed article. Very helpful! Couple of things to note: 1) When we start the container first time, the networking is still not complete when the start-swift-helloworld.sh tries to download the code from git. So the container stops. I had to start the container again to allow the git clone to complete.
    2) Add the Content-Length in ~/swift-helloworld/Sources/Server/main.swift to avoid the “curl: (56) Recv failure: Connection reset by peer”
    let httpResponse = “HTTP/1.0 200 OK\n” +
    “Content-Type: text/html\n” +
    “Content-Length: 52\n\n” +
    “Hello from Swift on Linux!”
    Helped me create my first swift program and also work with Fibinacci and other examples.

    • Ricardo Olivieri March 01, 2016

      Alexei, thanks for your comment! This is very useful. I have updated the blog post above and the Docker image as well. I had noticed some intermittent issues with the container and now I understand why (the networking configuration was just not ready to be used).

  2. Robert Brown November 04, 2016

    I walked through the steps above and noted 2 things
    1. docker tag -f ibmcom/swift-runtime //swift-runtime_____ produces an error, but seems to run correctly without the -f
    2. once pushed I am unable to connect to IP provided:9080 ______connection refused error
    3. in Bluemix the status contiues as Networking and Policy Status Incomplete_____Going into View reports shows 4 errors in the sysctl program. If this is the issue, I certainly don’t know how to resolve it.

    • Ricardo Olivieri November 06, 2016

      Hello, thanks for checking out this blog post! This was published several months ago and some of its contents became outdated. I just updated it and also updated the docker image (note that the name of the docker image changed as well as the repo that hosts the docker image code). The docker image was successfully instantiated as an IBM Container on Bluemix. If after reviewing the contents of the updated blog post, you still run into issues, please let us know. Thanks!

      • Robert Brown November 07, 2016

        Ok, thanks for the update. The image is now loading and got out ofthe “networking” mode. For you information there are now several new errors being reported on the container image while running in Bluemix.
        1. Policy violation Failed
        Image has installed packages with known vulnerabilities
        2. Vulnerable Packages ibcurl3-gnutls, libcurl3 Corrective Action Upgrade libcurl3-gnutls to at least version 7.35.0-1ubuntu2.10, Upgrade libcurl3 to at least version 7.35.0-1ubuntu2.10
        3. Valneable Package libdbus-1-3
        3116-1
        Several security issues were fixed in DBus.
        Corrective Action Upgrade libdbus-1-3 to at least version 1.6.18-0ubuntu4.4
        5. Security Violations sysctl
        /etc/sysctl.conf
        No
        /etc/sysctl.conf containing many parameters that affect system.
        /etc/sysctl.conf does not exist per rule.
        No value

        I am not sure you can get these corrected for a “Hello World” type of example. Maybe an additional set of steps on how to correct these types of errors in the container image would help.

        • Ricardo Olivieri November 08, 2016

          Thanks Robert for sharing the information above. Yes, there is a new recent vulnerability that requires upgrading the libdbus-1-3 package. If you pull down the latest version of the ibmcom/swift-helloworld-ubuntu image, this issue should be now gone. As for the warning about certain files (/etc/sysctl.conf) not being present, we have raised an issue to address them (these seem to be false negatives since the files are present in the image).

Join The Discussion

Your email address will not be published. Required fields are marked *