Docker is an open-source container engine and a set of tools to compose, build, ship, and run distributed applications. The Docker container engine provides for the execution of applications composed as Docker images. Docker hub and Docker private registries are services that enable sharing of Docker images. The Docker command-line tool enables developers to build Docker images, to work with Docker hub and private registries, and to instantiate Docker images as containers in a Docker container engine. The relatively small size of Docker images—compared with VM images—and their portability enable developers to move applications seamlessly between test, quality assurance, and production environments, increasing the agility of application development and operations.

Although Docker has been a very popular technology for some time, until recently its ecosystem has been primarily restricted to x86 architectures and the Linux operating system. Systems such as IBM POWER Linux, IBM z/Linux, and ARM Linux require a porting effort to support Docker. In this tutorial, we describe how to use Docker on the POWER Linux platform. We also illustrate the process of building Docker from scratch on the POWER platform, a process developers on other platforms can use as a template for enabling Docker on their own platforms.

In this tutorial, we explain how to use Docker on the POWER Linux platform and how to compile Docker binaries using gccgo as the compiler back end. Also, we show how to build a Docker private registry to host private Docker images.

What you’ll need to build your application

  • Docker 1.3.0 (see Step 1)
  • Docker registry (see Step 3)
  • The gccgo tool (see Build gccgo)
  • Ubuntu installed on a POWER machine

Step 1. Install the binary package of Docker on POWER

The Debian package file of Docker 1.3.0 on POWER is available courtesy of the University of Campinas in Brazil at: ftp://ftp.unicamp.br/pub/linuxpatch/docker-ppc64/ubuntu/14_10/docker.io-1.3.0-dev_ppc64el.deb.

Here are the commands to download and install the package. You can verify the installation using the dpkg -l command.


$ curl ‑o docker.io‑1.3.0‑dev_ppc64el.deb \
    'ftp://ftp.unicamp.br/pub/linuxpatch/docker‑ppc64/ubuntu/14_10/docker.io‑1.3.0‑dev_ppc64el.deb'
$ sudo dpkg ‑i docker.io‑1.3.0‑dev_ppc64el.deb
$ dpkg ‑l 'docker∗'
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf‑files/Unpacked/halF‑conf/Half‑inst/trig‑aWait/Trig‑pend
|/ Err?=(none)/Reinst‑required (Status,Err: uppercase=bad)
||/ Name                  Version         Architecture    Description
+++‑=====================‑===============‑===============‑=========================================
ii  docker.io‑1.3.0‑dev   1.3.0‑dev‑20141 ppc64el         Linux container runtime
...

Step 2. Create an Ubuntu base image for POWER

As of this writing, no image for POWER is available in the public Docker Hub Registry. You will, therefore, need to create an Ubuntu base image for POWER before running a Docker container.

Here is the procedure for creating a minimal image of Ubuntu 14.04 ( Trusty). You can create an Ubuntu 14.10 ( Utopic) image the same way by substituting utopic and 14.10 for trusty and 14.04, respectively.


$ sudo apt‑get install ‑y debootstrap
$ curl ‑o debootstrap.sh \
    https://raw.githubusercontent.com/docker/docker/master/contrib/mkimage/debootstrap
$ chmod 755 debootstrap.sh
$ sudo ./debootstrap.sh ubuntu ‑‑components=main,universe trusty
$ sudo tar ‑C ubuntu ‑c . | docker import ‑ ubuntu:14.04
$ docker tag ubuntu:14.04 ubuntu:trusty
$ docker tag ubuntu:14.04 ubuntu:latest
$ sudo rm ‑fr ubuntu

Note: Don’t forget to add the latest tag to the image. Docker searches the image with the latest tag when the specified image name does not have a tag name. If there is no image with a latest tag in the local repository, Docker tries to download it from the public Docker Hub Registry, which contains images for the x86 platform only. Such images will not work. Because it is common that publicly available Dockerfiles do not specify tags in their base image names at the FROM line, you should keep a base image tagged with latest in the register.

You can check the target architecture of an image using the docker inspect command. For example, images for the POWER platform have metadata of "ppc64":


$ uname ‑m
ppc64le
$ docker inspect f3b2472e2593 | grep Architecture
    "Architecture": "ppc64",

On an x86 machine, the metadata is "amd64":


$ uname ‑m
x86_64
$ docker inspect eca7633ed783 | grep Architecture
    "Architecture": "amd64",

You can verify that the Docker image is created successfully using the docker images command.


$ docker images
REPOSITORY         TAG                 IMAGE ID            CREATED                 VIRTUAL SIZE
ubuntu                     14.04              f3b2472e2593        About a minute ago   188.3 MB
ubuntu                     latest              f3b2472e2593        About a minute ago   188.3 MB
ubuntu                     trusty              f3b2472e2593        About a minute ago   188.3 MB

Now you can run the Docker container like other platforms. The docker run command starts a container with a randomly generated host name and runs the hostname command in it.


$ hostname
myhost.mydomain
$ docker run ubuntu hostname
bf4ab3d25d4d

Step 3. Build your own Docker registry on POWER

The Docker Hub Registry hosted by www.docker.io is a key component that differentiates Docker from other container-based technologies. Users can easily share their images through the public registry. The registry also distributes official images, which consist of a wide variety of trusted images of free operating systems such as Ubuntu, middleware such as NGINX and MongoDB, and applications such as WordPress. Unfortunately, these images are built for x86 platforms, and there is no public registry that distributes images for POWER at this time.

You can, however, share your image with your friends and colleagues if you run a registry server yourself. This section explains the steps for building and running your own registry server.

Docker registry is a Python application and its source code is available as a GitHub project, so you can run your own registry server on POWER machines by building it. Docker registry runs both in a Docker container and outside of Docker. This tutorial shows the procedure for running Docker registry in a container. Note that you should not follow the quick-start instructions in the README.md file on the Docker registry site. Those instructions assume the use of a Docker image in the public registry.

Before building the image, make sure you have an Ubuntu image with a ubuntu:14.04 tag. The Dockerfile refers to that tag.

  1. The first step is to download the source code. We will use the stable version of 0.9.1.
    
    $ cd ~
    $ git clone https://github.com/docker/distribution
    $ cd ~/docker‑registry
    $ git checkout ‑q 0.9.1
  2. Next, you need to update the config.guess and config.sub files in the gevent-1.0.1 package because that package contains old versions of these config.* files, which do not recognize ppc64le. To do this, follow the steps below to apply a patch to docker-registry/Dockerfile:
    
    $ cat ~/docker‑registry/docker‑registry.patch
    ∗∗∗ docker‑registry.orig/Dockerfile     Sat Jan 31 07:20:32 2015
    ‑‑‑ docker‑registry/Dockerfile  Sat Jan 31 13:12:11 2015
    ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    ∗∗∗ 19,24 ∗∗∗∗
    ‑‑‑ 19,27 ‑‑‑‑
              libssl‑dev \
              liblzma‑dev \
              libevent1‑dev \
    + #Install deps for building gevent
    +         curl \
    +         cython \
          && rm ‑rf /var/lib/apt/lists/∗
    
      COPY . /docker‑registry
    ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    ∗∗∗ 27,32 ∗∗∗∗
    ‑‑‑ 30,45 ‑‑‑‑
      #Install core
      RUN pip install /docker‑registry/depends/docker‑registry‑core
    
    + #Install gevent 1.0.1 using updated config.guess and config.sub
    + RUN curl https://pypi.python.org/packages/source/g/gevent/gevent‑1.0.1.tar.gz | tar ‑xzf ‑ ‑C / \
    +     && curl ‑o /gevent‑1.0.1/libev/config.guess \
    +          'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' \
    +     && curl ‑o /gevent‑1.0.1/libev/config.sub \
    +          'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' \
    +     && cp ‑pf /gevent‑1.0.1/libev/config.guess /gevent‑1.0.1/c‑ares/config.guess \
    +     && cp ‑pf /gevent‑1.0.1/libev/config.sub /gevent‑1.0.1/c‑ares/config.sub \
    +     && pip install /gevent‑1.0.1
    +
      #Install registry
      RUN pip install file:///docker‑registry#egg=docker‑registry[bugsnag,newrelic,cors]
  3. After applying this patch, build the image using the docker build command.
    
    $ cd ~/docker‑registry
    $ patch ‑p1 < docker‑registry.patch
    $ docker build ‑t registry .
  4. Now, you can start a local registry server in the same manner as the description in the README.md file in the Docker-registry project. We recommend that you specify storage options. Otherwise, the storage for the registry is created in the container, and it will disappear when the container finishes.
    
    $ docker run ‑p 5000:5000 registry
  5. A local registry can be located by the host name and port number. For pushing an image to a local registry server, you need to add a tag :/ to the image, so Docker can recognize the full registry location. For more information, see “How to Use Your Own Registry.”
    
    $ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    registry                  latest              82b144bfff96        17 minutes ago      428.1 MB
    ubuntu                   14.04               f3b2472e2593        2 days ago          188.3 MB
    ubuntu                   latest              f3b2472e2593        2 days ago          188.3 MB
    ubuntu                   trusty              f3b2472e2593        2 days ago          188.3 MB
    $ docker tag f3b2472e2593 localhost:5000/ubuntu
    $ docker images
    REPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    registry                     latest              82b144bfff96        2 hours ago         428.1 MB
    localhost:5000/ubuntu        latest              f3b2472e2593        2 days ago          188.3 MB
    ubuntu                       14.04               f3b2472e2593        2 days ago          188.3 MB
    ubuntu                       latest              f3b2472e2593        2 days ago          188.3 MB
    ubuntu                       trusty              f3b2472e2593        2 days ago          188.3 MB
    
  6. Now you can push the Ubuntu image by specifying the host name, port number, and image name. You can also search images in the local registry server.
    
    $ docker push localhost:5000/ubuntu
    The push refers to a repository [localhost:5000/ubuntu] (len: 1)
    Sending image list
    Pushing repository localhost:5000/ubuntu (1 tags)
    f3b2472e2593: Image successfully pushed
    Pushing tag for rev [f3b2472e2593] on {http://localhost:5000/v1/repositories/ubuntu/tags/latest}
    $ docker search localhost:5000/ubuntu
    NAME             DESCRIPTION   STARS     OFFICIAL   AUTOMATED
    library/ubuntu                 0

See the README.md of the Docker registry project for additional information.

Step 4. Build an environment for Docker on POWER

If you want to try a newer version of Docker, such as 1.4.1, you need to build it from the source code. This section shows the tools available for use on the POWER platform. (This tutorial assumes that the operating system is Ubuntu 14.04. You may also be able to use Debian on POWER using similar steps, but that procedure is out of the scope of this tutorial.)

The source code of Docker is written in the Go programming language. The Go language (also referred to as golang) is a compiled programming language developed by Google Inc. Its official compiler, gc, and supporting tools, such as go commands, are freely available on the Internet. The go command is the front-end command for running common tasks, such as building a source tree, package management, unit testing, and debugging.

Unfortunately, the official Go tool chain supports only Linux, Mac OS X, FreeBSD, and Windows on the x86 and ARM processors. For other platforms, such as POWER Linux, you need an alternative tool chain. The gcc-based Go compiler gccgo is the alternative. It supports any platform that gcc supports, including POWER Linux and z/Linux as well as x86 and ARM Linux.

Build gccgo

This section explains the procedure for building gccgo on Ubuntu on POWER. Note that Ubuntu on POWER supports only the little-endian POWER platform.

  1. Install the necessary packages as follows:
    
    
    $ sudo apt‑get install ‑y build‑essential libgmp‑dev libgmp3‑dev libmpfr‑dev libmpc‑dev flex subversion
    $ sudo apt‑get install ‑y git mercurial libsqlite3‑dev lxc libffi‑dev pandoc ruby ruby‑dev curl
    $ sudo apt‑get install ‑y aufs‑tools btrfs‑tools libdevmapper‑dev libapparmor‑dev
    $ sudo apt‑get install ‑y linux‑image‑extra‑uname ‑r
    $ sudo gem install fpm
    The latest release of Docker is 1.4.1; Version 1.5.0 is under development as this tutorial is being written. Docker versions 1.4.1 and earlier assume that it is compiled with the Go compiler Version 1.3; Docker 1.5.0 will assume Go 1.4. The gccgo revision that corresponds to Go 1.3 is 219550; for Go 1.4, it is 219661. Download the revision corresponding to the Docker version you are building. This tutorial shows the procedure for building gccgo revision 219550 for building Docker 1.4.1.
  2. You need to apply a patch to gccgo that has not been integrated to either of these revisions. After applying the patch, you can build gccgo by running configure, make, and make install commands.
    
    $ mkdir ~/gccgo
    $ cd ~/gccgo
    $ svn co ‑q ‑‑revision 219550 svn://gcc.gnu.org/svn/gcc/trunk src
    $ curl 'https://gcc.gnu.org/bugzilla/attachment.cgi?id=33966&action=diff&context=patch&format=raw' | \
        sed 's/cgo_unix\.go\.orig/cgo_unix\.go/' | patch ‑p1
    $ mkdir bld
    $ cd bld
    $ ../src/configure ‑‑enable‑threads=posix ‑‑enable‑shared ‑‑enable‑__cxa_atexit \
        ‑‑enable‑languages=c,c++,go ‑‑enable‑secureplt ‑‑enable‑checking=yes ‑‑with‑long‑double‑128 \
        ‑‑enable‑decimal‑float ‑‑disable‑bootstrap ‑‑disable‑alsa ‑‑disable‑multilib \
        ‑‑prefix=/usr/local/gccgo
    $ make
    $ sudo make install
  3. After installing gccgo, make sure the following environment variables are set in your shell:
    
    $ export PATH=/usr/local/gccgo/bin:$PATH
    $ export LD_LIBRARY_PATH=/usr/local/gccgo/lib64:$LD_LIBRARY_PATH

Build Docker on POWER from the source code

This tutorial shows the procedure for building Docker outside a Docker container, unlike the official build procedure on the x86 platform.

Prepare the Docker source code for building with gccgo

  1. First, you need to clone the Docker source code. This example assumes that the work directory is under ~/docker.work, and the source code is cloned to the ~/docker.work/src/github.com/docker/docker sub-directory. Do not change the path src/github.com/docker/docker because it is hard-coded in the source code as an include path. Here is the procedure for cloning the Docker source code of version 1.4.1:
    
    $ mkdir ‑p ~/docker.work/src/github.com/docker
    $ cd ~/docker.work/src/github.com/docker
    $ git clone https://github.com/moby/moby
    $ cd docker
    $ git checkout ‑q v1.4.1
  2. You now need to apply patches to the original source code if you are building Docker with gccgo. IBM’s Srini Brahmaroutu maintains some source trees that can be built with gccgo on POWER and z System. You can extract a set of patches using his GitHub repository:
    
    $ cd ~/docker.work/src/github.com/docker/docker
    $ curl
    'https://github.com/brahmaroutu/docker/compare/docker:v1.4.1...gccgo_power_141.patch' | \
        patch ‑p1
  3. After preparing the source code, make sure the following environment variables are set in your shell. GOPATH is an include path for the go source code, and a wrong value results in the building of incorrect source code.
    
    $ export GOPATH=~/docker.work:~/docker.work/src/github.com/docker/docker/vendor
    $ export CGO_ENABLED=1

Build the go-md2man tool and LVM2 library

The next steps before building Docker are to build the tool and the library used in the Docker’s build script: go-md2man and the statically linked library of LVM2. These steps are required on any platform, though they are hidden in the Dockerfile when we build Docker using the Docker container.

  1. go-md2man is a tool to generate UNIX man pages from documents in markdown format. Here is the procedure for building go-md2man:
    
    $ cd ~/docker.work/src
    $ git clone ‑b v1 https://github.com/cpuguy83/go‑md2man.git github.com/cpuguy83/go‑md2man
    $ git clone ‑b v1.2 https://github.com/russross/blackfriday github.com/russross/blackfriday
    $ go build ‑gccgoflags '‑static‑libgo ‑static‑libgcc' github.com/cpuguy83/go‑md2man
    $ cp ‑p go‑md2man /usr/local/gccgo/bin
  2. Docker requires LVM2 libraries of the statically linked library to enable devmapper support. You cannot use the libraries included in the package for apt-get because they are for dynamically linked binaries. Here is the procedure for building LVM2:
    
    $ cd ~
    $ git clone ‑‑no‑checkout https://git.fedorahosted.org/git/lvm2.git lvm2
    $ cd ~/lvm2
    $ git checkout ‑q v2_02_103
    $ curl ‑o autoconf/config.guess \
        'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
    $ curl ‑o autoconf/config.sub \
        'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
    $ ./configure ‑‑enable‑static_link ‑‑prefix /usr/local/lvm2
    $ make device‑mapper
    $ sudo make install_device‑mapper
  3. After installing the LVM library, make sure the following environment variables are set in your shell:
    
    $ export C_INCLUDE_PATH=/usr/local/lvm2/include
    $ export LIBRARY_PATH=/usr/local/lvm2/lib:$LIBRARY_PATH
    $ export LD_LIBRARY_PATH=/usr/local/lvm2/lib:$LD_LIBRARY_PATH

Build Debian package of Docker

Now, you are ready to build the Docker source code. Parameters to the project/make.sh script specify the build targets: binary builds executable files, and ubuntu creates a Debian package. All targets must be specified in a single invocation of make.sh. If you build Docker 1.3, run hack/make.sh instead of project/make.sh because the hack/ directory was renamed in version 1.4.


$ cd ~/docker.work/src/github.com/docker/docker
$ export DOCKER_BUILDTAGS="apparmor selinux btrfs_noversion"
$ project/make.sh binary ubuntu

Debian packages will be created in the bundles/1.4.1-dev/ubuntu directory when the build succeeds. There are two .deb files in this directory, but the larger one is the package to install. You can install it using the dpkg -i command:


$ ls bundles/1.4.1/
binary  ubuntu
$ ls ‑s bundles/1.4.1/ubuntu/
total 8524
8520 lxc‑docker‑1.4.1_1.4.1‑20150201030418‑5bc2ff8‑dirty_ppc64el.deb
   4 lxc‑docker_1.4.1‑20150201030418‑5bc2ff8‑dirty_ppc64el.deb
$ sudo dpkg ‑i bundles/1.4.1/ubuntu/lxc‑docker‑1.4.1_1.4.1‑20150201030418‑5bc2ff8‑dirty_ppc64el.deb
Selecting previously unselected package lxc‑docker‑1.4.1.
(Reading database ... 26658 files and directories currently installed.)
Preparing to unpack .../lxc‑docker‑1.4.1_1.4.1‑20150201030418‑5bc2ff8‑dirty_ppc64el.deb ...
Unpacking lxc‑docker‑1.4.1 (1.4.1‑20150201030418‑5bc2ff8‑dirty) ...
Setting up lxc‑docker‑1.4.1 (1.4.1‑20150201030418‑5bc2ff8‑dirty) ...
Processing triggers for ureadahead (0.100.0‑16) ...
$ sudo dpkg ‑l '∗docker∗'
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf‑files/Unpacked/halF‑conf/Half‑inst/trig‑aWait/Trig‑pend
|/ Err?=(none)/Reinst‑required (Status,Err: uppercase=bad)
||/ Name                  Version         Architecture    Description
+++‑=====================‑===============‑===============‑================================================
ii  lxc‑docker‑1.4.1      1.4.1‑201502010 ppc64el         Linux container runtime
...
$ docker version
Client version: 1.4.1
...

If you have installed Docker 1.3.0 downloaded from unicamp.br, you need to uninstall it before installing the built package:


$ sudo dpkg ‑r docker.io‑1.3.0‑dev

Conclusion

In this tutorial, we have described how to use Docker on the POWER Linux platform. We also described how to compile Docker binaries using gccgo as the compiler back end. We explained how to build a Docker private registry to host private Docker images. Finally, here is a list of additional resources where you can find further information on this topic.

Docker User Guide https://docs.docker.com/userguide/

Discussion on muti-archtecture support in Dockerfile https://github.com/moby/moby/issues/10063

Discussion on gccgo support for building Docker https://github.com/moby/moby/issues/9207

Tutorial of the Go Programming Language https://golang.org/doc/