Play Docker(1)

For playing docker and prepare for my presentation, I wrote this series and try to record my tips on playing docker.

Background

I created a droplet on DigitalOcean.com, which is running CentOS 7, the memory is only 512M, with one core and 20G size disk, which means its caculation resource is pretty limited, so heavy tasks should be avoid, like building.
Since the memory is only 512M, I allocated 1G swapfile to the machine.
The usable disk is 17G now.

Docker Installation

Docker is already part of CentOS7, so install it directly via:

$ sudo yum install -y docker
$ which docker
/usr/bin/docker

Start the service and make it default:

$ sudo service docker start
Redirecting to /bin/systemctl start  docker.service
$ sudo chkconfig docker on
Note: Forwarding request to 'systemctl enable docker.service'.
ln -s '/usr/lib/systemd/system/docker.service' '/etc/systemd/system/multi-user.target.wants/docker.service'

Now even if you restart the machine, the service would be automatically started together with system boot.

First Instance

Pull the debian back:

$ sudo docker pull debian
Pulling repository debian
c90d655b99b2: Download complete 
511136ea3c5a: Download complete 
30d39e59ffe2: Download complete 
Status: Downloaded newer image for debian:latest
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
debian              wheezy              c90d655b99b2        8 hours ago         85.12 MB
debian              7                   c90d655b99b2        8 hours ago         85.12 MB
debian              7.8                 c90d655b99b2        8 hours ago         85.12 MB
debian              latest              c90d655b99b2        8 hours ago         85.12 MB

Install the lsb_release, then run different tags, all of them are the same:

$ sudo docker run -i -t debian:7.8 /bin/bash
xxxxxxx # lsb_release -a 
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 7.8 (wheezy)
Release:	7.8
Codename:	wheezy

Destroy Container

List all of the container via sudo docker ps -a, then destroy the container via sudo docker rm xxxxxx while xxxxxx is the container ID.
Play magic, one line for remove all of the containers:

$ sudo docker rm `sudo docker ps -a -q`
16d606046c24
65ceffcf4a7b
dfbc6d0fa051
1dd18dbf8b9c
66c931879c2c
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Remove The Images

One line for remove all of the ununsed images:

$ sudo docker images -q
c90d655b99b2
c90d655b99b2
c90d655b99b2
c90d655b99b2
$ sudo docker rmi `sudo docker images -q`
Untagged: debian:7
Untagged: debian:7.8
Untagged: debian:latest
Untagged: debian:wheezy
Deleted: c90d655b99b2ec5b7e94d38c87f92dce015c17a313caeaae0e980d9b9bed8444
Deleted: 30d39e59ffe287f29a41a3f8bd70734afc8728329e3289945cbdc5bbf07cd980
Deleted: 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158
Error response from daemon: No such image: c90d655b99b2
Error response from daemon: No such image: c90d655b99b2
Error response from daemon: No such image: c90d655b99b2
2015/01/27 21:14:01 Error: failed to remove one or more images
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

But it would be add a pipe like sudo docker images -q | uniq

Connect To Existing Running Container

Docker 1.3 Ways

From Docker 1.3, we could use docker exec -it for attaching to running container:

$ sudo docker run -i -t centos /bin/bash
[root@1f9005d495c6 /]# 
$ sudo docker ps
[sudo] password for Trusty: 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
1f9005d495c6        centos:7            "/bin/bash"         8 minutes ago       Up 8 minutes                            sick_jones          
$ sudo docker exec -it 1f9005d495c6 /bin/bash
[root@1f9005d495c6 /]# 

But the Container’s lifecycle is controlled by the first instance, docker exec only attached to, this means if you exit the container, all of the docker exec tty will be shutdown.

Nsenter Ways

First use docker inspect for get the PID.

$ sudo docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8337ea52cfd1        centos:7            "/bin/bash"         4 seconds ago       Up 4 seconds                            pensive_blackwell   
$ PID=$(sudo docker inspect --format {{.State.Pid}} 8337ea52cfd1)
$ echo $PID
3951

Use nsenter for enter the PID’s namespace:

$ sudo nsenter --target $PID --mount --uts --ipc --net --pid
[root@8337ea52cfd1 /]#

Lazy Wrap of Nsenter Ways

Just visit:
https://github.com/jpetazzo/nsenter, download the docker-enter, and place it in the right place:

$ sudo docker ps 
[sudo] password for Trusty: 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8337ea52cfd1        centos:7            "/bin/bash"         11 minutes ago      Up 11 minutes                           pensive_blackwell   
$ sudo docker-enter pensive_blackwell ls -la
...
$ sudo docker-enter 8337ea52cfd1 /bin/bash
[root@8337ea52cfd1 /]# 

Docker Attach

If you attach to the container, you must remember, better you use tmux holding the whole instance.

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
057435c2f1cb        centos:7            "/bin/bash"         5 seconds ago       Up 4 seconds                            evil_kirch          
$ sudo docker attach 057435c2f1cb
[root@057435c2f1cb /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  selinux  srv  sys  tmp  usr  var

Once you quit from the “attached” tty, the origin tty will also quit.

More System Info

Use docker info to get more detailed system infos:

$ sudo docker info
Containers: 3
Images: 3
Storage Driver: devicemapper
 Pool Name: docker-253:1-397799-pool
 Pool Blocksize: 65.54 kB
 Data file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata
 Data Space Used: 563.1 MB
 Data Space Total: 107.4 GB
 Metadata Space Used: 1.069 MB
 Metadata Space Total: 2.147 GB
 Library Version: 1.02.84-RHEL7 (2014-03-26)
Execution Driver: native-0.2
Kernel Version: 3.10.0-123.8.1.el7.x86_64
Operating System: CentOS Linux 7 (Core)
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              7                   8efe422e6104        3 weeks ago         224 MB
centos              centos7             8efe422e6104        3 weeks ago         224 MB
centos              latest              8efe422e6104        3 weeks ago         224 MB
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
057435c2f1cb        centos:7            "/bin/bash"         3 minutes ago       Exited (0) 54 seconds ago                        evil_kirch          
8337ea52cfd1        centos:7            "/bin/bash"         21 minutes ago      Exited (127) 4 minutes ago                       pensive_blackwell   
1f9005d495c6        centos:7            "/bin/bash"         34 minutes ago      Exited (0) 24 minutes ago                        sick_jones          

Commit Changes

Install the vim in the running container:

$ sudo docker run -i -t centos /bin/bash
[sudo] password for Trusty: 
[root@ea29113ba0e1 /]# which vim
/usr/bin/which: no vim in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin)
[root@ea29113ba0e1 /]# yum install -y vim

In another container, commit the changes:

$ sudo docker commit ea29113ba0e1 vim_installed
54cebb627e37600e81a832616eb3253af5dd26d0d248b9a9251e23bc8c93567d
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
vim_installed       latest              54cebb627e37        12 seconds ago      362.6 MB
centos              latest              8efe422e6104        3 weeks ago         224 MB
centos              7                   8efe422e6104        3 weeks ago         224 MB
centos              centos7             8efe422e6104        3 weeks ago         224 MB

Next time if you want to use the vim installed images, simply run:

$ sudo docker run -it vim_installed /bin/bash
[root@4b76f0c7bc46 /]# which vim
/usr/bin/vim

Job Controlling

Use environment variables for recording the running job:

$ JOB=$(sudo docker run -d vim_installed /bin/sh -c "while true; do echo Hello World; sleep 1; done")
$ echo $JOB
5dcb0884d27077e84ef4fea7fc0b3e8151657e92e0c2d4d1e33f84483715dfb9

Examine the log from the app’s output:

$ sudo docker logs $JOB
$ sudo docker logs --follow $JOB

Add –follow will continue to view the log output.
Stop the running container:

$ sudo docker stop $JOB
5dcb0884d27077e84ef4fea7fc0b3e8151657e92e0c2d4d1e33f84483715dfb9

Start the stopped container:

$ sudo docker start $JOB
5dcb0884d27077e84ef4fea7fc0b3e8151657e92e0c2d4d1e33f84483715dfb9

Or Restart:

$ sudo docker restart $JOB

Or kill:

$ sudo docker kill $JOB

Notice the kill exit code is -1:

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$ sudo docker ps -a
CONTAINER ID        IMAGE                  COMMAND                CREATED             STATUS                        PORTS               NAMES
5dcb0884d270        vim_installed:latest   "/bin/sh -c 'while t   9 minutes ago       Exited (-1) 8 seconds ago                         focused_pike 

sudo docker rm $JOB will remove the job.

Play Docker(2)

Continue, but this time for further topics:

Export/Import

From https://registry.hub.docker.com/ to find more interesting images:
Use opensuse:

$ sudo docker pull opensuse
$ sudo docker images
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
opensuse            latest              758c78b4040c        3 weeks ago         622.7 MB
opensuse            13.2                758c78b4040c        3 weeks ago         622.7 MB
opensuse            harlequin           758c78b4040c        3 weeks ago         622.7 MB
$ sudo docker run -i -t opensuse /bin/bash
:/ # yzpper in vim

After installed commit the changes and verify:

$ sudo docker run -i -t install_vim_suse /bin/bash
:/ # which vim
/usr/bin/vim

Now we export it to tar file:

$ sudo docker ps
$ sudo docker export 7b594d048b0b>~/opensuse_vim.tar
$ ls -l -h ~/opensuse_vim.tar
-rw-r--r--  1 Trusty root 704M Jan 27 22:39 opensuse_vim.tar

Made changes after we exported the tar file.

$ sudo tar xvf opensuse_vim.tar
$ sudo touch ./root/I_Want_You_See_This_File
$ sudo rm -f opensuse_vim.tar
$ sudo tar cvf opensuse_vim_modified.tar ./*
$ ls -l -h *.tar
-rw-r--r-- 1 root root 704M Jan 27 22:45 opensuse_vim_modified.tar

Import the tar file into the images:

$ sudo cat ./opensuse_vim_modified.tar | sudo docker import - Trusty/opensuse_vim_modified:v1.0
c18f7e43c4197a2a1a614a1ee91c6d8f0e06a6d7593ca94354303e3760e389a7
$ sudo docker images
$ sudo docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
Trusty/opensuse_vim_modified   v1.0                c18f7e43c419        47 seconds ago      724 MB
$ sudo docker run -i -t Trusty/opensuse_vim_modified:v1.0 /bin/bash
:/ # ls /root/
I_Want_You_See_This_File  bin

Now we could see the modified files has been ported to our running containers.
Even you could docker import from remote url:

$sudo docker import http://example.com/exampleimage.tgz example/imagerepo

Networking

Run app inside the container

First pull the images training/webapp back:

$ sudo docker pull training/webapp
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
training/webapp     latest              31fa814ba25a        8 months ago        278.6 MB

Quickly enter the container and examine what’s inside the pandora box:

$ sudo docker run -i -t training/webapp /bin/bash
root@f19ca7c18763:/opt/webapp# cat /etc/issue
Ubuntu 12.04.4 LTS \n \l

root@f19ca7c18763:/opt/webapp# ls
Procfile  app.py  requirements.txt  tests.py
root@f19ca7c18763:/opt/webapp# cat app.py | more
import os

from flask import Flask

It’s a flask based webapp.
Manually run the app.py and use another terminal for testing it:

root@f19ca7c18763:/opt/webapp# python app.py
 * Running on http://0.0.0.0:5000/
$ sudo docker exec -it f19ca7c18763 /bin/bash
root@f19ca7c18763:/opt/webapp# which curl
/usr/bin/curl
root@f19ca7c18763:/opt/webapp# curl http://127.0.0.1:5000
Hello world!root@f19ca7c18763:/opt/webapp# 

When you use curl, you will see in the first terminal it will indicates the request has been solved.
Or you could directly request the page in host machine, via: curl http://172.17.0.21:5000, the result will be the same.

Expose to World

Randomly let our container map to host’s port via:

$ sudo docker run -d -P --name web training/webapp python app.py
8781cf98cc685ae37a9aa421a9d30f71c64f12fa8fc07b2e1d888f761089e528
$ sudo docker ps -l
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                     NAMES
8781cf98cc68        training/webapp:latest   "python app.py"     6 seconds ago       Up 5 seconds        0.0.0.0:49153->5000/tcp   web                 

Then on Internet, we could directly fetch the HelloWorld now.

~% curl http://1xx.xxx.xx.xxx:49153
Hello world!%          

Inspect the name of the running container:

$ sudo docker inspect -f "{{ .State.StartedAt }}" 8781cf98cc68
2015-01-28T04:25:38.768661692Z
$ sudo docker inspect -f "{{ .State.Pid }}" 8781cf98cc68
7307
$ sudo docker inspect -f "{{ .Name }}" 8781cf98cc68
/web

We got the name, then we could directly read the logs using this name:

$ sudo docker logs -f web
 * Running on http://0.0.0.0:5000/
183.62.15.118 - - [28/Jan/2015 04:27:30] "GET / HTTP/1.1" 200 -
183.62.15.118 - - [28/Jan/2015 06:00:18] "GET / HTTP/1.1" 200 -
183.62.15.118 - - [28/Jan/2015 06:00:24] "GET / HTTP/1.1" 200 -

Using -p for specify the host port and container port mapping:

$ sudo docker run -d -p 5000:5000 --name web1 training/webapp python app.py
2a0692015ba776f7daa957906470178df1fd8d26439422cd4528d2e253bf3331
$ sudo docker ps
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                    NAMES
2a0692015ba7        training/webapp:latest   "python app.py"     3 seconds ago       Up 3 seconds        0.0.0.0:5000->5000/tcp   web1 

The test could be curl the 5000 port of the remote machine, while the logs could be found using -f web1.
Examine the port mapping using following command:

$ sudo docker run -d -P --name web3 training/webapp python app.py
$ sudo docker port web3 5000
0.0.0.0:49154

-p could be added as multiple ports, like:

$ sudo docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py

Docker Container Linking

Pull back a new images and run it as daemon:

$ sudo docker run -d --name db training/postgres
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
training/postgres   latest              258105bea10d        7 months ago        364.5 MB
training/webapp     latest              31fa814ba25a        8 months ago        278.6 MB
$ sudo docker ps 
CONTAINER ID        IMAGE                      COMMAND                CREATED             STATUS              PORTS                     NAMES
ff6603d47552        training/postgres:latest   "su postgres -c '/us   14 seconds ago      Up 14 seconds       5432/tcp                  db                  
f94368f3d091        training/webapp:latest     "python app.py"        9 minutes ago       Up 9 minutes        0.0.0.0:49154->5000/tcp   web3                

Remove the existing web3 container, and create a new one which links to container db:

$ sudo docker rm -f f94368f3d091
f94368f3d091
$ sudo docker run -d -P --name web4 --link db:db training/webapp python app.py
0cf8f0adcb3d1728c61e33c0c9184213478a2a231ba525339a3049534f4ce4ef
$ sudo docker ps
CONTAINER ID        IMAGE                      COMMAND                CREATED             STATUS              PORTS                     NAMES
0cf8f0adcb3d        training/webapp:latest     "python app.py"        4 seconds ago       Up 3 seconds        0.0.0.0:49155->5000/tcp   web4                
ff6603d47552        training/postgres:latest   "su postgres -c '/us   2 minutes ago       Up 2 minutes        5432/tcp                  db  

Examine the link infos when entering the container itself:

$ sudo docker exec -i -t 0cf8f0adcb3d  /bin/bash
root@0cf8f0adcb3d:/opt/webapp# env
HOSTNAME=0cf8f0adcb3d
DB_NAME=/web4/db
DB_PORT_5432_TCP_ADDR=172.17.0.26
DB_PORT=tcp://172.17.0.26:5432
DB_PORT_5432_TCP=tcp://172.17.0.26:5432
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/opt/webapp
DB_PORT_5432_TCP_PORT=5432
SHLVL=1
HOME=/
DB_PORT_5432_TCP_PROTO=tcp
DB_ENV_PG_VERSION=9.3
_=/usr/bin/env


Use ip address show to examine the ip address.
Why they could be linked?
Also when you enter the web machine, cat its /etc/hosts, will see the db named:

root@0cf8f0adcb3d:/opt/webapp# cat /etc/hosts
172.17.0.27	0cf8f0adcb3d
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.26	db

Advance Networking

Secret of DNS/hostname/hosts:

root@0cf8f0adcb3d:/opt/webapp# mount
/dev/vda1 on /etc/resolv.conf type ext4 (rw,relatime,data=ordered)
/dev/vda1 on /etc/hostname type ext4 (rw,relatime,data=ordered)
/dev/vda1 on /etc/hosts type ext4 (rw,relatime,data=ordered)

Once the variables changes the container’s corresponding name will also be changed.

Iptables

Container Visit WAN:
Use sysctl’s ip_forward, check it via:

$ cat /proc//sys/net/ipv4/ip_forward
1

1 means that we could forward our traffic flow from WAN to

WAN visit Container:

$ sudo docker run -d -p 5000:5000 --name web5 training/webapp python app.py
$ sudo iptables -t nat -nL
......
Chain DOCKER (2 references)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:49155 to:172.17.0.27:5000
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:5000 to:172.17.0.28:5000

The last one is added via our run command.

Trying Docker In Company

Installation

Install docker via:

$ sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
$ sh -c "echo deb http://get.docker.io/ubuntu docker main\
> /etc/apt/sources.list.d/docker.list"
$ apt-get update
$ apt-get install lxc-docker
$ which docker
/usr/bin/docker

Very Beginning

Docker pull the docker.cn packages back, the speed is around 500K/

$ docker pull docker.cn/docker/ubuntu

Run into an instance:

# docker run -i -t docker.cn/docker/ubuntu /bin/bash
root@3ad7689e600a:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 06:27 ?        00:00:00 /bin/bash
root        16     1  0 06:27 ?        00:00:00 ps -ef

In another terminal, show the running container:

# docker ps
CONTAINER ID        IMAGE                           COMMAND             CREATED             STATUS              PORTS               NAMES
3ad7689e600a        docker.cn/docker/ubuntu:14.04   "/bin/bash"         11 seconds ago      Up 10 seconds                           sick_hodgkin 

Make Changes And Submit

First made some modification to our container:

sudo apt-get install vim

The above command will install vim.
Now commit the changes:

# docker commit c7ddc390f0c8 installed_vim_container
ed347fc03634e6c66ee45d213cf4d2839e55376f3e34d18c6e58bada1f701425

List all of the images:

# docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
installed_vim_container   latest              ed347fc03634        47 seconds ago      235.8 MB
docker.cn/docker/ubuntu   14.04               b39b81afc8ca        9 days ago          192.7 MB
docker.cn/docker/ubuntu   14.04.1             b39b81afc8ca        9 days ago          192.7 MB
docker.cn/docker/ubuntu   latest              b39b81afc8ca        9 days ago          192.7 MB
docker.cn/docker/ubuntu   trusty              b39b81afc8ca        9 days ago          192.7 MB

Using DO For Building OpenContrail

Since the network environment is not good(In fact, very bad), because of the GFW, so I have to build the opencontrail packages in digitalOcean. Following is the tips and how-to.

Preparation

First we have to get the Latest Ubuntu images, and let it OK for building the OpenContrail:

$ docker search ubuntu
.....
$ docker pull ubuntu
$ docker run -i -t ubuntu /bin/bash
root@4c74f2890dbe:/# apt-get update

Now we run into the ubuntu build environment. This is where we want to build the whole opencontrail deb file.
Install curl and then install repo:

# apt-get install curl
# mkdir -p ~/bin
# curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
# chmod 777 /root/bin/repo
# apt-get install vim
# vim ~/.bashrc
export PATH=/root/bin:$PATH
# source ~/.bashrc
# which repo
/root/bin/repo

Now repo became usable in our system.
Install following packages(So many packages!!!) for preparing the building of the opencontrail:

# apt-get install -y scons git python-lxml wget gcc patch make unzip flex bison g++ libssl-dev autoconf automake libtool pkg-config vim python-dev python-setuptools libprotobuf-dev protobuf-compiler libsnmp-python libboost-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libcurl4-openssl-dev google-mock libgoogle-perftools-dev liblog4cplus-dev libtbb-dev libhttp-parser-dev libxml2-dev libicu-dev

Use tmux for holding the building context:

# apt-get install tmux
# tmux new -s "BuildContrail"

Clone The Code

Create the directories and then configure the git’s username and Email.

# mkdir Code
# cd Code/
#  git config --global user.email kkkttt@gmail.com
# git config --global user.name kkkttt
# ssh-keygen

Upload the generate id_rsa.pub to the github.com, then let your machine verified by github.

# ssh -T git@github.com
Hi kkkttt! You've successfully authenticated, but GitHub does not provide shell access.

Now you could use repo for syncing back the code:

# mkdir -p ~/Code
# cd ~/Code
# repo init -u git@github.com:Juniper/contrail-vnc
# repo sync 

Third-Party

There is little trick in syncing the 3rd party source code back, you have to manually create the folder and let it writable, then modify the source code of the python file:

# mkdir -p /tmp/cache/root/
# chmod -R /tmp/cache/root/
# vim third_party/*.py
_PACKAGE_CACHE='/tmp/cache/' + os.environ['USER'] + '/third_party'
_PACKAGE_CACHE='/tmp/cache/root/' + '/third_party'

Now use following command for syncing the 3rd party packages back:

# python third_party/fetch_packages.py

Build

Building is pretty easy, simply type scons then everything is automatically on-going.
Troubles, if you don’t specify USER, then the error will be raised, complains the os.environ[‘USER’] got nothing, then scons will be halt.
Solution:

# declare -x USER="root"

Then the build begin, and it will last for a long time.

Using New DO System

Since the coreOS met some critical errors, I have to re-construct the DO System using CentOS. So I destroyed the old CoreOS machine, runs CentOS.

Configure

Install packages

Update and install vim

$ yum update
$ yum install vim

Add Swap

512M is not enough for playing, enlarge the swapfile.

# dd if=/dev/zero of=/swapfile bs=1M count=1024
# chmod 600 /swapfile
# mkswap /swapfile
$ sudo vim /etc/systemd/system/swap.service
 [Unit]  
 Description=Turn on swap  
 [Service]  
 Type=oneshot  
 Environment="SWAPFILE=/swapfile"
 RemainAfterExit=true  
 ExecStartPre=/usr/sbin/losetup -f ${SWAPFILE}  
 ExecStart=/usr/bin/sh -c "/sbin/swapon $(/usr/sbin/losetup -j ${SWAPFILE} | /usr/bin/cut -d : -f 1)"  
 ExecStop=/usr/bin/sh -c "/sbin/swapoff $(/usr/sbin/losetup -j ${SWAPFILE} | /usr/bin/cut -d : -f 1)"  
 ExecStopPost=/usr/bin/sh -c "/usr/sbin/losetup -d $(/usr/sbin/losetup -j ${SWAPFILE} | /usr/bin/cut -d : -f 1)"  
 [Install]  
 WantedBy=multi-user.target 
$ sudo  systemctl enable /etc/systemd/system/swap.service  
$ sudo systemctl start swap  

Now the swapfile is 1000MB, enough for doing various operations.

Add new user

Add new user and changes its password:

# useradd -m -g root -G root -s /bin/bash Trusty
# passwd Trusty

Change the sshd configuration, disable root login, and change the listening port.

vim /etc/ssh/sshd_config
port changes, 
PermitRootLogin no

Now reboot the system, you will got a safe DigitalOcean machine.

Build OpenContrail

The repo is the same as the above article, then we install other packages which needed for CengOS.

$ sudo yum install -y libtool kernel-devel 
$ sudo yum install -y bzip2 boost-devel tbb-devel libcurl-devel libxml2-devel 

Install epel via:

$ sudo yum install -y https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
$ sudo sed -i -e 's/enabled=1/enabled=0/' /etc/yum.repos.d/epel.repo 

Install following packages from epel:

$ sudo yum install -y --disablerepo="*" --enablerepo="epel" scons protobuf protobuf-devel protobuf-compiler 
$  sudo yum install -y python-lxml patch unzip flex bison gcc-c++ openssl-devel make wget python-setuptools

So now you could run the whole compilation via scons under the ~/Code folder.
tips: tmux’s q will quit ctrl+b mode.