Monday, March 14, 2016

Docker Container 初探

dockerInstall

Docker Install

最近事情有點多,所以只好中英文交雜著,也懶得管文法了。

只是初探而已,我想我就直接用Ubuntu14.04的Docker,不做升級了。

apt-get update 
apt-get -y install docker.io

測試安裝結果

裝完了,拉個Ubuntu Container檔案看看。 接下來連進這台Container中。

docker pull ubuntu
docker run -i -t ubuntu /bin/bash

An test image

download a webapp from docker hub.

指下載image不啟動Container。

docker pull training/webapp

runing the webapp for testing

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

提取container的5000 port maps to host 80 port. So one can use

curl http://hostip:80

to test it,其中hostip為host的IP。

commit a modified image

You can commit a running container and will not affect the running status(UP).

docker commit -m "Added new webapp" -a "Docker Newbee for webapp" 89f4c0576be3 training/webapp2:v2

where 89xx is id, traning/webapp repository name, and v2 is a TAG.
The default TAG is latest so if you want to run a image with v2 tag, you can use

docker run -d -p 81:5001 training/webapp2:v2 python app1.py

why show Exited

If you have no job running, docker will mark it as Exited(0) while type docker ps -a. You can have a test on it, after 10 sec it will show Exited(0).

docker run --name cont6 ubuntu sleep 10 &

if then command with -t, TTY, it will not show Exited, the status will always show "UP".

docker run -t --name cont6 ubuntu /bin/bash 

Time Namespace Problem

If you are running container with the following commands, changing date is not permission. The admin permission is being limited.

docker run -t --name intermode2 ubuntu

but use the following commands will release the admin permission.

docker run -t --privileged --name intermode2 ubuntu

When you change the date with Date -s " 2000 / 01 / 01 00 : 00 : 00 command in the container.
The host's date will be changed, since kernel not support time namespace.
When disable --privileged will make the user as a guest user and cannot be admin user. Some command also will be disable, such as mount command. If you want to be a admin user, you can not avoid the lack of namespace supported problem.

tty Connection

tty connect to container by using docker command

docker exec -i -t id bash

Docker Link

Docker link 只能發生在同一台Server。

Running db first.

docker run -d --name db training/postgres

Running web then.

docker run -d -P --name web --link db:db training/webapp python app.py

連到web server檢查/etc/hosts發現如下,link只是更改了/etc/hosts/加入了db information。

72.17.0.4      8eb308a6f375
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.3      db a768185b48d7

The most cool thing is:
If the db' IP changed due to DHCP or ..., the /etc/hosts in web server will automatically update.

One can check the detail connection information through:

docker inspect -f "{{ .HostConfig.Links }}" web

It's in the section of HostConfig with variable Links using command docker inspect.

Dockerfile

建立一個目錄放入Dockerfile,名為Dockerfile

# A basic apache server. To use either add or bind mount content under /var/www
FROM ubuntu

MAINTAINER Kimbro Staken version: 0.1

RUN apt-get update && apt-get install -y apache2 && apt-get clean && rm -rf /var/lib/apt/lists/*

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

其中FROM指下載的image位置。
RUN 表示在內部執行的命令,如果image存在,可透過此命令做為init的方法執行啟動程式。發生在build階段。
CMD 表示docker -it ubuntu python webapp.py。其中CMD就是指這段最後的指令。發生在啟動階段。

No init

這是一件很難想像的事情,而大部分的人好似也接受了。官網希望一個Container只跑一個特定的服務。 但我總覺得這會讓事情沒有更容易。這也是個奇想,在任何地方,任何老闆,大概沒有辦法接受有這樣的情況。
這也證明了創意才是重點,那些小問題一點都不重要。 這到目前為止還是個大問題,SIGKILL捕捉的到嗎?sub-process清得乾淨嗎?

s6 seems the best application for solving this problem.

ambassador

這是一個好想法,我應該再往這裡面專研一下。
首先我們先測試一下。

在server1,啟動redis-server and abassador connector to redis-server

docker run -d --name redis redis
docker run -d --link redis:redis --name ambassador1 -p 6379:6379 svendowideit/ambassador

在server2,啟動redis-client and abassador connector to redis-cli

docker run -d --name ambassador2 --expose 6379 -e REDIS_PORT_6379_TCP=tcp://172.16.235.128:6379 svendowideit/ambassador
docker run -d -t  --link ambassador2:redis relateiq/redis-cli

其中,172.16.235.128為server1的IP。

我們進去redis-cli看看

root@7882118ba9aa:/# env
REDIS_PORT_6379_TCP_PROTO=tcp
HOSTNAME=7882118ba9aa
TERM=xterm
REDIS_NAME=/mad_stallman/redis
REDIS_PORT_6379_TCP_ADDR=172.17.0.2
REDIS_PORT_6379_TCP_PORT=6379
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
REDIS_ENV_REDIS_PORT_6379_TCP=tcp://172.16.235.128:6379
REDIS_PORT_6379_TCP=tcp://172.17.0.2:6379
SHLVL=1
HOME=/
REDIS_PORT=tcp://172.17.0.2:6379
_=/usr/bin/env

redis-cli的script為

root@7882118ba9aa:/# cat start.sh
#!/bin/bash

if [ $# -eq 0 ]; then
    /redis/src/redis-cli -h $REDIS_PORT_6379_TCP_ADDR -p $REDIS_PORT_6379_TCP_PORT
else
    /redis/src/redis-cli "$@"
fi

其中REDISPORT6379TCPADDRREDISPORT6379TCPPORT在環境變數中已經設立。 啟動start.sh後執行

root@7882118ba9aa:/# ./start.sh
redis 172.17.0.2:6379> ping
PONG

有反應了。

這裏解釋一下,為何是--link ambassador2:redis。 首先我們看一下envstart.sh間用什麼變數溝通,答案是REDIS_這個prefix。
假設我們用--link ambassador2:ambassador2會怎樣?

root@f0a8b07680bc:/# env
AMBASSADOR2_PORT_6379_TCP=tcp://172.17.0.2:6379
HOSTNAME=f0a8b07680bc
TERM=xterm
AMBASSADOR2_PORT_6379_TCP_PROTO=tcp
AMBASSADOR2_PORT_6379_TCP_PORT=6379
AMBASSADOR2_PORT=tcp://172.17.0.2:6379
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
AMBASSADOR2_NAME=/furious_einstein/ambassador2
AMBASSADOR2_ENV_REDIS_PORT_6379_TCP=tcp://172.16.235.128:6379
SHLVL=1
HOME=/
AMBASSADOR2_PORT_6379_TCP_ADDR=172.17.0.2
_=/usr/bin/env

env被改成AMBASSADOR2的env了,使得,script對應的參數是錯的。

另外也影響了/etc/hosts

root@f0a8b07680bc:/# cat /etc/hosts
172.17.0.10 f0a8b07680bc
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.2  ambassador2 5fb7c99e8b6c

因此link可解讀為--link destination container name:local alias name
local alias name表示source container(啟動的這台)所隱含的參數相對於desination container。

command

list all container
docker ps -a

delete a container 
docker rm id

show all images
docker images

run a container from an image: with -t to keep inteactive, and alway show UP.  
if not contains -t will show Exited(0) while no job running.  
docker run -t  --name intermode ubuntu

to run it on the background
docker run -d rethinkdb

remove an image
docker rmi id

show the detailed container infomation
docker inspect id

trouble shooting

already being pulled by another client. Waiting.

service restart docker

check list of container and see the status that should be shown "UP".

docker start id

No comments:

Post a Comment