Docekr学习笔记四构建并测试web应用程序

  1. 构建Sinatra应用程序创建sinatra工作目录,编写Dockerfile文件构建一个镜像,并利用该镜像生成容器应用。重点我们将讲述如何将多个容器连接形成应用栈。
    $ md sinatra && cd sinatra
    $ vi Dockerfile
    
    FROM ubuntu
    MAINTAINER Kael Wang zb55@foxmail.com
    ENV REFRESHED_AT 2016-12-12
    RUN apt-get update
    RUN apt-get -y install 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"]
    
    $ docker build -t kaelwang/sinatra .
    Sending build context to Docker daemon 10.24 kB
    Step 1 : FROM ubuntu
     ---> 44f18eb3c13f
    Step 2 : MAINTAINER Kael Wang zb55@foxmail.com
     ---> Using cache
     ---> 0230268896a0
    Step 3 : ENV REFRESHED_AT 2016-12-12
     ---> Using cache
     ---> 4aad3f178a57
    Step 4 : RUN apt-get update
     ---> Using cache
     ---> 254a26583566
    Step 5 : RUN apt-get -y install ruby ruby-dev build-essential redis-tools
     ---> Using cache
     ---> 3a0a3f602557
    Step 6 : RUN gem install --no-rdoc --no-ri sinatra json redis
     ---> Using cache
     ---> 933b8b6d6d84
    Step 7 : RUN mkdir -p /opt/webapp
     ---> Using cache
     ---> 710d3db42f72
    Step 8 : EXPOSE 4567
     ---> Using cache
     ---> 01c8718f0607
    Step 9 : CMD /opt/webapp/bin/webapp
     ---> Running in 2acb0e4a3bc3
     ---> d9d3d801d9e1
    Removing intermediate container 2acb0e4a3bc3
    Successfully built d9d3d801d9e1
    
    docker run -d -p 4567 --name webapp -v $PWD/webapp:/opt/webapp kaelwang/sinatra
    19a8e0112a32e93505dcf49d2852f9035d5ecbbf4a3fe960269e78a1187af755
    
    $ docker logs webapp
    [2016-07-27 06:40:04] INFO  WEBrick 1.3.1
    [2016-07-27 06:40:04] INFO  ruby 2.3.1 (2016-04-26) [x86_64-linux-gnu]
    == Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from WEBrick
    [2016-07-27 06:40:04] INFO  WEBrick::HTTPServer#start: pid=1 port=4567
    
    $ docker ps -a
    CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                   PORTS                         NAMES
    19a8e0112a32        kaelwang/sinatra           "/opt/webapp/bin/weba"   5 seconds ago       Up 3 seconds             0.0.0.0:32770->4567/tcp       webapp
    

    目前,我们已经建立了sinatra容器应用,此应用还很基础,指示接受输入参数,并将输入转化为JSON输出。现在,我们用curl命令来测试这个应用程序。

    $ curl -i -H 'Accept:application/json' -d 'name=Foo&status=Bar' http://localhost:32770/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/2.3.1/2016-04-26)
    Date: Wed, 27 Jul 2016 06:46:33 GMT
    Connection: Keep-Alive
    
    {"name":"Foo","status":"Bar"}
    

    我们可以看到,给sinatra应用程序传入了一些参数,并转化为了json散列后输出:{“name”:”Foo”,”status”:”Bar”}成功。

    我们添加一个服务,这个服务运行在另一个容器里,把当前的示例应用程序扩展为真正的应用栈。

  2. 构建Redis镜像和容器扩展sinatra应用程序,加入Redis后端数据库,并在Redis数据库中存储输入的参数。为了达到这个目的,要构建全新的镜像和容器运行redis数据库。之后,利用Docker的特性来关联两个容器。
    $ md redisdocker&&cd redisdocker
    $ vi Dockerfile
    
    FROM ubuntu
    MAINTAINER Kael Wang zb55@foxmail.com
    ENV REFRESHED_AT 2016-12-12
    RUN apt-get update
    RUN apt-get -y isntall redis-server redis-tools
    EXPOSE 6379
    ENTRYPOINT ["/usr/bin/redis-server"]
    CMD []
    
    $ docker build -t kaelwang/redis .
    Sending build context to Docker daemon 2.048 kB
    Step 1 : FROM ubuntu
     ---> 44f18eb3c13f
    Step 2 : MAINTAINER Kael Wang zb55@foxmail.com
     ---> Using cache
     ---> 0230268896a0
    Step 3 : ENV REFRESHED_AT 2016-12-12
     ---> Using cache
     ---> 4aad3f178a57
    Step 4 : RUN apt-get update
     ---> Using cache
     ---> 254a26583566
    Step 5 : RUN apt-get -y install redis-server redis-tools
     ---> Using cache
     ---> d0cf8437fb46
    Step 6 : EXPOSE 6379
     ---> Using cache
     ---> 7a8d1aa862b4
    Step 7 : ENTRYPOINT /usr/bin/redis-server
     ---> Running in c0ce2aeb9eda
     ---> dd4f375c2236
    Removing intermediate container c0ce2aeb9eda
    Step 8 : CMD 
     ---> Running in a386c0559e6c
     ---> e730c0e265d3
    Removing intermediate container a386c0559e6c
    Successfully built e730c0e265d3
    

    从这个镜像构建容器

    $ docker run -d -p 6379 --name redis kaelwang/redis
    6fdcfc399370872475d654563c24c54c3c9a1c67806a2d7eee7a2eaea8175269
    
    $ docker port redis
    6379/tcp -> 0.0.0.0:32771
    

    我们用本机redis测试一下容器里的redis服务是否工作

    $ redis-cli  -h 127.0.0.1 -p 32771
    127.0.0.1:32771> 
    
  3. Docker容器网络知识现在来更新sinatra应用程序,让其连接到redis并存储传入的参数。为此,需要能够与redis服务器对话,要做到这一点,可以有几种方法。第一种涉及Docker自己的网络栈。到目前为止,我们看到的Docker容器都是公开端口并绑定到本地网络接口的,这样可以吧容器里的服务在本地 Docker宿主机所在的外部网络上公开,除了这样方法,Docker这个特性还有种内部网络。在安装Docker时,会创建一个新的网络接口,名字是 docker0.每个Docker容器都会在这个接口上分配一个ip地址。
    $ ip a show docker0
    3: docker0: <broadcast,multicast,up,lower_up> mtu 9001 qdisc noqueue state UP group default 
        link/ether 02:42:3e:8e:ae:4d 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:3eff:fe8e:ae4d/64 scope link 
           valid_lft forever preferred_lft forever
    

    docker0是一个虚拟的以太网桥,用于连接容器和本地宿主机。docker0复合RFC1918的私有ip地址,范围是172.16.x.x到172.30.x.x同时Docker网络必须还要依赖防火墙和NAT规则才能允许被建立连接

    $ iptables -t nat -L -n
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination         
    DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
    
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
    
    Chain POSTROUTING (policy ACCEPT)
    target     prot opt source               destination         
    MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           
    MASQUERADE  tcp  --  172.17.0.3           172.17.0.3           tcp dpt:80
    MASQUERADE  tcp  --  172.17.0.4           172.17.0.4           tcp dpt:4567
    MASQUERADE  tcp  --  172.17.0.5           172.17.0.5           tcp dpt:6379
    
    Chain DOCKER (2 references)
    target     prot opt source               destination         
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.3:80
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32770 to:172.17.0.4:4567
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:32771 to:172.17.0.5:6379
    

    容器默认是无法访问的,从宿主网络与容器通信时,必须明确指定打开的端口,下面我们以DNAT即目标NAT这个规则为例,这个规则吧容器里的访问路由到Docker宿主机的32771端口。

  4. 通过Docker内网连接Redis
    $ docker inspect redis
    	.
    	.
    	.
        "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "b4bb7703aa7d658f8309abbfcdf7fe575ac5faa3546805e33dc44be86e3932cb",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Ports": {
            "6379/tcp": [
                {
                    "HostIp": "0.0.0.0",
                    "HostPort": "32771"
                }
            ]
        },
        "SandboxKey": "/var/run/docker/netns/b4bb7703aa7d",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "8e96a4e055c46a34331f3ae3b3c455ecdcddb6a16b2650fe53cdb638127e5255",
        "Gateway": "172.17.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.5",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "MacAddress": "02:42:ac:11:00:05",
        "Networks": {
            "bridge": {
                "EndpointID": "8e96a4e055c46a34331f3ae3b3c455ecdcddb6a16b2650fe53cdb638127e5255",
                "Gateway": "172.17.0.1",
                "IPAddress": "172.17.0.5",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "MacAddress": "02:42:ac:11:00:05"
            }
        }
    	.
    	.
    	.
    

    docker inspect命令展示Docker容器的细节,这里只显示网络信息。容器的ip地址为172.17.0.5,并使用网关172.17.0.1即 docker0。也可以看到容器6379端口被映射到本地宿主机32771端口。只是,因为运行在本地Docker宿主机上,所以不是一定要用映射的端 口,也可以直接使用Docker0分配的内网地址

    $ redis-cli  -h 172.17.0.5
    172.17.0.5:6379> 
    

    但是,通过这种方法连接两个容器,有两个大问题,第一,要在应用内对redis容器的ip地址做硬编程,第二,如果重启或容器意外中断后恢复,Docker会改变容器的ip地址。

  5. 引用容器名字让两个容器相连首先删掉原来我们构建的Sinatra和redis容器,然后重新构建一个新的Sinatra和redis容器
    $ docker stop redis sinatra
    $ docker rm redis sinatra
    

    实现连接

    $ docker run -d --name redis kaelwang/redis
    a843b4e5adaa3630a08ebdbe8828a6028fbf6331ba537f082f4484dff8a6b27b
    
    $ docker run -p 4567 --name webapp --link redis:db -t -i -v $PWD/webapp:/opt/webapp kaelwang/sinatra /bin/bash
    root@d205ff072682:/# cat /etc/hosts
    172.17.0.4      d205ff072682
    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.5      db a843b4e5adaa redis
    
    root@d205ff072682:/# env
    HOSTNAME=d205ff072682
    DB_NAME=/webapp/db
    DB_PORT_6379_TCP_PORT=6379
    TERM=xterm
    DB_PORT=tcp://172.17.0.5:6379
    DB_PORT_6379_TCP=tcp://172.17.0.5:6379
    LS_COLORS=rs=0:di=01;34:ln=01;...(此处信息较多省略)
    DB_ENV_REFRESHED_AT=2016-12-12
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    REFRESHED_AT=2016-12-12
    PWD=/
    DB_PORT_6379_TCP_ADDR=172.17.0.5
    DB_PORT_6379_TCP_PROTO=tcp
    SHLVL=1
    HOME=/root
    _=/usr/bin/env
    root@d205ff072682:/# 
    

    –link标志创建了两个容器间的父子相连,这个标志需要两个参数,一个是要连接的容器名字,另一个是连接后容器的别名。此处别名是db,别名让 我们可以访问公开的信息,而无需关注底层容器的名字,连接让父容器有能力访问子容器,并且把子容器的一些连接细节分享给父容器。这些细节有助于配置应用程 序并使用这个连接。

    连接也能得到一些安全上的额好处。启动redis容器时,并没有使用-p标志公开redis的端口。通过父容器直接访问任意子容器的公开端口。且只 有使用的–link标志连接到这个容器的容器才能连接到这个端口,容器的端口不需要对本地宿主机公开,现在我们已经拥有了一个非常安全的模型,在这个模 型里,容器话的应用程序限制了可被攻击的界面,减少了公开暴露的网络。也可以吧多个容器连接到一起,比如一个redis示例服务于多个web应用服务器。 出于一些原因,我们可以在启动Docker守护进程时加上–icc=false标志,关闭所有没有连接的容器间的通讯,这样强制Docker只允许有连 接的容器之间相互通信。

    我们通过env查看环境变量发现有一些以别名DB开头的,Docker在连接webapp和redis容器时,自动创建了这些以DB开头的环境变量。 这些自动创建的环境变量包含以下信息。

    • 子容器的名字
    • 容器里运行的服务所使用的协议,ip和端口
    • 容器里运行的不同的服务所指定的协议,ip和端口
    • 容器里由Docker设置的环境变量的值。
  6. 使用容器连接来通信
    1. 使用环境变量里的一些连接信息。
    2. 使用DNS和/etc/hosts信息。

    应用程序会在本地查找名叫db的主机,找到/etc/hosts文件里的项解析到正确的ip地址,这也解决了硬编码IP地址的问题,因为hosts文件会随着你的Docker启动时自动更新相应信息。

    这个web应用程序栈由以下几部分组成

    • 一个运行Sinatra和web服务器容器
    • 一个Redis数据库容器
    • 两个容器间的一个安全连接

    这样就可以在本地环境构建,复制,迭代开发用于生产的应用程序,甚至很多复杂的多层应用程序。

分类: Docker

77 条评论

https://pzfs.eu · 2026-09-02 12:51

References:

Australian on line pokies https://pzfs.eu

福利视频 · 2026-09-08 17:44

Excellent website. A llot oof helppful information here. I amm sendcing it too
a few buddies anns additionzlly sharing iin delicious. And obviously, thanks in yolur effort!
xnxx

dmgameloginbet · 2026-09-13 12:40

Logged into dmgameloginbet last night and had a blast! The games are actually pretty fun and the site’s pretty user-friendly. Good way to kill some time. Log in here: dmgameloginbet

pbase.com · 2026-09-22 03:27

References:

Casino mit sofort erfahrungen pbase.com

Neue Online Casinos mit Sofort · 2026-09-22 06:11

References:

Sofort Casino Vergleich Neue Online Casinos mit Sofort

https://pad.funkwhale.audio/ · 2026-09-22 21:19

References:

Casino mit sofortiger auszahlung https://pad.funkwhale.audio/

https://comsenz-service.com/?182553 · 2026-09-23 02:25

References:

Online casino schnelle auszahlung sofort
https://comsenz-service.com/?182553

http://bbs.wuhudj.com · 2026-09-23 03:45

References:

Klarna sofortüberweisung casino http://bbs.wuhudj.com

casino ohne limit sofortüberweisung · 2026-09-23 03:46

References:

Online casino mit sofortüberweisung einzahlung http://www.lezcc.com/?618842

http://www.jzq5.cn/ · 2026-09-23 05:23

References:

Instant withdrawal payid pokies http://www.jzq5.cn/space-uid-458864.html

http://www.qilurexian.net/?241572 · 2026-09-23 06:53

References:

Online casino sofortüberweisung test http://www.qilurexian.net/?241572

sofort online casino · 2026-09-23 15:48

References:

Legale sofort casinos deutschland http://bbs.51pinzhi.cn/home.php?mod=space&uid=8376266

online pokies payid australia · 2026-09-25 23:10

References:

How to play pokies with payid https://hedgedoc.envs.net/ZPCDvPMlSf211s3EH1-nyA

best payid pokies sites · 2026-09-26 03:19

References:

Play pokies with payid https://md.interhacker.space/eQS66o2OSyGnoJhbcNadbQ

pbase.com · 2026-09-28 23:14

References:

How to play pokies with payid https://pbase.com/targetvinyl41/

md.coredump.ch · 2026-09-29 15:07

References:

Anonymous payid pokies https://md.coredump.ch/oGq7urokSxiqqC95vaBQMg

payid online pokies · 2026-09-29 15:39

References:

Payid pokies free spins https://docs.monadical.com/m1Ai9e_oSmuRHxIeJ7ktcw

bandori.party · 2026-09-29 21:48

References:

Payid pokies no deposit bonus https://bandori.party/user/1770827/lierdew87/

online pokies that accept payid · 2026-09-30 06:38

References:

Fast payout payid pokies https://www.akaguide.com/user/greasecat69

bbs.ybk001.com · 2026-09-30 18:28

References:

No deposit payid pokies australia https://bbs.ybk001.com/home.php?mod=space&uid=611393

https://iskustva.net · 2026-09-30 23:26

References:

Pokies with payid deposit https://iskustva.net/user/radarspace3

forum.issabel.org · 2026-10-01 03:22

References:

Pokies sites that take payid https://forum.issabel.org/u/cubandream64

payid deposit online pokies · 2026-10-02 00:58

References:

No verification payid pokies australia http://bbs.wuhudj.com/space-uid-1769246.html

top neosurf casinos australia · 2026-10-04 00:53

References:

Neosurf online pokies australia real money http://qiaoxiaojun.vip/home.php?mod=space&uid=2668510

http://mashspec.ru/ · 2026-10-04 05:02

References:

Neosurf casino tips australia http://mashspec.ru/user/fanwarm4/

https://codimd.syssec.org/ · 2026-10-04 05:51

References:

$1 minimum deposit casino neosurf australia https://codimd.syssec.org/8r0EoRtjRWezytT0bg1O5Q

http://www.lezcc.com · 2026-10-04 07:53

References:

Neosurf casino welcome bonus http://www.lezcc.com/?610361

https://undrtone.com/ · 2026-10-04 08:12

References:

Trusted payid pokies australia https://undrtone.com/taiwandesign67

anonymous payid pokies · 2026-10-04 08:42

References:

Bonus pokies payid http://bbs.wuhudj.com/space-uid-1770076.html

neosurf no deposit bonus australia · 2026-10-04 14:31

References:

Neosurf casino sites accepting australian players https://xn—-7sbarohhk4a0dxb3c.xn--p1ai/user/whalesquid8/

https://hedgedoc.uni-ak.ac.at/U74eTZdXQs6bp59E_Ov3YA · 2026-10-05 03:01

References:

How to deposit with neosurf at online casinos https://hedgedoc.uni-ak.ac.at/U74eTZdXQs6bp59E_Ov3YA

md.coredump.ch · 2026-10-06 00:38

References:

Neosurf voucher online casino australia https://md.coredump.ch/qJfbdX1ERvWg-N2K9LTOJQ

neosurf reload casino australia · 2026-10-06 04:57

References:

Neosurf casino fees australia http://www.sg588.tw/home.php?mod=space&uid=1296880

http://asresin.cn · 2026-10-06 05:08

References:

Neosurf prepaid voucher casino australia http://asresin.cn/home.php?mod=space&uid=1259908

neosurf casino australia review · 2026-10-06 05:29

References:

$5 minimum deposit casino neosurf australia http://www.seafishzone.com/home.php?mod=space&uid=3270125

https://text.fraction.jp · 2026-10-06 05:42

References:

Best neosurf casinos australia https://text.fraction.jp/jBh0nnWqT0acSH4J9roHLA

http://forum.djwx.com/ · 2026-10-06 05:49

References:

Play pokies with neosurf http://forum.djwx.com/home.php?mod=space&uid=57857

http://t.044300.net/ · 2026-10-06 11:19

References:

Neosurf no verification casino australia http://t.044300.net/home.php?mod=space&uid=3142654

www.vamudhumeni.org · 2026-10-06 13:19

References:

How to use neosurf at casino australia https://www.vamudhumeni.org/forums/users/maracaday33/

发表回复

Avatar placeholder

您的邮箱地址不会被公开。 必填项已用 * 标注