dockerUseWebApp - juedaiyuer/researchNote GitHub Wiki

#Docker构建并测试Web应用程序#

##Dockerfile##

FROM ubuntu:14.04
MAINTAINER juedaiyuer "[email protected]"
ENV REFRESHED_AT 2016-07-10

RUN apt-get update
RUN apt-get install -y ruby ruby-dev build-essential redis-tools
RUN gem install --no-rdoc --no-ri sinatra json redis

RUN mkdir -p /opt/webapp

EXPOSE 4567

CMD [ "/opt/webapp/bin/webapp" ]


#构建新的sinatra镜像
$ sudo docker build -t juedaiyuer/sinatra .


gem install json 
ERROR:  Error installing json:
json requires Ruby version ~> 2.0.

##创建Sinatra容器##

#sinatra web应用程序的源代码---sinatra/webapp/bin lib

#确保webapp/bin/webapp可以执行

#启动第一个sinatra容器
#没有在命令行中指定命令,而是在dockerfile中的CMD指定
$ sudo docker run -d -p 4567 --name webapp -v $PWD/webapp:/opt/webapp juedaiyuer/sinatra

#查看执行的命令都输出了什么
$ sudo docker logs webapp

#类似于tail -f
$ sudo docker logs -f webapp

#列出sinatra进程
$ sudo docker top webapp

#检查sinatra的端口映射
$ sudo docker port webapp 4567


#测试Sinatra应用程序
$ curl -i -H 'Accept:application/json' -d 'name=Foo&status=Bar' http://localhost:32773/json
HTTP/1.1 200 OK 
Content-Type: text/html;charset=utf-8
Content-Length: 29
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-11-22)
Date: Mon, 11 Jul 2016 02:29:19 GMT
Connection: Keep-Alive

{"name":"Foo","status":"Bar"}

##构建Redis镜像和容器##

FROM ubuntu:14.04
MAINTAINER juedaiyuer "[email protected]"
ENV REFRESHED_AT 2016-07-10
RUN apt-get update
RUN apt-get -y install redis-server redis-tools
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
CMD []

$ sudo docker build -t juedaiyuer/reids .

$ sudo docker run -d -p 6379 --name redis juedaiyuer/redis 

#查看端口
$ sudo docker port redis 6379

#本地安装Redis客户端测试,客户端程序一般在redis-tools
$ sudo apt-get -y install redis-tools
#测试连接到Redis服务器
$ sudo redis-cli -h 127.0.0.1 -p 32768
127.0.0.1:32768> 

##两容器的连接##

更新Sinatra应用程序,让其连接到Redis并存储传入的参数,需要与Redis服务器对话

###Docker网络栈-内部网络###

安装docker时,会创建一个新的网络接口,叫docker0;每个容器都会在这个接口上分配一个IP地址

$ ip a show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
	link/ether 02:42:66:f4:4d:54 brd ff:ff:ff:ff:ff:ff
	inet 172.17.0.1/16 scope global docker0
	   valid_lft forever preferred_lft forever
	inet6 fe80::42:66ff:fef4:4d54/64 scope link 
	   valid_lft forever preferred_lft forever
  • docker0接口符合RFC1918的私有IP地址,范围是172.16~172.30

  • 接口本身的地址127.17.42.1,即这个Docker网络的网关地址

  • 默认172.17.x.x作为子网地址,如果被占用,会尝试其它范围

  • 虚拟的以太网桥,用于连接容器和本地宿主网络

    #容器里内的eth0接口 $ sudo docker run -t -i ubuntu /bin/bash root@d74391e80f73:/# ip a show eth0 11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft foreve

    inet 172.17.0.2

    #容器内跟踪对外通信的路由 root@d74391e80f73:/# apt-get -yqq update && apt-get install -yqq traceroute root@d74391e80f73:/# traceroute google.com traceroute to google.com (37.61.54.158), 30 hops max, 60 byte packets 1 172.17.0.1 (172.17.0.1) 0.074 ms 0.038 ms 0.040 ms

###配置建立连接###

#Docker的iptables和NAT配置

##连接Redis##

#查看Redis容器的网络配置
$ sudo docker inspect redis

"NetworkSettings": {
    "Bridge": "",
    "SandboxID": "41329028a8fffcc4f5c46f22e4f3c9453afcd37aa54dd7ae1a138b246e2ec447",
    "HairpinMode": false,
    "LinkLocalIPv6Address": "",
    "LinkLocalIPv6PrefixLen": 0,
    "Ports": {
        "6379/tcp": [
            {
                "HostIp": "0.0.0.0",
                "HostPort": "32768"
            }
        ]
    },

...

#查看Redis容器的IP地址
$ sudo docker inspect -f '{{ .NetworkSettings.IPAddress }}' redis
172.17.0.2

$ redis-cli -h 172.17.0.2
172.17.0.2:6379> 
  1. 要在应用程序里对Redis容器的IP地址做硬编码
  2. 重启容器,Docker会改变容器的IP地址

##让Docker容器互连##

#启动另一个Redis容器
#测试前,需要删除重名容器
$ sudo docker run -d --name juedaiyuer/redis

#连接Redis容器
$ sudo docker run -p 4567 --name webapp --link redis:db -t -i -v $PWD/webapp:/opt/webapp juedaiyuer/sinatra /bin/bash

#查看连接信息
root@08d78050e896:/# cat /etc/hosts
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	db f1c6804d67e9 redis
172.17.0.3	08d78050e896

#显示用于连接的环境变量
root@08d78050e896:/# env
HOSTNAME=08d78050e896
DB_NAME=/webapp/db
DB_PORT_6379_TCP_PORT=6379
TERM=xterm
DB_PORT=tcp://172.17.0.2:6379
DB_PORT_6379_TCP=tcp://172.17.0.2:6379

...

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
REFRESHED_AT=2016-07-10
PWD=/
DB_PORT_6379_TCP_ADDR=172.17.0.2
DB_PORT_6379_TCP_PROTO=tcp
SHLVL=1
HOME=/root
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env


#通过环境变量建立到Redis的连接
#web应用程序的lib/app.rb
require "rubygems"
require "sinatra"
require "json"

class App < Sinatra::Application

  set :bind, '0.0.0.0'

  get '/' do
	"<h1>DockerBook Test Sinatra app</h1>"
  end

  post '/json/?' do
	params.to_json
  end

end

#使用本地DNS

#启动支持Redis的Sinatra应用程序
root@08d78050e896:~# nohup /opt/webapp/bin/webapp &
[1] 30
root@08d78050e896:~# nohup: ignoring input and appending output to 'nohup.out'

#测试支持Redis的Sinatra应用程序
$ curl -i -H 'Accept:application/json' -d 'name=Foo&status=Bar' http://localhost:32777/json
HTTP/1.1 200 OK 
Content-Type: text/html;charset=utf-8
Content-Length: 29
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-11-22)
Date: Mon, 11 Jul 2016 06:58:15 GMT
Connection: Keep-Alive
{"name":"Foo","status":"Bar"}

#确认Redis存储了相关数据
⚠️ **GitHub.com Fallback** ⚠️